summaryrefslogtreecommitdiffstats
path: root/mobile/android/thirdparty/org
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/thirdparty/org')
-rw-r--r--mobile/android/thirdparty/org/json/simple/ItemList.java147
-rw-r--r--mobile/android/thirdparty/org/json/simple/JSONArray.java107
-rw-r--r--mobile/android/thirdparty/org/json/simple/JSONAware.java12
-rw-r--r--mobile/android/thirdparty/org/json/simple/JSONObject.java129
-rw-r--r--mobile/android/thirdparty/org/json/simple/JSONStreamAware.java15
-rw-r--r--mobile/android/thirdparty/org/json/simple/JSONValue.java272
-rw-r--r--mobile/android/thirdparty/org/json/simple/LICENSE.txt202
-rw-r--r--mobile/android/thirdparty/org/json/simple/parser/ContainerFactory.java23
-rw-r--r--mobile/android/thirdparty/org/json/simple/parser/ContentHandler.java110
-rw-r--r--mobile/android/thirdparty/org/json/simple/parser/JSONParser.java533
-rw-r--r--mobile/android/thirdparty/org/json/simple/parser/ParseException.java96
-rw-r--r--mobile/android/thirdparty/org/json/simple/parser/Yylex.java688
-rw-r--r--mobile/android/thirdparty/org/json/simple/parser/Yytoken.java58
-rw-r--r--mobile/android/thirdparty/org/lucasr/dspec/DesignSpec.java645
-rw-r--r--mobile/android/thirdparty/org/lucasr/dspec/RawResource.java60
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/BinaryDecoder.java43
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/BinaryEncoder.java43
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/CharEncoding.java127
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/Decoder.java56
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/DecoderException.java90
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/Encoder.java47
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/EncoderException.java91
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringDecoder.java41
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringEncoder.java41
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringEncoderComparator.java87
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32.java471
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32InputStream.java85
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32OutputStream.java85
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64.java756
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64InputStream.java89
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64OutputStream.java89
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodec.java445
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodecInputStream.java132
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodecOutputStream.java142
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BinaryCodec.java297
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Hex.java302
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/StringUtils.java287
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/package.html21
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/digest/DigestUtils.java583
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/digest/package.html21
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/AbstractCaverphone.java78
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone.java104
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone1.java126
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone2.java129
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/ColognePhonetic.java417
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/DoubleMetaphone.java1106
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Metaphone.java408
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/RefinedSoundex.java203
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Soundex.java279
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/SoundexUtils.java124
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/package.html21
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/BCodec.java209
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/QCodec.java312
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/QuotedPrintableCodec.java388
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/RFC1522Codec.java179
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/URLCodec.java362
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/Utils.java50
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/package.html23
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/overview.html29
-rw-r--r--mobile/android/thirdparty/org/mozilla/apache/commons/codec/package.html100
60 files changed, 12215 insertions, 0 deletions
diff --git a/mobile/android/thirdparty/org/json/simple/ItemList.java b/mobile/android/thirdparty/org/json/simple/ItemList.java
new file mode 100644
index 000000000..07231e673
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/ItemList.java
@@ -0,0 +1,147 @@
+/*
+ * $Id: ItemList.java,v 1.1 2006/04/15 14:10:48 platform Exp $
+ * Created on 2006-3-24
+ */
+package org.json.simple;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * |a:b:c| => |a|,|b|,|c|
+ * |:| => ||,||
+ * |a:| => |a|,||
+ * @author FangYidong<fangyidong@yahoo.com.cn>
+ */
+public class ItemList {
+ private String sp=",";
+ List items=new ArrayList();
+
+
+ public ItemList(){}
+
+
+ public ItemList(String s){
+ this.split(s,sp,items);
+ }
+
+ public ItemList(String s,String sp){
+ this.sp=s;
+ this.split(s,sp,items);
+ }
+
+ public ItemList(String s,String sp,boolean isMultiToken){
+ split(s,sp,items,isMultiToken);
+ }
+
+ public List getItems(){
+ return this.items;
+ }
+
+ public String[] getArray(){
+ return (String[])this.items.toArray();
+ }
+
+ public void split(String s,String sp,List append,boolean isMultiToken){
+ if(s==null || sp==null)
+ return;
+ if(isMultiToken){
+ StringTokenizer tokens=new StringTokenizer(s,sp);
+ while(tokens.hasMoreTokens()){
+ append.add(tokens.nextToken().trim());
+ }
+ }
+ else{
+ this.split(s,sp,append);
+ }
+ }
+
+ public void split(String s,String sp,List append){
+ if(s==null || sp==null)
+ return;
+ int pos=0;
+ int prevPos=0;
+ do{
+ prevPos=pos;
+ pos=s.indexOf(sp,pos);
+ if(pos==-1)
+ break;
+ append.add(s.substring(prevPos,pos).trim());
+ pos+=sp.length();
+ }while(pos!=-1);
+ append.add(s.substring(prevPos).trim());
+ }
+
+ public void setSP(String sp){
+ this.sp=sp;
+ }
+
+ public void add(int i,String item){
+ if(item==null)
+ return;
+ items.add(i,item.trim());
+ }
+
+ public void add(String item){
+ if(item==null)
+ return;
+ items.add(item.trim());
+ }
+
+ public void addAll(ItemList list){
+ items.addAll(list.items);
+ }
+
+ public void addAll(String s){
+ this.split(s,sp,items);
+ }
+
+ public void addAll(String s,String sp){
+ this.split(s,sp,items);
+ }
+
+ public void addAll(String s,String sp,boolean isMultiToken){
+ this.split(s,sp,items,isMultiToken);
+ }
+
+ /**
+ * @param i 0-based
+ * @return
+ */
+ public String get(int i){
+ return (String)items.get(i);
+ }
+
+ public int size(){
+ return items.size();
+ }
+
+ public String toString(){
+ return toString(sp);
+ }
+
+ public String toString(String sp){
+ StringBuffer sb=new StringBuffer();
+
+ for(int i=0;i<items.size();i++){
+ if(i==0)
+ sb.append(items.get(i));
+ else{
+ sb.append(sp);
+ sb.append(items.get(i));
+ }
+ }
+ return sb.toString();
+
+ }
+
+ public void clear(){
+ items.clear();
+ }
+
+ public void reset(){
+ sp=",";
+ items.clear();
+ }
+}
diff --git a/mobile/android/thirdparty/org/json/simple/JSONArray.java b/mobile/android/thirdparty/org/json/simple/JSONArray.java
new file mode 100644
index 000000000..57167f482
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/JSONArray.java
@@ -0,0 +1,107 @@
+/*
+ * $Id: JSONArray.java,v 1.1 2006/04/15 14:10:48 platform Exp $
+ * Created on 2006-4-10
+ */
+package org.json.simple;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+/**
+ * A JSON array. JSONObject supports java.util.List interface.
+ *
+ * @author FangYidong<fangyidong@yahoo.com.cn>
+ */
+public class JSONArray extends ArrayList implements List, JSONAware, JSONStreamAware {
+ private static final long serialVersionUID = 3957988303675231981L;
+
+ /**
+ * Encode a list into JSON text and write it to out.
+ * If this list is also a JSONStreamAware or a JSONAware, JSONStreamAware and JSONAware specific behaviours will be ignored at this top level.
+ *
+ * @see org.json.simple.JSONValue#writeJSONString(Object, Writer)
+ *
+ * @param list
+ * @param out
+ */
+ public static void writeJSONString(List list, Writer out) throws IOException{
+ if(list == null){
+ out.write("null");
+ return;
+ }
+
+ boolean first = true;
+ Iterator iter=list.iterator();
+
+ out.write('[');
+ while(iter.hasNext()){
+ if(first)
+ first = false;
+ else
+ out.write(',');
+
+ Object value=iter.next();
+ if(value == null){
+ out.write("null");
+ continue;
+ }
+
+ JSONValue.writeJSONString(value, out);
+ }
+ out.write(']');
+ }
+
+ public void writeJSONString(Writer out) throws IOException{
+ writeJSONString(this, out);
+ }
+
+ /**
+ * Convert a list to JSON text. The result is a JSON array.
+ * If this list is also a JSONAware, JSONAware specific behaviours will be omitted at this top level.
+ *
+ * @see org.json.simple.JSONValue#toJSONString(Object)
+ *
+ * @param list
+ * @return JSON text, or "null" if list is null.
+ */
+ public static String toJSONString(List list){
+ if(list == null)
+ return "null";
+
+ boolean first = true;
+ StringBuffer sb = new StringBuffer();
+ Iterator iter=list.iterator();
+
+ sb.append('[');
+ while(iter.hasNext()){
+ if(first)
+ first = false;
+ else
+ sb.append(',');
+
+ Object value=iter.next();
+ if(value == null){
+ sb.append("null");
+ continue;
+ }
+ sb.append(JSONValue.toJSONString(value));
+ }
+ sb.append(']');
+ return sb.toString();
+ }
+
+ public String toJSONString(){
+ return toJSONString(this);
+ }
+
+ public String toString() {
+ return toJSONString();
+ }
+
+
+
+}
diff --git a/mobile/android/thirdparty/org/json/simple/JSONAware.java b/mobile/android/thirdparty/org/json/simple/JSONAware.java
new file mode 100644
index 000000000..89f152510
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/JSONAware.java
@@ -0,0 +1,12 @@
+package org.json.simple;
+
+/**
+ * Beans that support customized output of JSON text shall implement this interface.
+ * @author FangYidong<fangyidong@yahoo.com.cn>
+ */
+public interface JSONAware {
+ /**
+ * @return JSON text
+ */
+ String toJSONString();
+}
diff --git a/mobile/android/thirdparty/org/json/simple/JSONObject.java b/mobile/android/thirdparty/org/json/simple/JSONObject.java
new file mode 100644
index 000000000..d4401e114
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/JSONObject.java
@@ -0,0 +1,129 @@
+/*
+ * $Id: JSONObject.java,v 1.1 2006/04/15 14:10:48 platform Exp $
+ * Created on 2006-4-10
+ */
+package org.json.simple;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * A JSON object. Key value pairs are unordered. JSONObject supports java.util.Map interface.
+ *
+ * @author FangYidong<fangyidong@yahoo.com.cn>
+ */
+public class JSONObject extends HashMap implements Map, JSONAware, JSONStreamAware{
+ private static final long serialVersionUID = -503443796854799292L;
+
+ /**
+ * Encode a map into JSON text and write it to out.
+ * If this map is also a JSONAware or JSONStreamAware, JSONAware or JSONStreamAware specific behaviours will be ignored at this top level.
+ *
+ * @see org.json.simple.JSONValue#writeJSONString(Object, Writer)
+ *
+ * @param map
+ * @param out
+ */
+ public static void writeJSONString(Map map, Writer out) throws IOException {
+ if(map == null){
+ out.write("null");
+ return;
+ }
+
+ boolean first = true;
+ Iterator iter=map.entrySet().iterator();
+
+ out.write('{');
+ while(iter.hasNext()){
+ if(first)
+ first = false;
+ else
+ out.write(',');
+ Map.Entry entry=(Map.Entry)iter.next();
+ out.write('\"');
+ out.write(escape(String.valueOf(entry.getKey())));
+ out.write('\"');
+ out.write(':');
+ JSONValue.writeJSONString(entry.getValue(), out);
+ }
+ out.write('}');
+ }
+
+ public void writeJSONString(Writer out) throws IOException{
+ writeJSONString(this, out);
+ }
+
+ /**
+ * Convert a map to JSON text. The result is a JSON object.
+ * If this map is also a JSONAware, JSONAware specific behaviours will be omitted at this top level.
+ *
+ * @see org.json.simple.JSONValue#toJSONString(Object)
+ *
+ * @param map
+ * @return JSON text, or "null" if map is null.
+ */
+ public static String toJSONString(Map map){
+ if(map == null)
+ return "null";
+
+ StringBuffer sb = new StringBuffer();
+ boolean first = true;
+ Iterator iter=map.entrySet().iterator();
+
+ sb.append('{');
+ while(iter.hasNext()){
+ if(first)
+ first = false;
+ else
+ sb.append(',');
+
+ Map.Entry entry=(Map.Entry)iter.next();
+ toJSONString(String.valueOf(entry.getKey()),entry.getValue(), sb);
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+
+ public String toJSONString(){
+ return toJSONString(this);
+ }
+
+ private static String toJSONString(String key,Object value, StringBuffer sb){
+ sb.append('\"');
+ if(key == null)
+ sb.append("null");
+ else
+ JSONValue.escape(key, sb);
+ sb.append('\"').append(':');
+
+ sb.append(JSONValue.toJSONString(value));
+
+ return sb.toString();
+ }
+
+ public String toString(){
+ return toJSONString();
+ }
+
+ public static String toString(String key,Object value){
+ StringBuffer sb = new StringBuffer();
+ toJSONString(key, value, sb);
+ return sb.toString();
+ }
+
+ /**
+ * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F).
+ * It's the same as JSONValue.escape() only for compatibility here.
+ *
+ * @see org.json.simple.JSONValue#escape(String)
+ *
+ * @param s
+ * @return
+ */
+ public static String escape(String s){
+ return JSONValue.escape(s);
+ }
+}
diff --git a/mobile/android/thirdparty/org/json/simple/JSONStreamAware.java b/mobile/android/thirdparty/org/json/simple/JSONStreamAware.java
new file mode 100644
index 000000000..c2287c459
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/JSONStreamAware.java
@@ -0,0 +1,15 @@
+package org.json.simple;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * Beans that support customized output of JSON text to a writer shall implement this interface.
+ * @author FangYidong<fangyidong@yahoo.com.cn>
+ */
+public interface JSONStreamAware {
+ /**
+ * write JSON string to out.
+ */
+ void writeJSONString(Writer out) throws IOException;
+}
diff --git a/mobile/android/thirdparty/org/json/simple/JSONValue.java b/mobile/android/thirdparty/org/json/simple/JSONValue.java
new file mode 100644
index 000000000..aba3c40c2
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/JSONValue.java
@@ -0,0 +1,272 @@
+/*
+ * $Id: JSONValue.java,v 1.1 2006/04/15 14:37:04 platform Exp $
+ * Created on 2006-4-15
+ */
+package org.json.simple;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.Writer;
+import java.util.List;
+import java.util.Map;
+
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+
+
+/**
+ * @author FangYidong<fangyidong@yahoo.com.cn>
+ */
+public class JSONValue {
+ /**
+ * Parse JSON text into java object from the input source.
+ * Please use parseWithException() if you don't want to ignore the exception.
+ *
+ * @see org.json.simple.parser.JSONParser#parse(Reader)
+ * @see #parseWithException(Reader)
+ *
+ * @param in
+ * @return Instance of the following:
+ * org.json.simple.JSONObject,
+ * org.json.simple.JSONArray,
+ * java.lang.String,
+ * java.lang.Number,
+ * java.lang.Boolean,
+ * null
+ *
+ */
+ public static Object parse(Reader in){
+ try{
+ JSONParser parser=new JSONParser();
+ return parser.parse(in);
+ }
+ catch(Exception e){
+ return null;
+ }
+ }
+
+ public static Object parse(String s){
+ StringReader in=new StringReader(s);
+ return parse(in);
+ }
+
+ /**
+ * Parse JSON text into java object from the input source.
+ *
+ * @see org.json.simple.parser.JSONParser
+ *
+ * @param in
+ * @return Instance of the following:
+ * org.json.simple.JSONObject,
+ * org.json.simple.JSONArray,
+ * java.lang.String,
+ * java.lang.Number,
+ * java.lang.Boolean,
+ * null
+ *
+ * @throws IOException
+ * @throws ParseException
+ */
+ public static Object parseWithException(Reader in) throws IOException, ParseException{
+ JSONParser parser=new JSONParser();
+ return parser.parse(in);
+ }
+
+ public static Object parseWithException(String s) throws ParseException{
+ JSONParser parser=new JSONParser();
+ return parser.parse(s);
+ }
+
+ /**
+ * Encode an object into JSON text and write it to out.
+ * <p>
+ * If this object is a Map or a List, and it's also a JSONStreamAware or a JSONAware, JSONStreamAware or JSONAware will be considered firstly.
+ * <p>
+ * DO NOT call this method from writeJSONString(Writer) of a class that implements both JSONStreamAware and (Map or List) with
+ * "this" as the first parameter, use JSONObject.writeJSONString(Map, Writer) or JSONArray.writeJSONString(List, Writer) instead.
+ *
+ * @see org.json.simple.JSONObject#writeJSONString(Map, Writer)
+ * @see org.json.simple.JSONArray#writeJSONString(List, Writer)
+ *
+ * @param value
+ * @param writer
+ */
+ public static void writeJSONString(Object value, Writer out) throws IOException {
+ if(value == null){
+ out.write("null");
+ return;
+ }
+
+ if(value instanceof String){
+ out.write('\"');
+ out.write(escape((String)value));
+ out.write('\"');
+ return;
+ }
+
+ if(value instanceof Double){
+ if(((Double)value).isInfinite() || ((Double)value).isNaN())
+ out.write("null");
+ else
+ out.write(value.toString());
+ return;
+ }
+
+ if(value instanceof Float){
+ if(((Float)value).isInfinite() || ((Float)value).isNaN())
+ out.write("null");
+ else
+ out.write(value.toString());
+ return;
+ }
+
+ if(value instanceof Number){
+ out.write(value.toString());
+ return;
+ }
+
+ if(value instanceof Boolean){
+ out.write(value.toString());
+ return;
+ }
+
+ if((value instanceof JSONStreamAware)){
+ ((JSONStreamAware)value).writeJSONString(out);
+ return;
+ }
+
+ if((value instanceof JSONAware)){
+ out.write(((JSONAware)value).toJSONString());
+ return;
+ }
+
+ if(value instanceof Map){
+ JSONObject.writeJSONString((Map)value, out);
+ return;
+ }
+
+ if(value instanceof List){
+ JSONArray.writeJSONString((List)value, out);
+ return;
+ }
+
+ out.write(value.toString());
+ }
+
+ /**
+ * Convert an object to JSON text.
+ * <p>
+ * If this object is a Map or a List, and it's also a JSONAware, JSONAware will be considered firstly.
+ * <p>
+ * DO NOT call this method from toJSONString() of a class that implements both JSONAware and Map or List with
+ * "this" as the parameter, use JSONObject.toJSONString(Map) or JSONArray.toJSONString(List) instead.
+ *
+ * @see org.json.simple.JSONObject#toJSONString(Map)
+ * @see org.json.simple.JSONArray#toJSONString(List)
+ *
+ * @param value
+ * @return JSON text, or "null" if value is null or it's an NaN or an INF number.
+ */
+ public static String toJSONString(Object value){
+ if(value == null)
+ return "null";
+
+ if(value instanceof String)
+ return "\""+escape((String)value)+"\"";
+
+ if(value instanceof Double){
+ if(((Double)value).isInfinite() || ((Double)value).isNaN())
+ return "null";
+ else
+ return value.toString();
+ }
+
+ if(value instanceof Float){
+ if(((Float)value).isInfinite() || ((Float)value).isNaN())
+ return "null";
+ else
+ return value.toString();
+ }
+
+ if(value instanceof Number)
+ return value.toString();
+
+ if(value instanceof Boolean)
+ return value.toString();
+
+ if((value instanceof JSONAware))
+ return ((JSONAware)value).toJSONString();
+
+ if(value instanceof Map)
+ return JSONObject.toJSONString((Map)value);
+
+ if(value instanceof List)
+ return JSONArray.toJSONString((List)value);
+
+ return value.toString();
+ }
+
+ /**
+ * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F).
+ * @param s
+ * @return
+ */
+ public static String escape(String s){
+ if(s==null)
+ return null;
+ StringBuffer sb = new StringBuffer();
+ escape(s, sb);
+ return sb.toString();
+ }
+
+ /**
+ * @param s - Must not be null.
+ * @param sb
+ */
+ static void escape(String s, StringBuffer sb) {
+ for(int i=0;i<s.length();i++){
+ char ch=s.charAt(i);
+ switch(ch){
+ case '"':
+ sb.append("\\\"");
+ break;
+ case '\\':
+ sb.append("\\\\");
+ break;
+ case '\b':
+ sb.append("\\b");
+ break;
+ case '\f':
+ sb.append("\\f");
+ break;
+ case '\n':
+ sb.append("\\n");
+ break;
+ case '\r':
+ sb.append("\\r");
+ break;
+ case '\t':
+ sb.append("\\t");
+ break;
+ case '/':
+ sb.append("\\/");
+ break;
+ default:
+ //Reference: http://www.unicode.org/versions/Unicode5.1.0/
+ if((ch>='\u0000' && ch<='\u001F') || (ch>='\u007F' && ch<='\u009F') || (ch>='\u2000' && ch<='\u20FF')){
+ String ss=Integer.toHexString(ch);
+ sb.append("\\u");
+ for(int k=0;k<4-ss.length();k++){
+ sb.append('0');
+ }
+ sb.append(ss.toUpperCase());
+ }
+ else{
+ sb.append(ch);
+ }
+ }
+ }//for
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/json/simple/LICENSE.txt b/mobile/android/thirdparty/org/json/simple/LICENSE.txt
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ 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.
diff --git a/mobile/android/thirdparty/org/json/simple/parser/ContainerFactory.java b/mobile/android/thirdparty/org/json/simple/parser/ContainerFactory.java
new file mode 100644
index 000000000..366ac4dea
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/parser/ContainerFactory.java
@@ -0,0 +1,23 @@
+package org.json.simple.parser;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Container factory for creating containers for JSON object and JSON array.
+ *
+ * @see org.json.simple.parser.JSONParser#parse(java.io.Reader, ContainerFactory)
+ *
+ * @author FangYidong<fangyidong@yahoo.com.cn>
+ */
+public interface ContainerFactory {
+ /**
+ * @return A Map instance to store JSON object, or null if you want to use org.json.simple.JSONObject.
+ */
+ Map createObjectContainer();
+
+ /**
+ * @return A List instance to store JSON array, or null if you want to use org.json.simple.JSONArray.
+ */
+ List creatArrayContainer();
+}
diff --git a/mobile/android/thirdparty/org/json/simple/parser/ContentHandler.java b/mobile/android/thirdparty/org/json/simple/parser/ContentHandler.java
new file mode 100644
index 000000000..ae8d06557
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/parser/ContentHandler.java
@@ -0,0 +1,110 @@
+package org.json.simple.parser;
+
+import java.io.IOException;
+
+/**
+ * A simplified and stoppable SAX-like content handler for stream processing of JSON text.
+ *
+ * @see org.xml.sax.ContentHandler
+ * @see org.json.simple.parser.JSONParser#parse(java.io.Reader, ContentHandler, boolean)
+ *
+ * @author FangYidong<fangyidong@yahoo.com.cn>
+ */
+public interface ContentHandler {
+ /**
+ * Receive notification of the beginning of JSON processing.
+ * The parser will invoke this method only once.
+ *
+ * @throws ParseException
+ * - JSONParser will stop and throw the same exception to the caller when receiving this exception.
+ */
+ void startJSON() throws ParseException, IOException;
+
+ /**
+ * Receive notification of the end of JSON processing.
+ *
+ * @throws ParseException
+ */
+ void endJSON() throws ParseException, IOException;
+
+ /**
+ * Receive notification of the beginning of a JSON object.
+ *
+ * @return false if the handler wants to stop parsing after return.
+ * @throws ParseException
+ * - JSONParser will stop and throw the same exception to the caller when receiving this exception.
+ * @see #endJSON
+ */
+ boolean startObject() throws ParseException, IOException;
+
+ /**
+ * Receive notification of the end of a JSON object.
+ *
+ * @return false if the handler wants to stop parsing after return.
+ * @throws ParseException
+ *
+ * @see #startObject
+ */
+ boolean endObject() throws ParseException, IOException;
+
+ /**
+ * Receive notification of the beginning of a JSON object entry.
+ *
+ * @param key - Key of a JSON object entry.
+ *
+ * @return false if the handler wants to stop parsing after return.
+ * @throws ParseException
+ *
+ * @see #endObjectEntry
+ */
+ boolean startObjectEntry(String key) throws ParseException, IOException;
+
+ /**
+ * Receive notification of the end of the value of previous object entry.
+ *
+ * @return false if the handler wants to stop parsing after return.
+ * @throws ParseException
+ *
+ * @see #startObjectEntry
+ */
+ boolean endObjectEntry() throws ParseException, IOException;
+
+ /**
+ * Receive notification of the beginning of a JSON array.
+ *
+ * @return false if the handler wants to stop parsing after return.
+ * @throws ParseException
+ *
+ * @see #endArray
+ */
+ boolean startArray() throws ParseException, IOException;
+
+ /**
+ * Receive notification of the end of a JSON array.
+ *
+ * @return false if the handler wants to stop parsing after return.
+ * @throws ParseException
+ *
+ * @see #startArray
+ */
+ boolean endArray() throws ParseException, IOException;
+
+ /**
+ * Receive notification of the JSON primitive values:
+ * java.lang.String,
+ * java.lang.Number,
+ * java.lang.Boolean
+ * null
+ *
+ * @param value - Instance of the following:
+ * java.lang.String,
+ * java.lang.Number,
+ * java.lang.Boolean
+ * null
+ *
+ * @return false if the handler wants to stop parsing after return.
+ * @throws ParseException
+ */
+ boolean primitive(Object value) throws ParseException, IOException;
+
+}
diff --git a/mobile/android/thirdparty/org/json/simple/parser/JSONParser.java b/mobile/android/thirdparty/org/json/simple/parser/JSONParser.java
new file mode 100644
index 000000000..9acaa377f
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/parser/JSONParser.java
@@ -0,0 +1,533 @@
+/*
+ * $Id: JSONParser.java,v 1.1 2006/04/15 14:10:48 platform Exp $
+ * Created on 2006-4-15
+ */
+package org.json.simple.parser;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+
+
+/**
+ * Parser for JSON text. Please note that JSONParser is NOT thread-safe.
+ *
+ * @author FangYidong<fangyidong@yahoo.com.cn>
+ */
+public class JSONParser {
+ public static final int S_INIT=0;
+ public static final int S_IN_FINISHED_VALUE=1;//string,number,boolean,null,object,array
+ public static final int S_IN_OBJECT=2;
+ public static final int S_IN_ARRAY=3;
+ public static final int S_PASSED_PAIR_KEY=4;
+ public static final int S_IN_PAIR_VALUE=5;
+ public static final int S_END=6;
+ public static final int S_IN_ERROR=-1;
+
+ private LinkedList handlerStatusStack;
+ private Yylex lexer = new Yylex((Reader)null);
+ private Yytoken token = null;
+ private int status = S_INIT;
+
+ private int peekStatus(LinkedList statusStack){
+ if(statusStack.size()==0)
+ return -1;
+ Integer status=(Integer)statusStack.getFirst();
+ return status.intValue();
+ }
+
+ /**
+ * Reset the parser to the initial state without resetting the underlying reader.
+ *
+ */
+ public void reset(){
+ token = null;
+ status = S_INIT;
+ handlerStatusStack = null;
+ }
+
+ /**
+ * Reset the parser to the initial state with a new character reader.
+ *
+ * @param in - The new character reader.
+ * @throws IOException
+ * @throws ParseException
+ */
+ public void reset(Reader in){
+ lexer.yyreset(in);
+ reset();
+ }
+
+ /**
+ * @return The position of the beginning of the current token.
+ */
+ public int getPosition(){
+ return lexer.getPosition();
+ }
+
+ public Object parse(String s) throws ParseException{
+ return parse(s, (ContainerFactory)null);
+ }
+
+ public Object parse(String s, ContainerFactory containerFactory) throws ParseException{
+ StringReader in=new StringReader(s);
+ try{
+ return parse(in, containerFactory);
+ }
+ catch(IOException ie){
+ /*
+ * Actually it will never happen.
+ */
+ throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie);
+ }
+ }
+
+ public Object parse(Reader in) throws IOException, ParseException{
+ return parse(in, (ContainerFactory)null);
+ }
+
+ /**
+ * Parse JSON text into java object from the input source.
+ *
+ * @param in
+ * @param containerFactory - Use this factory to createyour own JSON object and JSON array containers.
+ * @return Instance of the following:
+ * org.json.simple.JSONObject,
+ * org.json.simple.JSONArray,
+ * java.lang.String,
+ * java.lang.Number,
+ * java.lang.Boolean,
+ * null
+ *
+ * @throws IOException
+ * @throws ParseException
+ */
+ public Object parse(Reader in, ContainerFactory containerFactory) throws IOException, ParseException{
+ reset(in);
+ LinkedList statusStack = new LinkedList();
+ LinkedList valueStack = new LinkedList();
+
+ try{
+ do{
+ nextToken();
+ switch(status){
+ case S_INIT:
+ switch(token.type){
+ case Yytoken.TYPE_VALUE:
+ status=S_IN_FINISHED_VALUE;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(token.value);
+ break;
+ case Yytoken.TYPE_LEFT_BRACE:
+ status=S_IN_OBJECT;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(createObjectContainer(containerFactory));
+ break;
+ case Yytoken.TYPE_LEFT_SQUARE:
+ status=S_IN_ARRAY;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(createArrayContainer(containerFactory));
+ break;
+ default:
+ status=S_IN_ERROR;
+ }//inner switch
+ break;
+
+ case S_IN_FINISHED_VALUE:
+ if(token.type==Yytoken.TYPE_EOF)
+ return valueStack.removeFirst();
+ else
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+
+ case S_IN_OBJECT:
+ switch(token.type){
+ case Yytoken.TYPE_COMMA:
+ break;
+ case Yytoken.TYPE_VALUE:
+ if(token.value instanceof String){
+ String key=(String)token.value;
+ valueStack.addFirst(key);
+ status=S_PASSED_PAIR_KEY;
+ statusStack.addFirst(new Integer(status));
+ }
+ else{
+ status=S_IN_ERROR;
+ }
+ break;
+ case Yytoken.TYPE_RIGHT_BRACE:
+ if(valueStack.size()>1){
+ statusStack.removeFirst();
+ valueStack.removeFirst();
+ status=peekStatus(statusStack);
+ }
+ else{
+ status=S_IN_FINISHED_VALUE;
+ }
+ break;
+ default:
+ status=S_IN_ERROR;
+ break;
+ }//inner switch
+ break;
+
+ case S_PASSED_PAIR_KEY:
+ switch(token.type){
+ case Yytoken.TYPE_COLON:
+ break;
+ case Yytoken.TYPE_VALUE:
+ statusStack.removeFirst();
+ String key=(String)valueStack.removeFirst();
+ Map parent=(Map)valueStack.getFirst();
+ parent.put(key,token.value);
+ status=peekStatus(statusStack);
+ break;
+ case Yytoken.TYPE_LEFT_SQUARE:
+ statusStack.removeFirst();
+ key=(String)valueStack.removeFirst();
+ parent=(Map)valueStack.getFirst();
+ List newArray=createArrayContainer(containerFactory);
+ parent.put(key,newArray);
+ status=S_IN_ARRAY;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(newArray);
+ break;
+ case Yytoken.TYPE_LEFT_BRACE:
+ statusStack.removeFirst();
+ key=(String)valueStack.removeFirst();
+ parent=(Map)valueStack.getFirst();
+ Map newObject=createObjectContainer(containerFactory);
+ parent.put(key,newObject);
+ status=S_IN_OBJECT;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(newObject);
+ break;
+ default:
+ status=S_IN_ERROR;
+ }
+ break;
+
+ case S_IN_ARRAY:
+ switch(token.type){
+ case Yytoken.TYPE_COMMA:
+ break;
+ case Yytoken.TYPE_VALUE:
+ List val=(List)valueStack.getFirst();
+ val.add(token.value);
+ break;
+ case Yytoken.TYPE_RIGHT_SQUARE:
+ if(valueStack.size()>1){
+ statusStack.removeFirst();
+ valueStack.removeFirst();
+ status=peekStatus(statusStack);
+ }
+ else{
+ status=S_IN_FINISHED_VALUE;
+ }
+ break;
+ case Yytoken.TYPE_LEFT_BRACE:
+ val=(List)valueStack.getFirst();
+ Map newObject=createObjectContainer(containerFactory);
+ val.add(newObject);
+ status=S_IN_OBJECT;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(newObject);
+ break;
+ case Yytoken.TYPE_LEFT_SQUARE:
+ val=(List)valueStack.getFirst();
+ List newArray=createArrayContainer(containerFactory);
+ val.add(newArray);
+ status=S_IN_ARRAY;
+ statusStack.addFirst(new Integer(status));
+ valueStack.addFirst(newArray);
+ break;
+ default:
+ status=S_IN_ERROR;
+ }//inner switch
+ break;
+ case S_IN_ERROR:
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }//switch
+ if(status==S_IN_ERROR){
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }
+ }while(token.type!=Yytoken.TYPE_EOF);
+ }
+ catch(IOException ie){
+ throw ie;
+ }
+
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }
+
+ private void nextToken() throws ParseException, IOException{
+ token = lexer.yylex();
+ if(token == null)
+ token = new Yytoken(Yytoken.TYPE_EOF, null);
+ }
+
+ private Map createObjectContainer(ContainerFactory containerFactory){
+ if(containerFactory == null)
+ return new JSONObject();
+ Map m = containerFactory.createObjectContainer();
+
+ if(m == null)
+ return new JSONObject();
+ return m;
+ }
+
+ private List createArrayContainer(ContainerFactory containerFactory){
+ if(containerFactory == null)
+ return new JSONArray();
+ List l = containerFactory.creatArrayContainer();
+
+ if(l == null)
+ return new JSONArray();
+ return l;
+ }
+
+ public void parse(String s, ContentHandler contentHandler) throws ParseException{
+ parse(s, contentHandler, false);
+ }
+
+ public void parse(String s, ContentHandler contentHandler, boolean isResume) throws ParseException{
+ StringReader in=new StringReader(s);
+ try{
+ parse(in, contentHandler, isResume);
+ }
+ catch(IOException ie){
+ /*
+ * Actually it will never happen.
+ */
+ throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie);
+ }
+ }
+
+ public void parse(Reader in, ContentHandler contentHandler) throws IOException, ParseException{
+ parse(in, contentHandler, false);
+ }
+
+ /**
+ * Stream processing of JSON text.
+ *
+ * @see ContentHandler
+ *
+ * @param in
+ * @param contentHandler
+ * @param isResume - Indicates if it continues previous parsing operation.
+ * If set to true, resume parsing the old stream, and parameter 'in' will be ignored.
+ * If this method is called for the first time in this instance, isResume will be ignored.
+ *
+ * @throws IOException
+ * @throws ParseException
+ */
+ public void parse(Reader in, ContentHandler contentHandler, boolean isResume) throws IOException, ParseException{
+ if(!isResume){
+ reset(in);
+ handlerStatusStack = new LinkedList();
+ }
+ else{
+ if(handlerStatusStack == null){
+ isResume = false;
+ reset(in);
+ handlerStatusStack = new LinkedList();
+ }
+ }
+
+ LinkedList statusStack = handlerStatusStack;
+
+ try{
+ do{
+ switch(status){
+ case S_INIT:
+ contentHandler.startJSON();
+ nextToken();
+ switch(token.type){
+ case Yytoken.TYPE_VALUE:
+ status=S_IN_FINISHED_VALUE;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.primitive(token.value))
+ return;
+ break;
+ case Yytoken.TYPE_LEFT_BRACE:
+ status=S_IN_OBJECT;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startObject())
+ return;
+ break;
+ case Yytoken.TYPE_LEFT_SQUARE:
+ status=S_IN_ARRAY;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startArray())
+ return;
+ break;
+ default:
+ status=S_IN_ERROR;
+ }//inner switch
+ break;
+
+ case S_IN_FINISHED_VALUE:
+ nextToken();
+ if(token.type==Yytoken.TYPE_EOF){
+ contentHandler.endJSON();
+ status = S_END;
+ return;
+ }
+ else{
+ status = S_IN_ERROR;
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }
+
+ case S_IN_OBJECT:
+ nextToken();
+ switch(token.type){
+ case Yytoken.TYPE_COMMA:
+ break;
+ case Yytoken.TYPE_VALUE:
+ if(token.value instanceof String){
+ String key=(String)token.value;
+ status=S_PASSED_PAIR_KEY;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startObjectEntry(key))
+ return;
+ }
+ else{
+ status=S_IN_ERROR;
+ }
+ break;
+ case Yytoken.TYPE_RIGHT_BRACE:
+ if(statusStack.size()>1){
+ statusStack.removeFirst();
+ status=peekStatus(statusStack);
+ }
+ else{
+ status=S_IN_FINISHED_VALUE;
+ }
+ if(!contentHandler.endObject())
+ return;
+ break;
+ default:
+ status=S_IN_ERROR;
+ break;
+ }//inner switch
+ break;
+
+ case S_PASSED_PAIR_KEY:
+ nextToken();
+ switch(token.type){
+ case Yytoken.TYPE_COLON:
+ break;
+ case Yytoken.TYPE_VALUE:
+ statusStack.removeFirst();
+ status=peekStatus(statusStack);
+ if(!contentHandler.primitive(token.value))
+ return;
+ if(!contentHandler.endObjectEntry())
+ return;
+ break;
+ case Yytoken.TYPE_LEFT_SQUARE:
+ statusStack.removeFirst();
+ statusStack.addFirst(new Integer(S_IN_PAIR_VALUE));
+ status=S_IN_ARRAY;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startArray())
+ return;
+ break;
+ case Yytoken.TYPE_LEFT_BRACE:
+ statusStack.removeFirst();
+ statusStack.addFirst(new Integer(S_IN_PAIR_VALUE));
+ status=S_IN_OBJECT;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startObject())
+ return;
+ break;
+ default:
+ status=S_IN_ERROR;
+ }
+ break;
+
+ case S_IN_PAIR_VALUE:
+ /*
+ * S_IN_PAIR_VALUE is just a marker to indicate the end of an object entry, it doesn't proccess any token,
+ * therefore delay consuming token until next round.
+ */
+ statusStack.removeFirst();
+ status = peekStatus(statusStack);
+ if(!contentHandler.endObjectEntry())
+ return;
+ break;
+
+ case S_IN_ARRAY:
+ nextToken();
+ switch(token.type){
+ case Yytoken.TYPE_COMMA:
+ break;
+ case Yytoken.TYPE_VALUE:
+ if(!contentHandler.primitive(token.value))
+ return;
+ break;
+ case Yytoken.TYPE_RIGHT_SQUARE:
+ if(statusStack.size()>1){
+ statusStack.removeFirst();
+ status=peekStatus(statusStack);
+ }
+ else{
+ status=S_IN_FINISHED_VALUE;
+ }
+ if(!contentHandler.endArray())
+ return;
+ break;
+ case Yytoken.TYPE_LEFT_BRACE:
+ status=S_IN_OBJECT;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startObject())
+ return;
+ break;
+ case Yytoken.TYPE_LEFT_SQUARE:
+ status=S_IN_ARRAY;
+ statusStack.addFirst(new Integer(status));
+ if(!contentHandler.startArray())
+ return;
+ break;
+ default:
+ status=S_IN_ERROR;
+ }//inner switch
+ break;
+
+ case S_END:
+ return;
+
+ case S_IN_ERROR:
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }//switch
+ if(status==S_IN_ERROR){
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }
+ }while(token.type!=Yytoken.TYPE_EOF);
+ }
+ catch(IOException ie){
+ status = S_IN_ERROR;
+ throw ie;
+ }
+ catch(ParseException pe){
+ status = S_IN_ERROR;
+ throw pe;
+ }
+ catch(RuntimeException re){
+ status = S_IN_ERROR;
+ throw re;
+ }
+ catch(Error e){
+ status = S_IN_ERROR;
+ throw e;
+ }
+
+ status = S_IN_ERROR;
+ throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
+ }
+}
diff --git a/mobile/android/thirdparty/org/json/simple/parser/ParseException.java b/mobile/android/thirdparty/org/json/simple/parser/ParseException.java
new file mode 100644
index 000000000..a5a5407f9
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/parser/ParseException.java
@@ -0,0 +1,96 @@
+package org.json.simple.parser;
+
+/**
+ * ParseException explains why and where the error occurs in source JSON text.
+ *
+ * @author FangYidong<fangyidong@yahoo.com.cn>
+ *
+ */
+public class ParseException extends Exception {
+ private static final long serialVersionUID = -7880698968187728548L;
+
+ public static final int ERROR_UNEXPECTED_CHAR = 0;
+ public static final int ERROR_UNEXPECTED_TOKEN = 1;
+ public static final int ERROR_UNEXPECTED_EXCEPTION = 2;
+
+ private int errorType;
+ private Object unexpectedObject;
+ private int position;
+
+ public ParseException(int errorType, Throwable throwable) {
+ this(-1, errorType, null, throwable);
+ }
+
+ public ParseException(int errorType, Object unexpectedObject) {
+ this(-1, errorType, unexpectedObject);
+ }
+
+ public ParseException(int position, int errorType, Object unexpectedObject) {
+ this(-1, errorType, unexpectedObject, null);
+ }
+
+ public ParseException(int position, int errorType, Object unexpectedObject, Throwable throwable) {
+ super(throwable);
+ this.position = position;
+ this.errorType = errorType;
+ this.unexpectedObject = unexpectedObject;
+ }
+
+ public int getErrorType() {
+ return errorType;
+ }
+
+ public void setErrorType(int errorType) {
+ this.errorType = errorType;
+ }
+
+ /**
+ * @see org.json.simple.parser.JSONParser#getPosition()
+ *
+ * @return The character position (starting with 0) of the input where the error occurs.
+ */
+ public int getPosition() {
+ return position;
+ }
+
+ public void setPosition(int position) {
+ this.position = position;
+ }
+
+ /**
+ * @see org.json.simple.parser.Yytoken
+ *
+ * @return One of the following base on the value of errorType:
+ * ERROR_UNEXPECTED_CHAR java.lang.Character
+ * ERROR_UNEXPECTED_TOKEN org.json.simple.parser.Yytoken
+ * ERROR_UNEXPECTED_EXCEPTION java.lang.Exception
+ */
+ public Object getUnexpectedObject() {
+ return unexpectedObject;
+ }
+
+ public void setUnexpectedObject(Object unexpectedObject) {
+ this.unexpectedObject = unexpectedObject;
+ }
+
+ @Override
+ public String toString(){
+ StringBuffer sb = new StringBuffer();
+
+ switch(errorType){
+ case ERROR_UNEXPECTED_CHAR:
+ sb.append("Unexpected character (").append(unexpectedObject).append(") at position ").append(position).append(".");
+ break;
+ case ERROR_UNEXPECTED_TOKEN:
+ sb.append("Unexpected token ").append(unexpectedObject).append(" at position ").append(position).append(".");
+ break;
+ case ERROR_UNEXPECTED_EXCEPTION:
+ sb.append("Unexpected exception at position ").append(position).append(": ").append(unexpectedObject);
+ break;
+ default:
+ sb.append("Unkown error at position ").append(position).append(".");
+ break;
+ }
+ return sb.toString();
+ }
+}
diff --git a/mobile/android/thirdparty/org/json/simple/parser/Yylex.java b/mobile/android/thirdparty/org/json/simple/parser/Yylex.java
new file mode 100644
index 000000000..42ce508eb
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/parser/Yylex.java
@@ -0,0 +1,688 @@
+/* The following code was generated by JFlex 1.4.2 */
+
+package org.json.simple.parser;
+
+class Yylex {
+
+ /** This character denotes the end of file */
+ public static final int YYEOF = -1;
+
+ /** initial size of the lookahead buffer */
+ private static final int ZZ_BUFFERSIZE = 16384;
+
+ /** lexical states */
+ public static final int YYINITIAL = 0;
+ public static final int STRING_BEGIN = 2;
+
+ /**
+ * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l
+ * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l
+ * at the beginning of a line
+ * l is of the form l = 2*k, k a non negative integer
+ */
+ private static final int ZZ_LEXSTATE[] = {
+ 0, 0, 1, 1
+ };
+
+ /**
+ * Translates characters to character classes
+ */
+ private static final String ZZ_CMAP_PACKED =
+ "\11\0\1\7\1\7\2\0\1\7\22\0\1\7\1\0\1\11\10\0"+
+ "\1\6\1\31\1\2\1\4\1\12\12\3\1\32\6\0\4\1\1\5"+
+ "\1\1\24\0\1\27\1\10\1\30\3\0\1\22\1\13\2\1\1\21"+
+ "\1\14\5\0\1\23\1\0\1\15\3\0\1\16\1\24\1\17\1\20"+
+ "\5\0\1\25\1\0\1\26\uff82\0";
+
+ /**
+ * Translates characters to character classes
+ */
+ private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED);
+
+ /**
+ * Translates DFA states to action switch labels.
+ */
+ private static final int [] ZZ_ACTION = zzUnpackAction();
+
+ private static final String ZZ_ACTION_PACKED_0 =
+ "\2\0\2\1\1\2\1\3\1\4\3\1\1\5\1\6"+
+ "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\5\0"+
+ "\1\14\1\16\1\17\1\20\1\21\1\22\1\23\1\24"+
+ "\1\0\1\25\1\0\1\25\4\0\1\26\1\27\2\0"+
+ "\1\30";
+
+ private static int [] zzUnpackAction() {
+ int [] result = new int[45];
+ int offset = 0;
+ offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result);
+ return result;
+ }
+
+ private static int zzUnpackAction(String packed, int offset, int [] result) {
+ int i = 0; /* index in packed string */
+ int j = offset; /* index in unpacked array */
+ int l = packed.length();
+ while (i < l) {
+ int count = packed.charAt(i++);
+ int value = packed.charAt(i++);
+ do result[j++] = value; while (--count > 0);
+ }
+ return j;
+ }
+
+
+ /**
+ * Translates a state to a row index in the transition table
+ */
+ private static final int [] ZZ_ROWMAP = zzUnpackRowMap();
+
+ private static final String ZZ_ROWMAP_PACKED_0 =
+ "\0\0\0\33\0\66\0\121\0\154\0\207\0\66\0\242"+
+ "\0\275\0\330\0\66\0\66\0\66\0\66\0\66\0\66"+
+ "\0\363\0\u010e\0\66\0\u0129\0\u0144\0\u015f\0\u017a\0\u0195"+
+ "\0\66\0\66\0\66\0\66\0\66\0\66\0\66\0\66"+
+ "\0\u01b0\0\u01cb\0\u01e6\0\u01e6\0\u0201\0\u021c\0\u0237\0\u0252"+
+ "\0\66\0\66\0\u026d\0\u0288\0\66";
+
+ private static int [] zzUnpackRowMap() {
+ int [] result = new int[45];
+ int offset = 0;
+ offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result);
+ return result;
+ }
+
+ private static int zzUnpackRowMap(String packed, int offset, int [] result) {
+ int i = 0; /* index in packed string */
+ int j = offset; /* index in unpacked array */
+ int l = packed.length();
+ while (i < l) {
+ int high = packed.charAt(i++) << 16;
+ result[j++] = high | packed.charAt(i++);
+ }
+ return j;
+ }
+
+ /**
+ * The transition table of the DFA
+ */
+ private static final int ZZ_TRANS [] = {
+ 2, 2, 3, 4, 2, 2, 2, 5, 2, 6,
+ 2, 2, 7, 8, 2, 9, 2, 2, 2, 2,
+ 2, 10, 11, 12, 13, 14, 15, 16, 16, 16,
+ 16, 16, 16, 16, 16, 17, 18, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 4, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 4, 19, 20, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 20, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 5, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 21, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 22, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 23, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 16, 16, 16, 16, 16, 16, 16,
+ 16, -1, -1, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ -1, -1, -1, -1, -1, -1, -1, -1, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 33, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 34, 35, -1, -1,
+ 34, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 36, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, 37, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, 38, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 39, -1, 39, -1, 39, -1, -1,
+ -1, -1, -1, 39, 39, -1, -1, -1, -1, 39,
+ 39, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 33, -1, 20, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 20, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 35,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 38, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 40,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, 41, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 42, -1, 42, -1, 42,
+ -1, -1, -1, -1, -1, 42, 42, -1, -1, -1,
+ -1, 42, 42, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 43, -1, 43, -1, 43, -1, -1, -1,
+ -1, -1, 43, 43, -1, -1, -1, -1, 43, 43,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 44,
+ -1, 44, -1, 44, -1, -1, -1, -1, -1, 44,
+ 44, -1, -1, -1, -1, 44, 44, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ };
+
+ /* error codes */
+ private static final int ZZ_UNKNOWN_ERROR = 0;
+ private static final int ZZ_NO_MATCH = 1;
+ private static final int ZZ_PUSHBACK_2BIG = 2;
+
+ /* error messages for the codes above */
+ private static final String ZZ_ERROR_MSG[] = {
+ "Unkown internal scanner error",
+ "Error: could not match input",
+ "Error: pushback value was too large"
+ };
+
+ /**
+ * ZZ_ATTRIBUTE[aState] contains the attributes of state <code>aState</code>
+ */
+ private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute();
+
+ private static final String ZZ_ATTRIBUTE_PACKED_0 =
+ "\2\0\1\11\3\1\1\11\3\1\6\11\2\1\1\11"+
+ "\5\0\10\11\1\0\1\1\1\0\1\1\4\0\2\11"+
+ "\2\0\1\11";
+
+ private static int [] zzUnpackAttribute() {
+ int [] result = new int[45];
+ int offset = 0;
+ offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result);
+ return result;
+ }
+
+ private static int zzUnpackAttribute(String packed, int offset, int [] result) {
+ int i = 0; /* index in packed string */
+ int j = offset; /* index in unpacked array */
+ int l = packed.length();
+ while (i < l) {
+ int count = packed.charAt(i++);
+ int value = packed.charAt(i++);
+ do result[j++] = value; while (--count > 0);
+ }
+ return j;
+ }
+
+ /** the input device */
+ private java.io.Reader zzReader;
+
+ /** the current state of the DFA */
+ private int zzState;
+
+ /** the current lexical state */
+ private int zzLexicalState = YYINITIAL;
+
+ /** this buffer contains the current text to be matched and is
+ the source of the yytext() string */
+ private char zzBuffer[] = new char[ZZ_BUFFERSIZE];
+
+ /** the textposition at the last accepting state */
+ private int zzMarkedPos;
+
+ /** the current text position in the buffer */
+ private int zzCurrentPos;
+
+ /** startRead marks the beginning of the yytext() string in the buffer */
+ private int zzStartRead;
+
+ /** endRead marks the last character in the buffer, that has been read
+ from input */
+ private int zzEndRead;
+
+ /** number of newlines encountered up to the start of the matched text */
+ private int yyline;
+
+ /** the number of characters up to the start of the matched text */
+ private int yychar;
+
+ /**
+ * the number of characters from the last newline up to the start of the
+ * matched text
+ */
+ private int yycolumn;
+
+ /**
+ * zzAtBOL == true <=> the scanner is currently at the beginning of a line
+ */
+ private boolean zzAtBOL = true;
+
+ /** zzAtEOF == true <=> the scanner is at the EOF */
+ private boolean zzAtEOF;
+
+ /* user code: */
+private StringBuffer sb=new StringBuffer();
+
+int getPosition(){
+ return yychar;
+}
+
+
+
+ /**
+ * Creates a new scanner
+ * There is also a java.io.InputStream version of this constructor.
+ *
+ * @param in the java.io.Reader to read input from.
+ */
+ Yylex(java.io.Reader in) {
+ this.zzReader = in;
+ }
+
+ /**
+ * Creates a new scanner.
+ * There is also java.io.Reader version of this constructor.
+ *
+ * @param in the java.io.Inputstream to read input from.
+ */
+ Yylex(java.io.InputStream in) {
+ this(new java.io.InputStreamReader(in));
+ }
+
+ /**
+ * Unpacks the compressed character translation table.
+ *
+ * @param packed the packed character translation table
+ * @return the unpacked character translation table
+ */
+ private static char [] zzUnpackCMap(String packed) {
+ char [] map = new char[0x10000];
+ int i = 0; /* index in packed string */
+ int j = 0; /* index in unpacked array */
+ while (i < 90) {
+ int count = packed.charAt(i++);
+ char value = packed.charAt(i++);
+ do map[j++] = value; while (--count > 0);
+ }
+ return map;
+ }
+
+
+ /**
+ * Refills the input buffer.
+ *
+ * @return <code>false</code>, iff there was new input.
+ *
+ * @exception java.io.IOException if any I/O-Error occurs
+ */
+ private boolean zzRefill() throws java.io.IOException {
+
+ /* first: make room (if you can) */
+ if (zzStartRead > 0) {
+ System.arraycopy(zzBuffer, zzStartRead,
+ zzBuffer, 0,
+ zzEndRead-zzStartRead);
+
+ /* translate stored positions */
+ zzEndRead-= zzStartRead;
+ zzCurrentPos-= zzStartRead;
+ zzMarkedPos-= zzStartRead;
+ zzStartRead = 0;
+ }
+
+ /* is the buffer big enough? */
+ if (zzCurrentPos >= zzBuffer.length) {
+ /* if not: blow it up */
+ char newBuffer[] = new char[zzCurrentPos*2];
+ System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length);
+ zzBuffer = newBuffer;
+ }
+
+ /* finally: fill the buffer with new input */
+ int numRead = zzReader.read(zzBuffer, zzEndRead,
+ zzBuffer.length-zzEndRead);
+
+ if (numRead > 0) {
+ zzEndRead+= numRead;
+ return false;
+ }
+ // unlikely but not impossible: read 0 characters, but not at end of stream
+ if (numRead == 0) {
+ int c = zzReader.read();
+ if (c == -1) {
+ return true;
+ } else {
+ zzBuffer[zzEndRead++] = (char) c;
+ return false;
+ }
+ }
+
+ // numRead < 0
+ return true;
+ }
+
+
+ /**
+ * Closes the input stream.
+ */
+ public final void yyclose() throws java.io.IOException {
+ zzAtEOF = true; /* indicate end of file */
+ zzEndRead = zzStartRead; /* invalidate buffer */
+
+ if (zzReader != null)
+ zzReader.close();
+ }
+
+
+ /**
+ * Resets the scanner to read from a new input stream.
+ * Does not close the old reader.
+ *
+ * All internal variables are reset, the old input stream
+ * <b>cannot</b> be reused (internal buffer is discarded and lost).
+ * Lexical state is set to <tt>ZZ_INITIAL</tt>.
+ *
+ * @param reader the new input stream
+ */
+ public final void yyreset(java.io.Reader reader) {
+ zzReader = reader;
+ zzAtBOL = true;
+ zzAtEOF = false;
+ zzEndRead = zzStartRead = 0;
+ zzCurrentPos = zzMarkedPos = 0;
+ yyline = yychar = yycolumn = 0;
+ zzLexicalState = YYINITIAL;
+ }
+
+
+ /**
+ * Returns the current lexical state.
+ */
+ public final int yystate() {
+ return zzLexicalState;
+ }
+
+
+ /**
+ * Enters a new lexical state
+ *
+ * @param newState the new lexical state
+ */
+ public final void yybegin(int newState) {
+ zzLexicalState = newState;
+ }
+
+
+ /**
+ * Returns the text matched by the current regular expression.
+ */
+ public final String yytext() {
+ return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead );
+ }
+
+
+ /**
+ * Returns the character at position <tt>pos</tt> from the
+ * matched text.
+ *
+ * It is equivalent to yytext().charAt(pos), but faster
+ *
+ * @param pos the position of the character to fetch.
+ * A value from 0 to yylength()-1.
+ *
+ * @return the character at position pos
+ */
+ public final char yycharat(int pos) {
+ return zzBuffer[zzStartRead+pos];
+ }
+
+
+ /**
+ * Returns the length of the matched text region.
+ */
+ public final int yylength() {
+ return zzMarkedPos-zzStartRead;
+ }
+
+
+ /**
+ * Reports an error that occured while scanning.
+ *
+ * In a wellformed scanner (no or only correct usage of
+ * yypushback(int) and a match-all fallback rule) this method
+ * will only be called with things that "Can't Possibly Happen".
+ * If this method is called, something is seriously wrong
+ * (e.g. a JFlex bug producing a faulty scanner etc.).
+ *
+ * Usual syntax/scanner level error handling should be done
+ * in error fallback rules.
+ *
+ * @param errorCode the code of the errormessage to display
+ */
+ private void zzScanError(int errorCode) {
+ String message;
+ try {
+ message = ZZ_ERROR_MSG[errorCode];
+ }
+ catch (ArrayIndexOutOfBoundsException e) {
+ message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR];
+ }
+
+ throw new Error(message);
+ }
+
+
+ /**
+ * Pushes the specified amount of characters back into the input stream.
+ *
+ * They will be read again by then next call of the scanning method
+ *
+ * @param number the number of characters to be read again.
+ * This number must not be greater than yylength()!
+ */
+ public void yypushback(int number) {
+ if ( number > yylength() )
+ zzScanError(ZZ_PUSHBACK_2BIG);
+
+ zzMarkedPos -= number;
+ }
+
+
+ /**
+ * Resumes scanning until the next regular expression is matched,
+ * the end of input is encountered or an I/O-Error occurs.
+ *
+ * @return the next token
+ * @exception java.io.IOException if any I/O-Error occurs
+ */
+ public Yytoken yylex() throws java.io.IOException, ParseException {
+ int zzInput;
+ int zzAction;
+
+ // cached fields:
+ int zzCurrentPosL;
+ int zzMarkedPosL;
+ int zzEndReadL = zzEndRead;
+ char [] zzBufferL = zzBuffer;
+ char [] zzCMapL = ZZ_CMAP;
+
+ int [] zzTransL = ZZ_TRANS;
+ int [] zzRowMapL = ZZ_ROWMAP;
+ int [] zzAttrL = ZZ_ATTRIBUTE;
+
+ while (true) {
+ zzMarkedPosL = zzMarkedPos;
+
+ yychar+= zzMarkedPosL-zzStartRead;
+
+ zzAction = -1;
+
+ zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL;
+
+ zzState = ZZ_LEXSTATE[zzLexicalState];
+
+
+ zzForAction: {
+ while (true) {
+
+ if (zzCurrentPosL < zzEndReadL)
+ zzInput = zzBufferL[zzCurrentPosL++];
+ else if (zzAtEOF) {
+ zzInput = YYEOF;
+ break zzForAction;
+ }
+ else {
+ // store back cached positions
+ zzCurrentPos = zzCurrentPosL;
+ zzMarkedPos = zzMarkedPosL;
+ boolean eof = zzRefill();
+ // get translated positions and possibly new buffer
+ zzCurrentPosL = zzCurrentPos;
+ zzMarkedPosL = zzMarkedPos;
+ zzBufferL = zzBuffer;
+ zzEndReadL = zzEndRead;
+ if (eof) {
+ zzInput = YYEOF;
+ break zzForAction;
+ }
+ else {
+ zzInput = zzBufferL[zzCurrentPosL++];
+ }
+ }
+ int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ];
+ if (zzNext == -1) break zzForAction;
+ zzState = zzNext;
+
+ int zzAttributes = zzAttrL[zzState];
+ if ( (zzAttributes & 1) == 1 ) {
+ zzAction = zzState;
+ zzMarkedPosL = zzCurrentPosL;
+ if ( (zzAttributes & 8) == 8 ) break zzForAction;
+ }
+
+ }
+ }
+
+ // store back cached position
+ zzMarkedPos = zzMarkedPosL;
+
+ switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) {
+ case 11:
+ { sb.append(yytext());
+ }
+ case 25: break;
+ case 4:
+ { sb.delete(0, sb.length());yybegin(STRING_BEGIN);
+ }
+ case 26: break;
+ case 16:
+ { sb.append('\b');
+ }
+ case 27: break;
+ case 6:
+ { return new Yytoken(Yytoken.TYPE_RIGHT_BRACE,null);
+ }
+ case 28: break;
+ case 23:
+ { Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val);
+ }
+ case 29: break;
+ case 22:
+ { return new Yytoken(Yytoken.TYPE_VALUE, null);
+ }
+ case 30: break;
+ case 13:
+ { yybegin(YYINITIAL);return new Yytoken(Yytoken.TYPE_VALUE, sb.toString());
+ }
+ case 31: break;
+ case 12:
+ { sb.append('\\');
+ }
+ case 32: break;
+ case 21:
+ { Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val);
+ }
+ case 33: break;
+ case 1:
+ { throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_CHAR, new Character(yycharat(0)));
+ }
+ case 34: break;
+ case 8:
+ { return new Yytoken(Yytoken.TYPE_RIGHT_SQUARE,null);
+ }
+ case 35: break;
+ case 19:
+ { sb.append('\r');
+ }
+ case 36: break;
+ case 15:
+ { sb.append('/');
+ }
+ case 37: break;
+ case 10:
+ { return new Yytoken(Yytoken.TYPE_COLON,null);
+ }
+ case 38: break;
+ case 14:
+ { sb.append('"');
+ }
+ case 39: break;
+ case 5:
+ { return new Yytoken(Yytoken.TYPE_LEFT_BRACE,null);
+ }
+ case 40: break;
+ case 17:
+ { sb.append('\f');
+ }
+ case 41: break;
+ case 24:
+ { try{
+ int ch=Integer.parseInt(yytext().substring(2),16);
+ sb.append((char)ch);
+ }
+ catch(Exception e){
+ throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_EXCEPTION, e);
+ }
+ }
+ case 42: break;
+ case 20:
+ { sb.append('\t');
+ }
+ case 43: break;
+ case 7:
+ { return new Yytoken(Yytoken.TYPE_LEFT_SQUARE,null);
+ }
+ case 44: break;
+ case 2:
+ { Long val=Long.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val);
+ }
+ case 45: break;
+ case 18:
+ { sb.append('\n');
+ }
+ case 46: break;
+ case 9:
+ { return new Yytoken(Yytoken.TYPE_COMMA,null);
+ }
+ case 47: break;
+ case 3:
+ {
+ }
+ case 48: break;
+ default:
+ if (zzInput == YYEOF && zzStartRead == zzCurrentPos) {
+ zzAtEOF = true;
+ return null;
+ }
+ else {
+ zzScanError(ZZ_NO_MATCH);
+ }
+ }
+ }
+ }
+
+
+}
diff --git a/mobile/android/thirdparty/org/json/simple/parser/Yytoken.java b/mobile/android/thirdparty/org/json/simple/parser/Yytoken.java
new file mode 100644
index 000000000..ff14e27c1
--- /dev/null
+++ b/mobile/android/thirdparty/org/json/simple/parser/Yytoken.java
@@ -0,0 +1,58 @@
+/*
+ * $Id: Yytoken.java,v 1.1 2006/04/15 14:10:48 platform Exp $
+ * Created on 2006-4-15
+ */
+package org.json.simple.parser;
+
+/**
+ * @author FangYidong<fangyidong@yahoo.com.cn>
+ */
+public class Yytoken {
+ public static final int TYPE_VALUE=0;//JSON primitive value: string,number,boolean,null
+ public static final int TYPE_LEFT_BRACE=1;
+ public static final int TYPE_RIGHT_BRACE=2;
+ public static final int TYPE_LEFT_SQUARE=3;
+ public static final int TYPE_RIGHT_SQUARE=4;
+ public static final int TYPE_COMMA=5;
+ public static final int TYPE_COLON=6;
+ public static final int TYPE_EOF=-1;//end of file
+
+ public int type=0;
+ public Object value=null;
+
+ public Yytoken(int type,Object value){
+ this.type=type;
+ this.value=value;
+ }
+
+ public String toString(){
+ StringBuffer sb = new StringBuffer();
+ switch(type){
+ case TYPE_VALUE:
+ sb.append("VALUE(").append(value).append(")");
+ break;
+ case TYPE_LEFT_BRACE:
+ sb.append("LEFT BRACE({)");
+ break;
+ case TYPE_RIGHT_BRACE:
+ sb.append("RIGHT BRACE(})");
+ break;
+ case TYPE_LEFT_SQUARE:
+ sb.append("LEFT SQUARE([)");
+ break;
+ case TYPE_RIGHT_SQUARE:
+ sb.append("RIGHT SQUARE(])");
+ break;
+ case TYPE_COMMA:
+ sb.append("COMMA(,)");
+ break;
+ case TYPE_COLON:
+ sb.append("COLON(:)");
+ break;
+ case TYPE_EOF:
+ sb.append("END OF FILE");
+ break;
+ }
+ return sb.toString();
+ }
+}
diff --git a/mobile/android/thirdparty/org/lucasr/dspec/DesignSpec.java b/mobile/android/thirdparty/org/lucasr/dspec/DesignSpec.java
new file mode 100644
index 000000000..43505be4e
--- /dev/null
+++ b/mobile/android/thirdparty/org/lucasr/dspec/DesignSpec.java
@@ -0,0 +1,645 @@
+/*
+ * Copyright (C) 2014 Lucas Rocha
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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 org.lucasr.dspec;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Draw a baseline grid, keylines, and spacing markers on top of a {@link View}.
+ *
+ * A {@link DesignSpec} can be configure programmatically as follows:
+ * <ol>
+ * <li>Toggle baseline grid visibility with {@link #setBaselineGridVisible(boolean)}.</li>
+ * <li>Change baseline grid cell width with {@link #setBaselineGridCellSize(float)}.
+ * <li>Change baseline grid color with {@link #setBaselineGridColor(int)}.
+ * <li>Toggle keylines visibility with {@link #setKeylinesVisible(boolean)}.
+ * <li>Change keylines color with {@link #setKeylinesColor(int)}.
+ * <li>Add keylines with {@link #addKeyline(float, From)}.
+ * <li>Toggle spacings visibility with {@link #setSpacingsVisible(boolean)}.
+ * <li>Change spacings color with {@link #setSpacingsColor(int)}.
+ * <li>Add spacing with {@link #addSpacing(float, float, From)}.
+ * </ol>
+ *
+ * You can also define a {@link DesignSpec} via a raw JSON resource as follows:
+ * <pre>
+ * {
+ * "baselineGridVisible": true,
+ * "baselineGridCellSize": 8,
+ * "keylines": [
+ * { "offset": 16,
+ * "from": "LEFT" },
+ * { "offset": 72,
+ * "from": "LEFT" },
+ * { "offset": 16,
+ * "from": "RIGHT" }
+ * ],
+ * "spacings": [
+ * { "offset": 0,
+ * "size": 16,
+ * "from": "LEFT" },
+ * { "offset": 56,
+ * "size": 16,
+ * "from": "LEFT" },
+ * { "offset": 0,
+ * "size": 16,
+ * "from": "RIGHT" }
+ * ]
+ * }
+ * </pre>
+ *
+ * The {@link From} arguments implicitly define the orientation of the given
+ * keyline or spacing i.e. {@link From#LEFT}, {@link From#RIGHT}, {@link From#HORIZONTAL_CENTER}
+ * are implicitly vertical; and {@link From#TOP}, {@link From#BOTTOM}, {@link From#VERTICAL_CENTER}
+ * are implicitly horizontal.
+ *
+ * The {@link From} arguments also define the 'direction' of the offsets and sizes in keylines and
+ * spacings. For example, a keyline using {@link From#RIGHT} will have its offset measured from
+ * right to left of the target {@link View}.
+ *
+ * The easiest way to use a {@link DesignSpec} is by enclosing your target {@link View} with
+ * a {@link DesignSpecFrameLayout} using the {@code designSpec} attribute as follows:
+ * <pre>
+ * <org.lucasr.dspec.DesignSpecFrameLayout
+ * xmlns:android="http://schemas.android.com/apk/res/android"
+ * android:id="@+id/design_spec"
+ * android:layout_width="match_parent"
+ * android:layout_height="match_parent"
+ * app:designSpec="@raw/my_spec">
+ *
+ * ...
+ *
+ * </org.lucasr.dspec.DesignSpecFrameLayout>
+ * </pre>
+ *
+ * Where {@code @raw/my_spec} is a raw JSON resource. Because the {@link DesignSpec} is
+ * defined in an Android resource, you can vary it according to the target form factor using
+ * well-known resource qualifiers making it easy to define different specs for phones and tablets.
+ *
+ * Because {@link DesignSpec} is a {@link Drawable}, you can simply add it to any
+ * {@link android.view.ViewOverlay} if you're running your app on API level >= 18:
+ *
+ * <pre>
+ * DesignSpec designSpec = DesignSpec.fromResource(someView, R.raw.some_spec);
+ * someView.getOverlay().add(designSpec);
+ * </pre>
+ *
+ * @see DesignSpecFrameLayout
+ * @see #fromResource(View, int)
+ */
+public class DesignSpec extends Drawable {
+ private static final boolean DEFAULT_BASELINE_GRID_VISIBLE = false;
+ private static final boolean DEFAULT_KEYLINES_VISIBLE = true;
+ private static final boolean DEFAULT_SPACINGS_VISIBLE = true;
+
+ private static final int DEFAULT_BASELINE_GRID_CELL_SIZE_DIP = 8;
+
+ private static final String DEFAULT_BASELINE_GRID_COLOR = "#44C2185B";
+ private static final String DEFAULT_KEYLINE_COLOR = "#CCC2185B";
+ private static final String DEFAULT_SPACING_COLOR = "#CC89FDFD";
+
+ private static final float KEYLINE_STROKE_WIDTH_DIP = 1.1f;
+
+ private static final String JSON_KEY_BASELINE_GRID_VISIBLE = "baselineGridVisible";
+ private static final String JSON_KEY_BASELINE_GRID_CELL_SIZE = "baselineGridCellSize";
+ private static final String JSON_KEY_BASELINE_GRID_COLOR = "baselineGridColor";
+
+ private static final String JSON_KEY_KEYLINES_VISIBLE = "keylinesVisible";
+ private static final String JSON_KEY_KEYLINES_COLOR = "keylinesColor";
+ private static final String JSON_KEY_KEYLINES = "keylines";
+
+ private static final String JSON_KEY_OFFSET = "offset";
+ private static final String JSON_KEY_SIZE = "size";
+ private static final String JSON_KEY_FROM = "from";
+
+ private static final String JSON_KEY_SPACINGS_VISIBLE = "spacingsVisible";
+ private static final String JSON_KEY_SPACINGS_COLOR = "spacingsColor";
+ private static final String JSON_KEY_SPACINGS = "spacings";
+
+ /**
+ * Defined the reference point from which keyline/spacing offsets and sizes
+ * will be calculated.
+ */
+ public enum From {
+ LEFT,
+ RIGHT,
+ TOP,
+ BOTTOM,
+ VERTICAL_CENTER,
+ HORIZONTAL_CENTER
+ }
+
+ private static class Keyline {
+ public final float position;
+ public final From from;
+
+ public Keyline(float position, From from) {
+ this.position = position;
+ this.from = from;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Keyline)) {
+ return false;
+ }
+
+ if (o == this) {
+ return true;
+ }
+
+ final Keyline other = (Keyline) o;
+ return (this.position == other.position && this.from == other.from);
+ }
+ }
+
+ private static class Spacing {
+ public final float offset;
+ public final float size;
+ public final From from;
+
+ public Spacing(float offset, float size, From from) {
+ this.offset = offset;
+ this.size = size;
+ this.from = from;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Keyline)) {
+ return false;
+ }
+
+ if (o == this) {
+ return true;
+ }
+
+ final Spacing other = (Spacing) o;
+ return (this.offset == other.offset &&
+ this.size == other.size &&
+ this.from == other.from);
+ }
+ }
+
+ private final View mHostView;
+
+ private final float mDensity;
+
+ private boolean mBaselineGridVisible = DEFAULT_BASELINE_GRID_VISIBLE;
+ private float mBaselineGridCellSize;
+ private final Paint mBaselineGridPaint;
+
+ private boolean mKeylinesVisible = DEFAULT_KEYLINES_VISIBLE;
+ private final Paint mKeylinesPaint;
+ private final List<Keyline> mKeylines;
+
+ private boolean mSpacingsVisible = DEFAULT_SPACINGS_VISIBLE;
+ private final Paint mSpacingsPaint;
+ private final List<Spacing> mSpacings;
+
+ public DesignSpec(Resources resources, View hostView) {
+ mHostView = hostView;
+ mDensity = resources.getDisplayMetrics().density;
+
+ mKeylines = new ArrayList<Keyline>();
+ mSpacings = new ArrayList<Spacing>();
+
+ mBaselineGridPaint = new Paint();
+ mBaselineGridPaint.setColor(Color.parseColor(DEFAULT_BASELINE_GRID_COLOR));
+
+ mKeylinesPaint = new Paint();
+ mKeylinesPaint.setStrokeWidth(KEYLINE_STROKE_WIDTH_DIP * mDensity);
+ mKeylinesPaint.setColor(Color.parseColor(DEFAULT_KEYLINE_COLOR));
+
+ mSpacingsPaint = new Paint();
+ mSpacingsPaint.setColor(Color.parseColor(DEFAULT_SPACING_COLOR));
+
+ mBaselineGridCellSize = mDensity * DEFAULT_BASELINE_GRID_CELL_SIZE_DIP;
+ }
+
+ /**
+ * Whether or not the baseline grid should be drawn.
+ */
+ public boolean isBaselineGridVisible() {
+ return mBaselineGridVisible;
+ }
+
+ /**
+ * Sets the baseline grid visibility.
+ */
+ public DesignSpec setBaselineGridVisible(boolean visible) {
+ if (mBaselineGridVisible == visible) {
+ return this;
+ }
+
+ mBaselineGridVisible = visible;
+ invalidateSelf();
+
+ return this;
+ }
+
+ /**
+ * Sets the size of the baseline grid cells. By default, it uses the
+ * material design 8dp cell size.
+ */
+ public DesignSpec setBaselineGridCellSize(float cellSize) {
+ if (mBaselineGridCellSize == cellSize) {
+ return this;
+ }
+
+ mBaselineGridCellSize = cellSize;
+ invalidateSelf();
+
+ return this;
+ }
+
+ /**
+ * Sets the baseline grid color.
+ */
+ public DesignSpec setBaselineGridColor(int color) {
+ if (mBaselineGridPaint.getColor() == color) {
+ return this;
+ }
+
+ mBaselineGridPaint.setColor(color);
+ invalidateSelf();
+
+ return this;
+ }
+
+ /**
+ * Whether or not the keylines should be drawn.
+ */
+ public boolean areKeylinesVisible() {
+ return mKeylinesVisible;
+ }
+
+ /**
+ * Sets the visibility of keylines.
+ */
+ public DesignSpec setKeylinesVisible(boolean visible) {
+ if (mKeylinesVisible == visible) {
+ return this;
+ }
+
+ mKeylinesVisible = visible;
+ invalidateSelf();
+
+ return this;
+ }
+
+ /**
+ * Sets the keyline color.
+ */
+ public DesignSpec setKeylinesColor(int color) {
+ if (mKeylinesPaint.getColor() == color) {
+ return this;
+ }
+
+ mKeylinesPaint.setColor(color);
+ invalidateSelf();
+
+ return this;
+ }
+
+ /**
+ * Adds a keyline to the {@link DesignSpec}.
+ */
+ public DesignSpec addKeyline(float position, From from) {
+ final Keyline keyline = new Keyline(position * mDensity, from);
+ if (mKeylines.contains(keyline)) {
+ return this;
+ }
+
+ mKeylines.add(keyline);
+ return this;
+ }
+
+ /**
+ * Whether or not the spacing markers should be drawn.
+ */
+ public boolean areSpacingsVisible() {
+ return mSpacingsVisible;
+ }
+
+ /**
+ * Sets the visibility of spacing markers.
+ */
+ public DesignSpec setSpacingsVisible(boolean visible) {
+ if (mSpacingsVisible == visible) {
+ return this;
+ }
+
+ mSpacingsVisible = visible;
+ invalidateSelf();
+
+ return this;
+ }
+
+ /**
+ * Sets the spacing mark color.
+ */
+ public DesignSpec setSpacingsColor(int color) {
+ if (mSpacingsPaint.getColor() == color) {
+ return this;
+ }
+
+ mSpacingsPaint.setColor(color);
+ invalidateSelf();
+
+ return this;
+ }
+
+ /**
+ * Adds a spacing mark to the {@link DesignSpec}.
+ */
+ public DesignSpec addSpacing(float position, float size, From from) {
+ final Spacing spacing = new Spacing(position * mDensity, size * mDensity, from);
+ if (mSpacings.contains(spacing)) {
+ return this;
+ }
+
+ mSpacings.add(spacing);
+ return this;
+ }
+
+ private void drawBaselineGrid(Canvas canvas) {
+ if (!mBaselineGridVisible) {
+ return;
+ }
+
+ final int width = getIntrinsicWidth();
+ final int height = getIntrinsicHeight();
+
+ float x = mBaselineGridCellSize;
+ while (x < width) {
+ canvas.drawLine(x, 0, x, height, mBaselineGridPaint);
+ x += mBaselineGridCellSize;
+ }
+
+ float y = mBaselineGridCellSize;
+ while (y < height) {
+ canvas.drawLine(0, y, width, y, mBaselineGridPaint);
+ y += mBaselineGridCellSize;
+ }
+ }
+
+ private void drawKeylines(Canvas canvas) {
+ if (!mKeylinesVisible) {
+ return;
+ }
+
+ final int width = getIntrinsicWidth();
+ final int height = getIntrinsicHeight();
+
+ final int count = mKeylines.size();
+ for (int i = 0; i < count; i++) {
+ final Keyline keyline = mKeylines.get(i);
+
+ final float position;
+ switch (keyline.from) {
+ case LEFT:
+ case TOP:
+ position = keyline.position;
+ break;
+
+ case RIGHT:
+ position = width - keyline.position;
+ break;
+
+ case BOTTOM:
+ position = height - keyline.position;
+ break;
+
+ case VERTICAL_CENTER:
+ position = (height / 2) + keyline.position;
+ break;
+
+ case HORIZONTAL_CENTER:
+ position = (width / 2) + keyline.position;
+ break;
+
+ default:
+ throw new IllegalStateException("Invalid keyline offset");
+ }
+
+ switch (keyline.from) {
+ case LEFT:
+ case RIGHT:
+ case HORIZONTAL_CENTER:
+ canvas.drawLine(position, 0, position, height, mKeylinesPaint);
+ break;
+
+ case TOP:
+ case BOTTOM:
+ case VERTICAL_CENTER:
+ canvas.drawLine(0, position, width, position, mKeylinesPaint);
+ break;
+ }
+ }
+ }
+
+ private void drawSpacings(Canvas canvas) {
+ if (!mSpacingsVisible) {
+ return;
+ }
+
+ final int width = getIntrinsicWidth();
+ final int height = getIntrinsicHeight();
+
+ final int count = mSpacings.size();
+ for (int i = 0; i < count; i++) {
+ final Spacing spacing = mSpacings.get(i);
+
+ final float position1;
+ final float position2;
+ switch (spacing.from) {
+ case LEFT:
+ case TOP:
+ position1 = spacing.offset;
+ position2 = position1 + spacing.size;
+ break;
+
+ case RIGHT:
+ position1 = width - spacing.offset + spacing.size;
+ position2 = width - spacing.offset;
+ break;
+
+ case BOTTOM:
+ position1 = height - spacing.offset + spacing.size;
+ position2 = height - spacing.offset;
+ break;
+
+ case VERTICAL_CENTER:
+ position1 = (height / 2) + spacing.offset;
+ position2 = position1 + spacing.size;
+ break;
+
+ case HORIZONTAL_CENTER:
+ position1 = (width / 2) + spacing.offset;
+ position2 = position1 + spacing.size;
+ break;
+
+ default:
+ throw new IllegalStateException("Invalid spacing offset");
+ }
+
+ switch (spacing.from) {
+ case LEFT:
+ case RIGHT:
+ case HORIZONTAL_CENTER:
+ canvas.drawRect(position1, 0, position2, height, mSpacingsPaint);
+ break;
+
+ case TOP:
+ case BOTTOM:
+ case VERTICAL_CENTER:
+ canvas.drawRect(0, position1, width, position2, mSpacingsPaint);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Draws the {@link DesignSpec}. You should call this in your {@link View}'s
+ * {@link View#onDraw(Canvas)} method if you're not simply enclosing it with a
+ * {@link DesignSpecFrameLayout}.
+ */
+ @Override
+ public void draw(Canvas canvas) {
+ drawSpacings(canvas);
+ drawBaselineGrid(canvas);
+ drawKeylines(canvas);
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mHostView.getWidth();
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mHostView.getHeight();
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mBaselineGridPaint.setAlpha(alpha);
+ mKeylinesPaint.setAlpha(alpha);
+ mSpacingsPaint.setAlpha(alpha);
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter cf) {
+ mBaselineGridPaint.setColorFilter(cf);
+ mKeylinesPaint.setColorFilter(cf);
+ mSpacingsPaint.setColorFilter(cf);
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ /**
+ * Creates a new {@link DesignSpec} instance from a resource ID using a {@link View}
+ * that will provide the {@link DesignSpec}'s intrinsic dimensions.
+ *
+ * @param view The {@link View} who will own the new {@link DesignSpec} instance.
+ * @param resId The resource ID pointing to a raw JSON resource.
+ * @return The newly created {@link DesignSpec} instance.
+ */
+ public static DesignSpec fromResource(View view, int resId) {
+ final Resources resources = view.getResources();
+ final DesignSpec spec = new DesignSpec(resources, view);
+ if (resId == 0) {
+ return spec;
+ }
+
+ final JSONObject json;
+ try {
+ json = RawResource.getAsJSON(resources, resId);
+ } catch (IOException e) {
+ throw new IllegalStateException("Could not read design spec resource", e);
+ }
+
+ final float density = resources.getDisplayMetrics().density;
+
+ spec.setBaselineGridCellSize(density * json.optInt(JSON_KEY_BASELINE_GRID_CELL_SIZE,
+ DEFAULT_BASELINE_GRID_CELL_SIZE_DIP));
+
+ spec.setBaselineGridVisible(json.optBoolean(JSON_KEY_BASELINE_GRID_VISIBLE,
+ DEFAULT_BASELINE_GRID_VISIBLE));
+ spec.setKeylinesVisible(json.optBoolean(JSON_KEY_KEYLINES_VISIBLE,
+ DEFAULT_KEYLINES_VISIBLE));
+ spec.setSpacingsVisible(json.optBoolean(JSON_KEY_SPACINGS_VISIBLE,
+ DEFAULT_SPACINGS_VISIBLE));
+
+ spec.setBaselineGridColor(Color.parseColor(json.optString(JSON_KEY_BASELINE_GRID_COLOR,
+ DEFAULT_BASELINE_GRID_COLOR)));
+ spec.setKeylinesColor(Color.parseColor(json.optString(JSON_KEY_KEYLINES_COLOR,
+ DEFAULT_KEYLINE_COLOR)));
+ spec.setSpacingsColor(Color.parseColor(json.optString(JSON_KEY_SPACINGS_COLOR,
+ DEFAULT_SPACING_COLOR)));
+
+ final JSONArray keylines = json.optJSONArray(JSON_KEY_KEYLINES);
+ if (keylines != null) {
+ final int keylineCount = keylines.length();
+ for (int i = 0; i < keylineCount; i++) {
+ try {
+ final JSONObject keyline = keylines.getJSONObject(i);
+ spec.addKeyline(keyline.getInt(JSON_KEY_OFFSET),
+ From.valueOf(keyline.getString(JSON_KEY_FROM).toUpperCase()));
+ } catch (JSONException e) {
+ continue;
+ }
+ }
+ }
+
+ final JSONArray spacings = json.optJSONArray(JSON_KEY_SPACINGS);
+ if (spacings != null) {
+ final int spacingCount = spacings.length();
+ for (int i = 0; i < spacingCount; i++) {
+ try {
+ final JSONObject spacing = spacings.getJSONObject(i);
+ spec.addSpacing(spacing.getInt(JSON_KEY_OFFSET), spacing.getInt(JSON_KEY_SIZE),
+ From.valueOf(spacing.getString(JSON_KEY_FROM).toUpperCase()));
+ } catch (JSONException e) {
+ continue;
+ }
+ }
+ }
+
+ return spec;
+ }
+}
diff --git a/mobile/android/thirdparty/org/lucasr/dspec/RawResource.java b/mobile/android/thirdparty/org/lucasr/dspec/RawResource.java
new file mode 100644
index 000000000..f2e743b11
--- /dev/null
+++ b/mobile/android/thirdparty/org/lucasr/dspec/RawResource.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 Lucas Rocha
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * 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 org.lucasr.dspec;
+
+import android.content.Context;
+import android.content.res.Resources;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.StringWriter;
+
+class RawResource {
+ public static JSONObject getAsJSON(Resources resources, int id) throws IOException {
+ InputStreamReader reader = null;
+
+ try {
+ final InputStream is = resources.openRawResource(id);
+ if (is == null) {
+ return null;
+ }
+
+ reader = new InputStreamReader(is, "UTF-8");
+
+ final char[] buffer = new char[1024];
+ final StringWriter s = new StringWriter();
+
+ int n;
+ while ((n = reader.read(buffer, 0, buffer.length)) != -1) {
+ s.write(buffer, 0, n);
+ }
+
+ return new JSONObject(s.toString());
+ } catch (JSONException e) {
+ throw new IllegalStateException("Invalid design spec JSON resource", e);
+ } finally {
+ if (reader != null) {
+ reader.close();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/BinaryDecoder.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/BinaryDecoder.java
new file mode 100644
index 000000000..82e77e009
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/BinaryDecoder.java
@@ -0,0 +1,43 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec;
+
+/**
+ * Defines common decoding methods for byte array decoders.
+ *
+ * @author Apache Software Foundation
+ * @version $Id: BinaryDecoder.java 1075406 2011-02-28 16:18:26Z ggregory $
+ */
+public interface BinaryDecoder extends Decoder {
+
+ /**
+ * Decodes a byte array and returns the results as a byte array.
+ *
+ * @param source A byte array which has been encoded with the
+ * appropriate encoder
+ *
+ * @return a byte array that contains decoded content
+ *
+ * @throws DecoderException A decoder exception is thrown
+ * if a Decoder encounters a failure condition during
+ * the decode process.
+ */
+ byte[] decode(byte[] source) throws DecoderException;
+}
+
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/BinaryEncoder.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/BinaryEncoder.java
new file mode 100644
index 000000000..5b1be202c
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/BinaryEncoder.java
@@ -0,0 +1,43 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec;
+
+/**
+ * Defines common encoding methods for byte array encoders.
+ *
+ * @author Apache Software Foundation
+ * @version $Id: BinaryEncoder.java 1075406 2011-02-28 16:18:26Z ggregory $
+ */
+public interface BinaryEncoder extends Encoder {
+
+ /**
+ * Encodes a byte array and return the encoded data
+ * as a byte array.
+ *
+ * @param source Data to be encoded
+ *
+ * @return A byte array containing the encoded data
+ *
+ * @throws EncoderException thrown if the Encoder
+ * encounters a failure condition during the
+ * encoding process.
+ */
+ byte[] encode(byte[] source) throws EncoderException;
+}
+
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/CharEncoding.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/CharEncoding.java
new file mode 100644
index 000000000..c4227fb0e
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/CharEncoding.java
@@ -0,0 +1,127 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec;
+
+/**
+ * Character encoding names required of every implementation of the Java platform.
+ *
+ * From the Java documentation <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard
+ * charsets</a>:
+ * <p>
+ * <cite>Every implementation of the Java platform is required to support the following character encodings. Consult the
+ * release documentation for your implementation to see if any other encodings are supported. Consult the release
+ * documentation for your implementation to see if any other encodings are supported. </cite>
+ * </p>
+ *
+ * <ul>
+ * <li><code>US-ASCII</code><br/>
+ * Seven-bit ASCII, a.k.a. ISO646-US, a.k.a. the Basic Latin block of the Unicode character set.</li>
+ * <li><code>ISO-8859-1</code><br/>
+ * ISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1.</li>
+ * <li><code>UTF-8</code><br/>
+ * Eight-bit Unicode Transformation Format.</li>
+ * <li><code>UTF-16BE</code><br/>
+ * Sixteen-bit Unicode Transformation Format, big-endian byte order.</li>
+ * <li><code>UTF-16LE</code><br/>
+ * Sixteen-bit Unicode Transformation Format, little-endian byte order.</li>
+ * <li><code>UTF-16</code><br/>
+ * Sixteen-bit Unicode Transformation Format, byte order specified by a mandatory initial byte-order mark (either order
+ * accepted on input, big-endian used on output.)</li>
+ * </ul>
+ *
+ * This perhaps would best belong in the [lang] project. Even if a similar interface is defined in [lang], it is not
+ * forseen that [codec] would be made to depend on [lang].
+ *
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ * @author Apache Software Foundation
+ * @since 1.4
+ * @version $Id: CharEncoding.java 797857 2009-07-25 23:43:33Z ggregory $
+ */
+public class CharEncoding {
+ /**
+ * CharEncodingISO Latin Alphabet No. 1, a.k.a. ISO-LATIN-1. </p>
+ * <p>
+ * Every implementation of the Java platform is required to support this character encoding.
+ * </p>
+ *
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ */
+ public static final String ISO_8859_1 = "ISO-8859-1";
+
+ /**
+ * <p>
+ * Seven-bit ASCII, also known as ISO646-US, also known as the Basic Latin block of the Unicode character set.
+ * </p>
+ * <p>
+ * Every implementation of the Java platform is required to support this character encoding.
+ * </p>
+ *
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ */
+ public static final String US_ASCII = "US-ASCII";
+
+ /**
+ * <p>
+ * Sixteen-bit Unicode Transformation Format, The byte order specified by a mandatory initial byte-order mark
+ * (either order accepted on input, big-endian used on output)
+ * </p>
+ * <p>
+ * Every implementation of the Java platform is required to support this character encoding.
+ * </p>
+ *
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ */
+ public static final String UTF_16 = "UTF-16";
+
+ /**
+ * <p>
+ * Sixteen-bit Unicode Transformation Format, big-endian byte order.
+ * </p>
+ * <p>
+ * Every implementation of the Java platform is required to support this character encoding.
+ * </p>
+ *
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ */
+ public static final String UTF_16BE = "UTF-16BE";
+
+ /**
+ * <p>
+ * Sixteen-bit Unicode Transformation Format, little-endian byte order.
+ * </p>
+ * <p>
+ * Every implementation of the Java platform is required to support this character encoding.
+ * </p>
+ *
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ */
+ public static final String UTF_16LE = "UTF-16LE";
+
+ /**
+ * <p>
+ * Eight-bit Unicode Transformation Format.
+ * </p>
+ * <p>
+ * Every implementation of the Java platform is required to support this character encoding.
+ * </p>
+ *
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ */
+ public static final String UTF_8 = "UTF-8";
+} \ No newline at end of file
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/Decoder.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/Decoder.java
new file mode 100644
index 000000000..5194feae2
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/Decoder.java
@@ -0,0 +1,56 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec;
+
+/**
+ * <p>Provides the highest level of abstraction for Decoders.
+ * This is the sister interface of {@link Encoder}. All
+ * Decoders implement this common generic interface.</p>
+ *
+ * <p>Allows a user to pass a generic Object to any Decoder
+ * implementation in the codec package.</p>
+ *
+ * <p>One of the two interfaces at the center of the codec package.</p>
+ *
+ * @author Apache Software Foundation
+ * @version $Id: Decoder.java 1075404 2011-02-28 16:17:29Z ggregory $
+ */
+public interface Decoder {
+
+ /**
+ * Decodes an "encoded" Object and returns a "decoded"
+ * Object. Note that the implementation of this
+ * interface will try to cast the Object parameter
+ * to the specific type expected by a particular Decoder
+ * implementation. If a {@link ClassCastException} occurs
+ * this decode method will throw a DecoderException.
+ *
+ * @param source the object to decode
+ *
+ * @return a 'decoded" object
+ *
+ * @throws DecoderException a decoder exception can
+ * be thrown for any number of reasons. Some good
+ * candidates are that the parameter passed to this
+ * method is null, a param cannot be cast to the
+ * appropriate type for a specific encoder.
+ */
+ Object decode(Object source) throws DecoderException;
+}
+
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/DecoderException.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/DecoderException.java
new file mode 100644
index 000000000..88108a548
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/DecoderException.java
@@ -0,0 +1,90 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec;
+
+/**
+ * Thrown when there is a failure condition during the decoding process. This exception is thrown when a {@link Decoder}
+ * encounters a decoding specific exception such as invalid data, or characters outside of the expected range.
+ *
+ * @author Apache Software Foundation
+ * @version $Id: DecoderException.java 1080701 2011-03-11 17:52:27Z ggregory $
+ */
+public class DecoderException extends Exception {
+
+ /**
+ * Declares the Serial Version Uid.
+ *
+ * @see <a href="http://c2.com/cgi/wiki?AlwaysDeclareSerialVersionUid">Always Declare Serial Version Uid</a>
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a new exception with <code>null</code> as its detail message. The cause is not initialized, and may
+ * subsequently be initialized by a call to {@link #initCause}.
+ *
+ * @since 1.4
+ */
+ public DecoderException() {
+ super();
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently
+ * be initialized by a call to {@link #initCause}.
+ *
+ * @param message
+ * The detail message which is saved for later retrieval by the {@link #getMessage()} method.
+ */
+ public DecoderException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructsa new exception with the specified detail message and cause.
+ *
+ * <p>
+ * Note that the detail message associated with <code>cause</code> is not automatically incorporated into this
+ * exception's detail message.
+ * </p>
+ *
+ * @param message
+ * The detail message which is saved for later retrieval by the {@link #getMessage()} method.
+ * @param cause
+ * The cause which is saved for later retrieval by the {@link #getCause()} method. A <code>null</code>
+ * value is permitted, and indicates that the cause is nonexistent or unknown.
+ * @since 1.4
+ */
+ public DecoderException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs a new exception with the specified cause and a detail message of <code>(cause==null ?
+ * null : cause.toString())</code> (which typically contains the class and detail message of <code>cause</code>).
+ * This constructor is useful for exceptions that are little more than wrappers for other throwables.
+ *
+ * @param cause
+ * The cause which is saved for later retrieval by the {@link #getCause()} method. A <code>null</code>
+ * value is permitted, and indicates that the cause is nonexistent or unknown.
+ * @since 1.4
+ */
+ public DecoderException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/Encoder.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/Encoder.java
new file mode 100644
index 000000000..1b81af9b2
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/Encoder.java
@@ -0,0 +1,47 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec;
+
+/**
+ * <p>Provides the highest level of abstraction for Encoders.
+ * This is the sister interface of {@link Decoder}. Every implementation of
+ * Encoder provides this common generic interface whic allows a user to pass a
+ * generic Object to any Encoder implementation in the codec package.</p>
+ *
+ * @author Apache Software Foundation
+ * @version $Id: Encoder.java 1075406 2011-02-28 16:18:26Z ggregory $
+ */
+public interface Encoder {
+
+ /**
+ * Encodes an "Object" and returns the encoded content
+ * as an Object. The Objects here may just be <code>byte[]</code>
+ * or <code>String</code>s depending on the implementation used.
+ *
+ * @param source An object ot encode
+ *
+ * @return An "encoded" Object
+ *
+ * @throws EncoderException an encoder exception is
+ * thrown if the encoder experiences a failure
+ * condition during the encoding process.
+ */
+ Object encode(Object source) throws EncoderException;
+}
+
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/EncoderException.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/EncoderException.java
new file mode 100644
index 000000000..a858abccd
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/EncoderException.java
@@ -0,0 +1,91 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec;
+
+/**
+ * Thrown when there is a failure condition during the encoding process. This exception is thrown when an
+ * {@link Encoder} encounters a encoding specific exception such as invalid data, inability to calculate a checksum,
+ * characters outside of the expected range.
+ *
+ * @author Apache Software Foundation
+ * @version $Id: EncoderException.java 1080701 2011-03-11 17:52:27Z ggregory $
+ */
+public class EncoderException extends Exception {
+
+ /**
+ * Declares the Serial Version Uid.
+ *
+ * @see <a href="http://c2.com/cgi/wiki?AlwaysDeclareSerialVersionUid">Always Declare Serial Version Uid</a>
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a new exception with <code>null</code> as its detail message. The cause is not initialized, and may
+ * subsequently be initialized by a call to {@link #initCause}.
+ *
+ * @since 1.4
+ */
+ public EncoderException() {
+ super();
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message. The cause is not initialized, and may subsequently
+ * be initialized by a call to {@link #initCause}.
+ *
+ * @param message
+ * a useful message relating to the encoder specific error.
+ */
+ public EncoderException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message and cause.
+ *
+ * <p>
+ * Note that the detail message associated with <code>cause</code> is not automatically incorporated into this
+ * exception's detail message.
+ * </p>
+ *
+ * @param message
+ * The detail message which is saved for later retrieval by the {@link #getMessage()} method.
+ * @param cause
+ * The cause which is saved for later retrieval by the {@link #getCause()} method. A <code>null</code>
+ * value is permitted, and indicates that the cause is nonexistent or unknown.
+ * @since 1.4
+ */
+ public EncoderException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs a new exception with the specified cause and a detail message of <code>(cause==null ?
+ * null : cause.toString())</code> (which typically contains the class and detail message of <code>cause</code>).
+ * This constructor is useful for exceptions that are little more than wrappers for other throwables.
+ *
+ * @param cause
+ * The cause which is saved for later retrieval by the {@link #getCause()} method. A <code>null</code>
+ * value is permitted, and indicates that the cause is nonexistent or unknown.
+ * @since 1.4
+ */
+ public EncoderException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringDecoder.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringDecoder.java
new file mode 100644
index 000000000..a112485b3
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringDecoder.java
@@ -0,0 +1,41 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec;
+
+/**
+ * Defines common decoding methods for String decoders.
+ *
+ * @author Apache Software Foundation
+ * @version $Id: StringDecoder.java 1080701 2011-03-11 17:52:27Z ggregory $
+ */
+public interface StringDecoder extends Decoder {
+
+ /**
+ * Decodes a String and returns a String.
+ *
+ * @param source the String to decode
+ *
+ * @return the encoded String
+ *
+ * @throws DecoderException thrown if there is
+ * an error condition during the Encoding process.
+ */
+ String decode(String source) throws DecoderException;
+}
+
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringEncoder.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringEncoder.java
new file mode 100644
index 000000000..2bcc5165d
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringEncoder.java
@@ -0,0 +1,41 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec;
+
+/**
+ * Defines common encoding methods for String encoders.
+ *
+ * @author Apache Software Foundation
+ * @version $Id: StringEncoder.java 1080701 2011-03-11 17:52:27Z ggregory $
+ */
+public interface StringEncoder extends Encoder {
+
+ /**
+ * Encodes a String and returns a String.
+ *
+ * @param source the String to encode
+ *
+ * @return the encoded String
+ *
+ * @throws EncoderException thrown if there is
+ * an error conidition during the Encoding process.
+ */
+ String encode(String source) throws EncoderException;
+}
+
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringEncoderComparator.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringEncoderComparator.java
new file mode 100644
index 000000000..8923df571
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringEncoderComparator.java
@@ -0,0 +1,87 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec;
+
+import java.util.Comparator;
+
+/**
+ * Compares Strings using a {@link StringEncoder}. This comparator is used to sort Strings by an encoding scheme such as
+ * Soundex, Metaphone, etc. This class can come in handy if one need to sort Strings by an encoded form of a name such
+ * as Soundex.
+ *
+ * @author Apache Software Foundation
+ * @version $Id: StringEncoderComparator.java 1080701 2011-03-11 17:52:27Z ggregory $
+ */
+@SuppressWarnings("rawtypes")
+public class StringEncoderComparator implements Comparator {
+
+ /**
+ * Internal encoder instance.
+ */
+ private final StringEncoder stringEncoder;
+
+ /**
+ * Constructs a new instance.
+ *
+ * @deprecated Creating an instance without a {@link StringEncoder} leads to a {@link NullPointerException}. Will be
+ * removed in 2.0.
+ */
+ public StringEncoderComparator() {
+ this.stringEncoder = null; // Trying to use this will cause things to break
+ }
+
+ /**
+ * Constructs a new instance with the given algorithm.
+ *
+ * @param stringEncoder
+ * the StringEncoder used for comparisons.
+ */
+ public StringEncoderComparator(StringEncoder stringEncoder) {
+ this.stringEncoder = stringEncoder;
+ }
+
+ /**
+ * Compares two strings based not on the strings themselves, but on an encoding of the two strings using the
+ * StringEncoder this Comparator was created with.
+ *
+ * If an {@link EncoderException} is encountered, return <code>0</code>.
+ *
+ * @param o1
+ * the object to compare
+ * @param o2
+ * the object to compare to
+ * @return the Comparable.compareTo() return code or 0 if an encoding error was caught.
+ * @see Comparable
+ */
+ @SuppressWarnings("unchecked")
+ public int compare(Object o1, Object o2) {
+
+ int compareCode = 0;
+
+ try {
+ Comparable s1 = (Comparable) this.stringEncoder.encode(o1);
+ Comparable s2 = (Comparable) this.stringEncoder.encode(o2);
+ compareCode = s1.compareTo(s2);
+ } catch (EncoderException ee) {
+ compareCode = 0;
+ }
+ return compareCode;
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32.java
new file mode 100644
index 000000000..d0d923e62
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32.java
@@ -0,0 +1,471 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.binary;
+
+/**
+ * Provides Base32 encoding and decoding as defined by <a href="http://www.ietf.org/rfc/rfc4648.txt">RFC 4648</a>.
+ *
+ * <p>
+ * The class can be parameterized in the following manner with various constructors:
+ * <ul>
+ * <li>Whether to use the "base32hex" variant instead of the default "base32"</li>
+ * <li>Line length: Default 76. Line length that aren't multiples of 8 will still essentially end up being multiples of
+ * 8 in the encoded data.
+ * <li>Line separator: Default is CRLF ("\r\n")</li>
+ * </ul>
+ * </p>
+ * <p>
+ * This class operates directly on byte streams, and not character streams.
+ * </p>
+ * <p>
+ * This class is not thread-safe. Each thread should use its own instance.
+ * </p>
+ *
+ * @see <a href="http://www.ietf.org/rfc/rfc4648.txt">RFC 4648</a>
+ *
+ * @since 1.5
+ * @version $Revision: 1080712 $
+ */
+public class Base32 extends BaseNCodec {
+
+ /**
+ * BASE32 characters are 5 bits in length.
+ * They are formed by taking a block of five octets to form a 40-bit string,
+ * which is converted into eight BASE32 characters.
+ */
+ private static final int BITS_PER_ENCODED_BYTE = 5;
+ private static final int BYTES_PER_ENCODED_BLOCK = 8;
+ private static final int BYTES_PER_UNENCODED_BLOCK = 5;
+
+ /**
+ * Chunk separator per RFC 2045 section 2.1.
+ *
+ * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
+ */
+ private static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};
+
+ /**
+ * This array is a lookup table that translates Unicode characters drawn from the "Base32 Alphabet" (as specified in
+ * Table 3 of RFC 2045) into their 5-bit positive integer equivalents. Characters that are not in the Base32
+ * alphabet but fall within the bounds of the array are translated to -1.
+ *
+ */
+ private static final byte[] DECODE_TABLE = {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 63, // 20-2f
+ -1, -1, 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, -1, // 30-3f 2-7
+ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 40-4f A-N
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 50-5a O-Z
+ };
+
+ /**
+ * This array is a lookup table that translates 5-bit positive integer index values into their "Base32 Alphabet"
+ * equivalents as specified in Table 3 of RFC 2045.
+ */
+ private static final byte[] ENCODE_TABLE = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ '2', '3', '4', '5', '6', '7',
+ };
+
+ /**
+ * This array is a lookup table that translates Unicode characters drawn from the "Base32 |Hex Alphabet" (as specified in
+ * Table 3 of RFC 2045) into their 5-bit positive integer equivalents. Characters that are not in the Base32 Hex
+ * alphabet but fall within the bounds of the array are translated to -1.
+ *
+ */
+ private static final byte[] HEX_DECODE_TABLE = {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 00-0f
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 10-1f
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 63, // 20-2f
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, // 30-3f 2-7
+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 40-4f A-N
+ 25, 26, 27, 28, 29, 30, 31, 32, // 50-57 O-V
+ };
+
+ /**
+ * This array is a lookup table that translates 5-bit positive integer index values into their "Base32 Hex Alphabet"
+ * equivalents as specified in Table 3 of RFC 2045.
+ */
+ private static final byte[] HEX_ENCODE_TABLE = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+ };
+
+ /** Mask used to extract 5 bits, used when encoding Base32 bytes */
+ private static final int MASK_5BITS = 0x1f;
+
+ // The static final fields above are used for the original static byte[] methods on Base32.
+ // The private member fields below are used with the new streaming approach, which requires
+ // some state be preserved between calls of encode() and decode().
+
+ /**
+ * Place holder for the bytes we're dealing with for our based logic.
+ * Bitwise operations store and extract the encoding or decoding from this variable.
+ */
+ private long bitWorkArea;
+
+ /**
+ * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
+ * <code>decodeSize = {@link BYTES_PER_ENCODED_BLOCK} - 1 + lineSeparator.length;</code>
+ */
+ private final int decodeSize;
+
+ /**
+ * Decode table to use.
+ */
+ private final byte[] decodeTable;
+
+ /**
+ * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
+ * <code>encodeSize = {@link BYTES_PER_ENCODED_BLOCK} + lineSeparator.length;</code>
+ */
+ private final int encodeSize;
+
+ /**
+ * Encode table to use.
+ */
+ private final byte[] encodeTable;
+
+ /**
+ * Line separator for encoding. Not used when decoding. Only used if lineLength > 0.
+ */
+ private final byte[] lineSeparator;
+
+ /**
+ * Creates a Base32 codec used for decoding and encoding.
+ * <p>
+ * When encoding the line length is 0 (no chunking).
+ * </p>
+ *
+ */
+ public Base32() {
+ this(false);
+ }
+
+ /**
+ * Creates a Base32 codec used for decoding and encoding.
+ * <p>
+ * When encoding the line length is 0 (no chunking).
+ * </p>
+ * @param useHex if <code>true</code> then use Base32 Hex alphabet
+ */
+ public Base32(boolean useHex) {
+ this(0, null, useHex);
+ }
+
+ /**
+ * Creates a Base32 codec used for decoding and encoding.
+ * <p>
+ * When encoding the line length is given in the constructor, the line separator is CRLF.
+ * </p>
+ *
+ * @param lineLength
+ * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 8).
+ * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
+ */
+ public Base32(int lineLength) {
+ this(lineLength, CHUNK_SEPARATOR);
+ }
+
+ /**
+ * Creates a Base32 codec used for decoding and encoding.
+ * <p>
+ * When encoding the line length and line separator are given in the constructor.
+ * </p>
+ * <p>
+ * Line lengths that aren't multiples of 8 will still essentially end up being multiples of 8 in the encoded data.
+ * </p>
+ *
+ * @param lineLength
+ * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 8).
+ * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
+ * @param lineSeparator
+ * Each line of encoded data will end with this sequence of bytes.
+ * @throws IllegalArgumentException
+ * The provided lineSeparator included some Base32 characters. That's not going to work!
+ */
+ public Base32(int lineLength, byte[] lineSeparator) {
+ this(lineLength, lineSeparator, false);
+ }
+
+ /**
+ * Creates a Base32 / Base32 Hex codec used for decoding and encoding.
+ * <p>
+ * When encoding the line length and line separator are given in the constructor.
+ * </p>
+ * <p>
+ * Line lengths that aren't multiples of 8 will still essentially end up being multiples of 8 in the encoded data.
+ * </p>
+ *
+ * @param lineLength
+ * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 8).
+ * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
+ * @param lineSeparator
+ * Each line of encoded data will end with this sequence of bytes.
+ * @param useHex if <code>true</code>, then use Base32 Hex alphabet, otherwise use Base32 alphabet
+ * @throws IllegalArgumentException
+ * The provided lineSeparator included some Base32 characters. That's not going to work!
+ * Or the lineLength > 0 and lineSeparator is null.
+ */
+ public Base32(int lineLength, byte[] lineSeparator, boolean useHex) {
+ super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK,
+ lineLength,
+ lineSeparator == null ? 0 : lineSeparator.length);
+ if (useHex){
+ this.encodeTable = HEX_ENCODE_TABLE;
+ this.decodeTable = HEX_DECODE_TABLE;
+ } else {
+ this.encodeTable = ENCODE_TABLE;
+ this.decodeTable = DECODE_TABLE;
+ }
+ if (lineLength > 0) {
+ if (lineSeparator == null) {
+ throw new IllegalArgumentException("lineLength "+lineLength+" > 0, but lineSeparator is null");
+ }
+ // Must be done after initializing the tables
+ if (containsAlphabetOrPad(lineSeparator)) {
+ String sep = StringUtils.newStringUtf8(lineSeparator);
+ throw new IllegalArgumentException("lineSeparator must not contain Base32 characters: [" + sep + "]");
+ }
+ this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length;
+ this.lineSeparator = new byte[lineSeparator.length];
+ System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
+ } else {
+ this.encodeSize = BYTES_PER_ENCODED_BLOCK;
+ this.lineSeparator = null;
+ }
+ this.decodeSize = this.encodeSize - 1;
+ }
+
+ /**
+ * <p>
+ * Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once
+ * with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The "-1"
+ * call is not necessary when decoding, but it doesn't hurt, either.
+ * </p>
+ * <p>
+ * Ignores all non-Base32 characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are
+ * silently ignored, but has implications for other bytes, too. This method subscribes to the garbage-in,
+ * garbage-out philosophy: it will not check the provided data for validity.
+ * </p>
+ *
+ * @param in
+ * byte[] array of ascii data to Base32 decode.
+ * @param inPos
+ * Position to start reading data from.
+ * @param inAvail
+ * Amount of bytes available from input for encoding.
+ *
+ * Output is written to {@link #buffer} as 8-bit octets, using {@link pos} as the buffer position
+ */
+ void decode(byte[] in, int inPos, int inAvail) { // package protected for access from I/O streams
+ if (eof) {
+ return;
+ }
+ if (inAvail < 0) {
+ eof = true;
+ }
+ for (int i = 0; i < inAvail; i++) {
+ byte b = in[inPos++];
+ if (b == PAD) {
+ // We're done.
+ eof = true;
+ break;
+ } else {
+ ensureBufferSize(decodeSize);
+ if (b >= 0 && b < this.decodeTable.length) {
+ int result = this.decodeTable[b];
+ if (result >= 0) {
+ modulus = (modulus+1) % BYTES_PER_ENCODED_BLOCK;
+ bitWorkArea = (bitWorkArea << BITS_PER_ENCODED_BYTE) + result; // collect decoded bytes
+ if (modulus == 0) { // we can output the 5 bytes
+ buffer[pos++] = (byte) ((bitWorkArea >> 32) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea >> 24) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+ buffer[pos++] = (byte) (bitWorkArea & MASK_8BITS);
+ }
+ }
+ }
+ }
+ }
+
+ // Two forms of EOF as far as Base32 decoder is concerned: actual
+ // EOF (-1) and first time '=' character is encountered in stream.
+ // This approach makes the '=' padding characters completely optional.
+ if (eof && modulus >= 2) { // if modulus < 2, nothing to do
+ ensureBufferSize(decodeSize);
+
+ // we ignore partial bytes, i.e. only multiples of 8 count
+ switch (modulus) {
+ case 2 : // 10 bits, drop 2 and output one byte
+ buffer[pos++] = (byte) ((bitWorkArea >> 2) & MASK_8BITS);
+ break;
+ case 3 : // 15 bits, drop 7 and output 1 byte
+ buffer[pos++] = (byte) ((bitWorkArea >> 7) & MASK_8BITS);
+ break;
+ case 4 : // 20 bits = 2*8 + 4
+ bitWorkArea = bitWorkArea >> 4; // drop 4 bits
+ buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
+ break;
+ case 5 : // 25bits = 3*8 + 1
+ bitWorkArea = bitWorkArea >> 1;
+ buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
+ break;
+ case 6 : // 30bits = 3*8 + 6
+ bitWorkArea = bitWorkArea >> 6;
+ buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
+ break;
+ case 7 : // 35 = 4*8 +3
+ bitWorkArea = bitWorkArea >> 3;
+ buffer[pos++] = (byte) ((bitWorkArea >> 24) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
+ break;
+ }
+ }
+ }
+
+ /**
+ * <p>
+ * Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with
+ * the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, so flush last
+ * remaining bytes (if not multiple of 5).
+ * </p>
+ *
+ * @param in
+ * byte[] array of binary data to Base32 encode.
+ * @param inPos
+ * Position to start reading data from.
+ * @param inAvail
+ * Amount of bytes available from input for encoding.
+ */
+ void encode(byte[] in, int inPos, int inAvail) { // package protected for access from I/O streams
+ if (eof) {
+ return;
+ }
+ // inAvail < 0 is how we're informed of EOF in the underlying data we're
+ // encoding.
+ if (inAvail < 0) {
+ eof = true;
+ if (0 == modulus && lineLength == 0) {
+ return; // no leftovers to process and not using chunking
+ }
+ ensureBufferSize(encodeSize);
+ int savedPos = pos;
+ switch (modulus) { // % 5
+ case 1 : // Only 1 octet; take top 5 bits then remainder
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 3) & MASK_5BITS]; // 8-1*5 = 3
+ buffer[pos++] = encodeTable[(int)(bitWorkArea << 2) & MASK_5BITS]; // 5-3=2
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ break;
+
+ case 2 : // 2 octets = 16 bits to use
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 11) & MASK_5BITS]; // 16-1*5 = 11
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 6) & MASK_5BITS]; // 16-2*5 = 6
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 1) & MASK_5BITS]; // 16-3*5 = 1
+ buffer[pos++] = encodeTable[(int)(bitWorkArea << 4) & MASK_5BITS]; // 5-1 = 4
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ break;
+ case 3 : // 3 octets = 24 bits to use
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 19) & MASK_5BITS]; // 24-1*5 = 19
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 14) & MASK_5BITS]; // 24-2*5 = 14
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 9) & MASK_5BITS]; // 24-3*5 = 9
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 4) & MASK_5BITS]; // 24-4*5 = 4
+ buffer[pos++] = encodeTable[(int)(bitWorkArea << 1) & MASK_5BITS]; // 5-4 = 1
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ break;
+ case 4 : // 4 octets = 32 bits to use
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 27) & MASK_5BITS]; // 32-1*5 = 27
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 22) & MASK_5BITS]; // 32-2*5 = 22
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 17) & MASK_5BITS]; // 32-3*5 = 17
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 12) & MASK_5BITS]; // 32-4*5 = 12
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 7) & MASK_5BITS]; // 32-5*5 = 7
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 2) & MASK_5BITS]; // 32-6*5 = 2
+ buffer[pos++] = encodeTable[(int)(bitWorkArea << 3) & MASK_5BITS]; // 5-2 = 3
+ buffer[pos++] = PAD;
+ break;
+ }
+ currentLinePos += pos - savedPos; // keep track of current line position
+ // if currentPos == 0 we are at the start of a line, so don't add CRLF
+ if (lineLength > 0 && currentLinePos > 0){ // add chunk separator if required
+ System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
+ pos += lineSeparator.length;
+ }
+ } else {
+ for (int i = 0; i < inAvail; i++) {
+ ensureBufferSize(encodeSize);
+ modulus = (modulus+1) % BYTES_PER_UNENCODED_BLOCK;
+ int b = in[inPos++];
+ if (b < 0) {
+ b += 256;
+ }
+ bitWorkArea = (bitWorkArea << 8) + b; // BITS_PER_BYTE
+ if (0 == modulus) { // we have enough bytes to create our output
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 35) & MASK_5BITS];
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 30) & MASK_5BITS];
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 25) & MASK_5BITS];
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 20) & MASK_5BITS];
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 15) & MASK_5BITS];
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 10) & MASK_5BITS];
+ buffer[pos++] = encodeTable[(int)(bitWorkArea >> 5) & MASK_5BITS];
+ buffer[pos++] = encodeTable[(int)bitWorkArea & MASK_5BITS];
+ currentLinePos += BYTES_PER_ENCODED_BLOCK;
+ if (lineLength > 0 && lineLength <= currentLinePos) {
+ System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
+ pos += lineSeparator.length;
+ currentLinePos = 0;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns whether or not the <code>octet</code> is in the Base32 alphabet.
+ *
+ * @param octet
+ * The value to test
+ * @return <code>true</code> if the value is defined in the the Base32 alphabet <code>false</code> otherwise.
+ */
+ public boolean isInAlphabet(byte octet) {
+ return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1;
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32InputStream.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32InputStream.java
new file mode 100644
index 000000000..acb284f9b
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32InputStream.java
@@ -0,0 +1,85 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.binary;
+
+import java.io.InputStream;
+
+/**
+ * Provides Base32 encoding and decoding in a streaming fashion (unlimited size). When encoding the default lineLength
+ * is 76 characters and the default lineEnding is CRLF, but these can be overridden by using the appropriate
+ * constructor.
+ * <p>
+ * The default behaviour of the Base32InputStream is to DECODE, whereas the default behaviour of the Base32OutputStream
+ * is to ENCODE, but this behaviour can be overridden by using a different constructor.
+ * </p>
+ * <p>
+ * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode
+ * character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc).
+ * </p>
+ *
+ * @version $Revision: 1063784 $
+ * @see <a href="http://www.ietf.org/rfc/rfc4648.txt">RFC 4648</a>
+ * @since 1.5
+ */
+public class Base32InputStream extends BaseNCodecInputStream {
+
+ /**
+ * Creates a Base32InputStream such that all data read is Base32-decoded from the original provided InputStream.
+ *
+ * @param in
+ * InputStream to wrap.
+ */
+ public Base32InputStream(InputStream in) {
+ this(in, false);
+ }
+
+ /**
+ * Creates a Base32InputStream such that all data read is either Base32-encoded or Base32-decoded from the original
+ * provided InputStream.
+ *
+ * @param in
+ * InputStream to wrap.
+ * @param doEncode
+ * true if we should encode all data read from us, false if we should decode.
+ */
+ public Base32InputStream(InputStream in, boolean doEncode) {
+ super(in, new Base32(false), doEncode);
+ }
+
+ /**
+ * Creates a Base32InputStream such that all data read is either Base32-encoded or Base32-decoded from the original
+ * provided InputStream.
+ *
+ * @param in
+ * InputStream to wrap.
+ * @param doEncode
+ * true if we should encode all data read from us, false if we should decode.
+ * @param lineLength
+ * If doEncode is true, each line of encoded data will contain lineLength characters (rounded down to
+ * nearest multiple of 4). If lineLength <=0, the encoded data is not divided into lines. If doEncode is
+ * false, lineLength is ignored.
+ * @param lineSeparator
+ * If doEncode is true, each line of encoded data will be terminated with this byte sequence (e.g. \r\n).
+ * If lineLength <= 0, the lineSeparator is not used. If doEncode is false lineSeparator is ignored.
+ */
+ public Base32InputStream(InputStream in, boolean doEncode, int lineLength, byte[] lineSeparator) {
+ super(in, new Base32(lineLength, lineSeparator), doEncode);
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32OutputStream.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32OutputStream.java
new file mode 100644
index 000000000..af2f4d718
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32OutputStream.java
@@ -0,0 +1,85 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.binary;
+
+import java.io.OutputStream;
+
+/**
+ * Provides Base32 encoding and decoding in a streaming fashion (unlimited size). When encoding the default lineLength
+ * is 76 characters and the default lineEnding is CRLF, but these can be overridden by using the appropriate
+ * constructor.
+ * <p>
+ * The default behaviour of the Base32OutputStream is to ENCODE, whereas the default behaviour of the Base32InputStream
+ * is to DECODE. But this behaviour can be overridden by using a different constructor.
+ * </p>
+ * <p>
+ * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode
+ * character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc).
+ * </p>
+ *
+ * @version $Revision: 1064132 $
+ * @see <a href="http://www.ietf.org/rfc/rfc4648.txt">RFC 4648</a>
+ * @since 1.5
+ */
+public class Base32OutputStream extends BaseNCodecOutputStream {
+
+ /**
+ * Creates a Base32OutputStream such that all data written is Base32-encoded to the original provided OutputStream.
+ *
+ * @param out
+ * OutputStream to wrap.
+ */
+ public Base32OutputStream(OutputStream out) {
+ this(out, true);
+ }
+
+ /**
+ * Creates a Base32OutputStream such that all data written is either Base32-encoded or Base32-decoded to the
+ * original provided OutputStream.
+ *
+ * @param out
+ * OutputStream to wrap.
+ * @param doEncode
+ * true if we should encode all data written to us, false if we should decode.
+ */
+ public Base32OutputStream(OutputStream out, boolean doEncode) {
+ super(out, new Base32(false), doEncode);
+ }
+
+ /**
+ * Creates a Base32OutputStream such that all data written is either Base32-encoded or Base32-decoded to the
+ * original provided OutputStream.
+ *
+ * @param out
+ * OutputStream to wrap.
+ * @param doEncode
+ * true if we should encode all data written to us, false if we should decode.
+ * @param lineLength
+ * If doEncode is true, each line of encoded data will contain lineLength characters (rounded down to
+ * nearest multiple of 4). If lineLength <=0, the encoded data is not divided into lines. If doEncode is
+ * false, lineLength is ignored.
+ * @param lineSeparator
+ * If doEncode is true, each line of encoded data will be terminated with this byte sequence (e.g. \r\n).
+ * If lineLength <= 0, the lineSeparator is not used. If doEncode is false lineSeparator is ignored.
+ */
+ public Base32OutputStream(OutputStream out, boolean doEncode, int lineLength, byte[] lineSeparator) {
+ super(out, new Base32(lineLength, lineSeparator), doEncode);
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64.java
new file mode 100644
index 000000000..07ed1a4c4
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64.java
@@ -0,0 +1,756 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.binary;
+
+import java.math.BigInteger;
+
+/**
+ * Provides Base64 encoding and decoding as defined by <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>.
+ *
+ * <p>
+ * This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045 <cite>Multipurpose
+ * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein.
+ * </p>
+ * <p>
+ * The class can be parameterized in the following manner with various constructors:
+ * <ul>
+ * <li>URL-safe mode: Default off.</li>
+ * <li>Line length: Default 76. Line length that aren't multiples of 4 will still essentially end up being multiples of
+ * 4 in the encoded data.
+ * <li>Line separator: Default is CRLF ("\r\n")</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode
+ * character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc).
+ * </p>
+ * <p>
+ * This class is not thread-safe. Each thread should use its own instance.
+ * </p>
+ *
+ * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
+ * @author Apache Software Foundation
+ * @since 1.0
+ * @version $Revision: 1080712 $
+ */
+public class Base64 extends BaseNCodec {
+
+ /**
+ * BASE32 characters are 6 bits in length.
+ * They are formed by taking a block of 3 octets to form a 24-bit string,
+ * which is converted into 4 BASE64 characters.
+ */
+ private static final int BITS_PER_ENCODED_BYTE = 6;
+ private static final int BYTES_PER_UNENCODED_BLOCK = 3;
+ private static final int BYTES_PER_ENCODED_BLOCK = 4;
+
+ /**
+ * Chunk separator per RFC 2045 section 2.1.
+ *
+ * <p>
+ * N.B. The next major release may break compatibility and make this field private.
+ * </p>
+ *
+ * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a>
+ */
+ static final byte[] CHUNK_SEPARATOR = {'\r', '\n'};
+
+ /**
+ * This array is a lookup table that translates 6-bit positive integer index values into their "Base64 Alphabet"
+ * equivalents as specified in Table 1 of RFC 2045.
+ *
+ * Thanks to "commons" project in ws.apache.org for this code.
+ * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+ */
+ private static final byte[] STANDARD_ENCODE_TABLE = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
+ };
+
+ /**
+ * This is a copy of the STANDARD_ENCODE_TABLE above, but with + and /
+ * changed to - and _ to make the encoded Base64 results more URL-SAFE.
+ * This table is only used when the Base64's mode is set to URL-SAFE.
+ */
+ private static final byte[] URL_SAFE_ENCODE_TABLE = {
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
+ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
+ 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
+ };
+
+ /**
+ * This array is a lookup table that translates Unicode characters drawn from the "Base64 Alphabet" (as specified in
+ * Table 1 of RFC 2045) into their 6-bit positive integer equivalents. Characters that are not in the Base64
+ * alphabet but fall within the bounds of the array are translated to -1.
+ *
+ * Note: '+' and '-' both decode to 62. '/' and '_' both decode to 63. This means decoder seamlessly handles both
+ * URL_SAFE and STANDARD base64. (The encoder, on the other hand, needs to know ahead of time what to emit).
+ *
+ * Thanks to "commons" project in ws.apache.org for this code.
+ * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+ */
+ private static final byte[] DECODE_TABLE = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, 62, -1, 63, 52, 53, 54,
+ 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+ 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
+ };
+
+ /**
+ * Base64 uses 6-bit fields.
+ */
+ /** Mask used to extract 6 bits, used when encoding */
+ private static final int MASK_6BITS = 0x3f;
+
+ // The static final fields above are used for the original static byte[] methods on Base64.
+ // The private member fields below are used with the new streaming approach, which requires
+ // some state be preserved between calls of encode() and decode().
+
+ /**
+ * Encode table to use: either STANDARD or URL_SAFE. Note: the DECODE_TABLE above remains static because it is able
+ * to decode both STANDARD and URL_SAFE streams, but the encodeTable must be a member variable so we can switch
+ * between the two modes.
+ */
+ private final byte[] encodeTable;
+
+ // Only one decode table currently; keep for consistency with Base32 code
+ private final byte[] decodeTable = DECODE_TABLE;
+
+ /**
+ * Line separator for encoding. Not used when decoding. Only used if lineLength > 0.
+ */
+ private final byte[] lineSeparator;
+
+ /**
+ * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
+ * <code>decodeSize = 3 + lineSeparator.length;</code>
+ */
+ private final int decodeSize;
+
+ /**
+ * Convenience variable to help us determine when our buffer is going to run out of room and needs resizing.
+ * <code>encodeSize = 4 + lineSeparator.length;</code>
+ */
+ private final int encodeSize;
+
+ /**
+ * Place holder for the bytes we're dealing with for our based logic.
+ * Bitwise operations store and extract the encoding or decoding from this variable.
+ */
+ private int bitWorkArea;
+
+ /**
+ * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+ * <p>
+ * When encoding the line length is 0 (no chunking), and the encoding table is STANDARD_ENCODE_TABLE.
+ * </p>
+ *
+ * <p>
+ * When decoding all variants are supported.
+ * </p>
+ */
+ public Base64() {
+ this(0);
+ }
+
+ /**
+ * Creates a Base64 codec used for decoding (all modes) and encoding in the given URL-safe mode.
+ * <p>
+ * When encoding the line length is 76, the line separator is CRLF, and the encoding table is STANDARD_ENCODE_TABLE.
+ * </p>
+ *
+ * <p>
+ * When decoding all variants are supported.
+ * </p>
+ *
+ * @param urlSafe
+ * if <code>true</code>, URL-safe encoding is used. In most cases this should be set to
+ * <code>false</code>.
+ * @since 1.4
+ */
+ public Base64(boolean urlSafe) {
+ this(MIME_CHUNK_SIZE, CHUNK_SEPARATOR, urlSafe);
+ }
+
+ /**
+ * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+ * <p>
+ * When encoding the line length is given in the constructor, the line separator is CRLF, and the encoding table is
+ * STANDARD_ENCODE_TABLE.
+ * </p>
+ * <p>
+ * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
+ * </p>
+ * <p>
+ * When decoding all variants are supported.
+ * </p>
+ *
+ * @param lineLength
+ * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
+ * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
+ * @since 1.4
+ */
+ public Base64(int lineLength) {
+ this(lineLength, CHUNK_SEPARATOR);
+ }
+
+ /**
+ * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+ * <p>
+ * When encoding the line length and line separator are given in the constructor, and the encoding table is
+ * STANDARD_ENCODE_TABLE.
+ * </p>
+ * <p>
+ * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
+ * </p>
+ * <p>
+ * When decoding all variants are supported.
+ * </p>
+ *
+ * @param lineLength
+ * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
+ * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
+ * @param lineSeparator
+ * Each line of encoded data will end with this sequence of bytes.
+ * @throws IllegalArgumentException
+ * Thrown when the provided lineSeparator included some base64 characters.
+ * @since 1.4
+ */
+ public Base64(int lineLength, byte[] lineSeparator) {
+ this(lineLength, lineSeparator, false);
+ }
+
+ /**
+ * Creates a Base64 codec used for decoding (all modes) and encoding in URL-unsafe mode.
+ * <p>
+ * When encoding the line length and line separator are given in the constructor, and the encoding table is
+ * STANDARD_ENCODE_TABLE.
+ * </p>
+ * <p>
+ * Line lengths that aren't multiples of 4 will still essentially end up being multiples of 4 in the encoded data.
+ * </p>
+ * <p>
+ * When decoding all variants are supported.
+ * </p>
+ *
+ * @param lineLength
+ * Each line of encoded data will be at most of the given length (rounded down to nearest multiple of 4).
+ * If lineLength <= 0, then the output will not be divided into lines (chunks). Ignored when decoding.
+ * @param lineSeparator
+ * Each line of encoded data will end with this sequence of bytes.
+ * @param urlSafe
+ * Instead of emitting '+' and '/' we emit '-' and '_' respectively. urlSafe is only applied to encode
+ * operations. Decoding seamlessly handles both modes.
+ * @throws IllegalArgumentException
+ * The provided lineSeparator included some base64 characters. That's not going to work!
+ * @since 1.4
+ */
+ public Base64(int lineLength, byte[] lineSeparator, boolean urlSafe) {
+ super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK,
+ lineLength,
+ lineSeparator == null ? 0 : lineSeparator.length);
+ // TODO could be simplified if there is no requirement to reject invalid line sep when length <=0
+ // @see test case Base64Test.testConstructors()
+ if (lineSeparator != null) {
+ if (containsAlphabetOrPad(lineSeparator)) {
+ String sep = StringUtils.newStringUtf8(lineSeparator);
+ throw new IllegalArgumentException("lineSeparator must not contain base64 characters: [" + sep + "]");
+ }
+ if (lineLength > 0){ // null line-sep forces no chunking rather than throwing IAE
+ this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparator.length;
+ this.lineSeparator = new byte[lineSeparator.length];
+ System.arraycopy(lineSeparator, 0, this.lineSeparator, 0, lineSeparator.length);
+ } else {
+ this.encodeSize = BYTES_PER_ENCODED_BLOCK;
+ this.lineSeparator = null;
+ }
+ } else {
+ this.encodeSize = BYTES_PER_ENCODED_BLOCK;
+ this.lineSeparator = null;
+ }
+ this.decodeSize = this.encodeSize - 1;
+ this.encodeTable = urlSafe ? URL_SAFE_ENCODE_TABLE : STANDARD_ENCODE_TABLE;
+ }
+
+ /**
+ * Returns our current encode mode. True if we're URL-SAFE, false otherwise.
+ *
+ * @return true if we're in URL-SAFE mode, false otherwise.
+ * @since 1.4
+ */
+ public boolean isUrlSafe() {
+ return this.encodeTable == URL_SAFE_ENCODE_TABLE;
+ }
+
+ /**
+ * <p>
+ * Encodes all of the provided data, starting at inPos, for inAvail bytes. Must be called at least twice: once with
+ * the data to encode, and once with inAvail set to "-1" to alert encoder that EOF has been reached, so flush last
+ * remaining bytes (if not multiple of 3).
+ * </p>
+ * <p>
+ * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
+ * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+ * </p>
+ *
+ * @param in
+ * byte[] array of binary data to base64 encode.
+ * @param inPos
+ * Position to start reading data from.
+ * @param inAvail
+ * Amount of bytes available from input for encoding.
+ */
+ void encode(byte[] in, int inPos, int inAvail) {
+ if (eof) {
+ return;
+ }
+ // inAvail < 0 is how we're informed of EOF in the underlying data we're
+ // encoding.
+ if (inAvail < 0) {
+ eof = true;
+ if (0 == modulus && lineLength == 0) {
+ return; // no leftovers to process and not using chunking
+ }
+ ensureBufferSize(encodeSize);
+ int savedPos = pos;
+ switch (modulus) { // 0-2
+ case 1 : // 8 bits = 6 + 2
+ buffer[pos++] = encodeTable[(bitWorkArea >> 2) & MASK_6BITS]; // top 6 bits
+ buffer[pos++] = encodeTable[(bitWorkArea << 4) & MASK_6BITS]; // remaining 2
+ // URL-SAFE skips the padding to further reduce size.
+ if (encodeTable == STANDARD_ENCODE_TABLE) {
+ buffer[pos++] = PAD;
+ buffer[pos++] = PAD;
+ }
+ break;
+
+ case 2 : // 16 bits = 6 + 6 + 4
+ buffer[pos++] = encodeTable[(bitWorkArea >> 10) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea >> 4) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea << 2) & MASK_6BITS];
+ // URL-SAFE skips the padding to further reduce size.
+ if (encodeTable == STANDARD_ENCODE_TABLE) {
+ buffer[pos++] = PAD;
+ }
+ break;
+ }
+ currentLinePos += pos - savedPos; // keep track of current line position
+ // if currentPos == 0 we are at the start of a line, so don't add CRLF
+ if (lineLength > 0 && currentLinePos > 0) {
+ System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
+ pos += lineSeparator.length;
+ }
+ } else {
+ for (int i = 0; i < inAvail; i++) {
+ ensureBufferSize(encodeSize);
+ modulus = (modulus+1) % BYTES_PER_UNENCODED_BLOCK;
+ int b = in[inPos++];
+ if (b < 0) {
+ b += 256;
+ }
+ bitWorkArea = (bitWorkArea << 8) + b; // BITS_PER_BYTE
+ if (0 == modulus) { // 3 bytes = 24 bits = 4 * 6 bits to extract
+ buffer[pos++] = encodeTable[(bitWorkArea >> 18) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea >> 12) & MASK_6BITS];
+ buffer[pos++] = encodeTable[(bitWorkArea >> 6) & MASK_6BITS];
+ buffer[pos++] = encodeTable[bitWorkArea & MASK_6BITS];
+ currentLinePos += BYTES_PER_ENCODED_BLOCK;
+ if (lineLength > 0 && lineLength <= currentLinePos) {
+ System.arraycopy(lineSeparator, 0, buffer, pos, lineSeparator.length);
+ pos += lineSeparator.length;
+ currentLinePos = 0;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * <p>
+ * Decodes all of the provided data, starting at inPos, for inAvail bytes. Should be called at least twice: once
+ * with the data to decode, and once with inAvail set to "-1" to alert decoder that EOF has been reached. The "-1"
+ * call is not necessary when decoding, but it doesn't hurt, either.
+ * </p>
+ * <p>
+ * Ignores all non-base64 characters. This is how chunked (e.g. 76 character) data is handled, since CR and LF are
+ * silently ignored, but has implications for other bytes, too. This method subscribes to the garbage-in,
+ * garbage-out philosophy: it will not check the provided data for validity.
+ * </p>
+ * <p>
+ * Thanks to "commons" project in ws.apache.org for the bitwise operations, and general approach.
+ * http://svn.apache.org/repos/asf/webservices/commons/trunk/modules/util/
+ * </p>
+ *
+ * @param in
+ * byte[] array of ascii data to base64 decode.
+ * @param inPos
+ * Position to start reading data from.
+ * @param inAvail
+ * Amount of bytes available from input for encoding.
+ */
+ void decode(byte[] in, int inPos, int inAvail) {
+ if (eof) {
+ return;
+ }
+ if (inAvail < 0) {
+ eof = true;
+ }
+ for (int i = 0; i < inAvail; i++) {
+ ensureBufferSize(decodeSize);
+ byte b = in[inPos++];
+ if (b == PAD) {
+ // We're done.
+ eof = true;
+ break;
+ } else {
+ if (b >= 0 && b < DECODE_TABLE.length) {
+ int result = DECODE_TABLE[b];
+ if (result >= 0) {
+ modulus = (modulus+1) % BYTES_PER_ENCODED_BLOCK;
+ bitWorkArea = (bitWorkArea << BITS_PER_ENCODED_BYTE) + result;
+ if (modulus == 0) {
+ buffer[pos++] = (byte) ((bitWorkArea >> 16) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+ buffer[pos++] = (byte) (bitWorkArea & MASK_8BITS);
+ }
+ }
+ }
+ }
+ }
+
+ // Two forms of EOF as far as base64 decoder is concerned: actual
+ // EOF (-1) and first time '=' character is encountered in stream.
+ // This approach makes the '=' padding characters completely optional.
+ if (eof && modulus != 0) {
+ ensureBufferSize(decodeSize);
+
+ // We have some spare bits remaining
+ // Output all whole multiples of 8 bits and ignore the rest
+ switch (modulus) {
+ // case 1: // 6 bits - ignore entirely
+ // break;
+ case 2 : // 12 bits = 8 + 4
+ bitWorkArea = bitWorkArea >> 4; // dump the extra 4 bits
+ buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
+ break;
+ case 3 : // 18 bits = 8 + 8 + 2
+ bitWorkArea = bitWorkArea >> 2; // dump 2 bits
+ buffer[pos++] = (byte) ((bitWorkArea >> 8) & MASK_8BITS);
+ buffer[pos++] = (byte) ((bitWorkArea) & MASK_8BITS);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Returns whether or not the <code>octet</code> is in the base 64 alphabet.
+ *
+ * @param octet
+ * The value to test
+ * @return <code>true</code> if the value is defined in the the base 64 alphabet, <code>false</code> otherwise.
+ * @since 1.4
+ */
+ public static boolean isBase64(byte octet) {
+ return octet == PAD_DEFAULT || (octet >= 0 && octet < DECODE_TABLE.length && DECODE_TABLE[octet] != -1);
+ }
+
+ /**
+ * Tests a given String to see if it contains only valid characters within the Base64 alphabet. Currently the
+ * method treats whitespace as valid.
+ *
+ * @param base64
+ * String to test
+ * @return <code>true</code> if all characters in the String are valid characters in the Base64 alphabet or if
+ * the String is empty; <code>false</code>, otherwise
+ * @since 1.5
+ */
+ public static boolean isBase64(String base64) {
+ return isBase64(StringUtils.getBytesUtf8(base64));
+ }
+
+ /**
+ * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the
+ * method treats whitespace as valid.
+ *
+ * @param arrayOctet
+ * byte array to test
+ * @return <code>true</code> if all bytes are valid characters in the Base64 alphabet or if the byte array is empty;
+ * <code>false</code>, otherwise
+ * @deprecated 1.5 Use {@link #isBase64(byte[])}, will be removed in 2.0.
+ */
+ public static boolean isArrayByteBase64(byte[] arrayOctet) {
+ return isBase64(arrayOctet);
+ }
+
+ /**
+ * Tests a given byte array to see if it contains only valid characters within the Base64 alphabet. Currently the
+ * method treats whitespace as valid.
+ *
+ * @param arrayOctet
+ * byte array to test
+ * @return <code>true</code> if all bytes are valid characters in the Base64 alphabet or if the byte array is empty;
+ * <code>false</code>, otherwise
+ * @since 1.5
+ */
+ public static boolean isBase64(byte[] arrayOctet) {
+ for (int i = 0; i < arrayOctet.length; i++) {
+ if (!isBase64(arrayOctet[i]) && !isWhiteSpace(arrayOctet[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Encodes binary data using the base64 algorithm but does not chunk the output.
+ *
+ * @param binaryData
+ * binary data to encode
+ * @return byte[] containing Base64 characters in their UTF-8 representation.
+ */
+ public static byte[] encodeBase64(byte[] binaryData) {
+ return encodeBase64(binaryData, false);
+ }
+
+ /**
+ * Encodes binary data using the base64 algorithm but does not chunk the output.
+ *
+ * NOTE: We changed the behaviour of this method from multi-line chunking (commons-codec-1.4) to
+ * single-line non-chunking (commons-codec-1.5).
+ *
+ * @param binaryData
+ * binary data to encode
+ * @return String containing Base64 characters.
+ * @since 1.4 (NOTE: 1.4 chunked the output, whereas 1.5 does not).
+ */
+ public static String encodeBase64String(byte[] binaryData) {
+ return StringUtils.newStringUtf8(encodeBase64(binaryData, false));
+ }
+
+ /**
+ * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The
+ * url-safe variation emits - and _ instead of + and / characters.
+ *
+ * @param binaryData
+ * binary data to encode
+ * @return byte[] containing Base64 characters in their UTF-8 representation.
+ * @since 1.4
+ */
+ public static byte[] encodeBase64URLSafe(byte[] binaryData) {
+ return encodeBase64(binaryData, false, true);
+ }
+
+ /**
+ * Encodes binary data using a URL-safe variation of the base64 algorithm but does not chunk the output. The
+ * url-safe variation emits - and _ instead of + and / characters.
+ *
+ * @param binaryData
+ * binary data to encode
+ * @return String containing Base64 characters
+ * @since 1.4
+ */
+ public static String encodeBase64URLSafeString(byte[] binaryData) {
+ return StringUtils.newStringUtf8(encodeBase64(binaryData, false, true));
+ }
+
+ /**
+ * Encodes binary data using the base64 algorithm and chunks the encoded output into 76 character blocks
+ *
+ * @param binaryData
+ * binary data to encode
+ * @return Base64 characters chunked in 76 character blocks
+ */
+ public static byte[] encodeBase64Chunked(byte[] binaryData) {
+ return encodeBase64(binaryData, true);
+ }
+
+ /**
+ * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
+ *
+ * @param binaryData
+ * Array containing binary data to encode.
+ * @param isChunked
+ * if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
+ * @return Base64-encoded data.
+ * @throws IllegalArgumentException
+ * Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
+ */
+ public static byte[] encodeBase64(byte[] binaryData, boolean isChunked) {
+ return encodeBase64(binaryData, isChunked, false);
+ }
+
+ /**
+ * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
+ *
+ * @param binaryData
+ * Array containing binary data to encode.
+ * @param isChunked
+ * if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
+ * @param urlSafe
+ * if <code>true</code> this encoder will emit - and _ instead of the usual + and / characters.
+ * @return Base64-encoded data.
+ * @throws IllegalArgumentException
+ * Thrown when the input array needs an output array bigger than {@link Integer#MAX_VALUE}
+ * @since 1.4
+ */
+ public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe) {
+ return encodeBase64(binaryData, isChunked, urlSafe, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Encodes binary data using the base64 algorithm, optionally chunking the output into 76 character blocks.
+ *
+ * @param binaryData
+ * Array containing binary data to encode.
+ * @param isChunked
+ * if <code>true</code> this encoder will chunk the base64 output into 76 character blocks
+ * @param urlSafe
+ * if <code>true</code> this encoder will emit - and _ instead of the usual + and / characters.
+ * @param maxResultSize
+ * The maximum result size to accept.
+ * @return Base64-encoded data.
+ * @throws IllegalArgumentException
+ * Thrown when the input array needs an output array bigger than maxResultSize
+ * @since 1.4
+ */
+ public static byte[] encodeBase64(byte[] binaryData, boolean isChunked, boolean urlSafe, int maxResultSize) {
+ if (binaryData == null || binaryData.length == 0) {
+ return binaryData;
+ }
+
+ // Create this so can use the super-class method
+ // Also ensures that the same roundings are performed by the ctor and the code
+ Base64 b64 = isChunked ? new Base64(urlSafe) : new Base64(0, CHUNK_SEPARATOR, urlSafe);
+ long len = b64.getEncodedLength(binaryData);
+ if (len > maxResultSize) {
+ throw new IllegalArgumentException("Input array too big, the output array would be bigger (" +
+ len +
+ ") than the specified maximum size of " +
+ maxResultSize);
+ }
+
+ return b64.encode(binaryData);
+ }
+
+ /**
+ * Decodes a Base64 String into octets
+ *
+ * @param base64String
+ * String containing Base64 data
+ * @return Array containing decoded data.
+ * @since 1.4
+ */
+ public static byte[] decodeBase64(String base64String) {
+ return new Base64().decode(base64String);
+ }
+
+ /**
+ * Decodes Base64 data into octets
+ *
+ * @param base64Data
+ * Byte array containing Base64 data
+ * @return Array containing decoded data.
+ */
+ public static byte[] decodeBase64(byte[] base64Data) {
+ return new Base64().decode(base64Data);
+ }
+
+ // Implementation of the Encoder Interface
+
+ // Implementation of integer encoding used for crypto
+ /**
+ * Decodes a byte64-encoded integer according to crypto standards such as W3C's XML-Signature
+ *
+ * @param pArray
+ * a byte array containing base64 character data
+ * @return A BigInteger
+ * @since 1.4
+ */
+ public static BigInteger decodeInteger(byte[] pArray) {
+ return new BigInteger(1, decodeBase64(pArray));
+ }
+
+ /**
+ * Encodes to a byte64-encoded integer according to crypto standards such as W3C's XML-Signature
+ *
+ * @param bigInt
+ * a BigInteger
+ * @return A byte array containing base64 character data
+ * @throws NullPointerException
+ * if null is passed in
+ * @since 1.4
+ */
+ public static byte[] encodeInteger(BigInteger bigInt) {
+ if (bigInt == null) {
+ throw new NullPointerException("encodeInteger called with null parameter");
+ }
+ return encodeBase64(toIntegerBytes(bigInt), false);
+ }
+
+ /**
+ * Returns a byte-array representation of a <code>BigInteger</code> without sign bit.
+ *
+ * @param bigInt
+ * <code>BigInteger</code> to be converted
+ * @return a byte array representation of the BigInteger parameter
+ */
+ static byte[] toIntegerBytes(BigInteger bigInt) {
+ int bitlen = bigInt.bitLength();
+ // round bitlen
+ bitlen = ((bitlen + 7) >> 3) << 3;
+ byte[] bigBytes = bigInt.toByteArray();
+
+ if (((bigInt.bitLength() % 8) != 0) && (((bigInt.bitLength() / 8) + 1) == (bitlen / 8))) {
+ return bigBytes;
+ }
+ // set up params for copying everything but sign bit
+ int startSrc = 0;
+ int len = bigBytes.length;
+
+ // if bigInt is exactly byte-aligned, just skip signbit in copy
+ if ((bigInt.bitLength() % 8) == 0) {
+ startSrc = 1;
+ len--;
+ }
+ int startDst = bitlen / 8 - len; // to pad w/ nulls as per spec
+ byte[] resizedBytes = new byte[bitlen / 8];
+ System.arraycopy(bigBytes, startSrc, resizedBytes, startDst, len);
+ return resizedBytes;
+ }
+
+ /**
+ * Returns whether or not the <code>octet</code> is in the Base32 alphabet.
+ *
+ * @param octet
+ * The value to test
+ * @return <code>true</code> if the value is defined in the the Base32 alphabet <code>false</code> otherwise.
+ */
+ protected boolean isInAlphabet(byte octet) {
+ return octet >= 0 && octet < decodeTable.length && decodeTable[octet] != -1;
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64InputStream.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64InputStream.java
new file mode 100644
index 000000000..cf99ceb91
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64InputStream.java
@@ -0,0 +1,89 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.binary;
+
+import java.io.InputStream;
+
+/**
+ * Provides Base64 encoding and decoding in a streaming fashion (unlimited size). When encoding the default lineLength
+ * is 76 characters and the default lineEnding is CRLF, but these can be overridden by using the appropriate
+ * constructor.
+ * <p>
+ * The default behaviour of the Base64InputStream is to DECODE, whereas the default behaviour of the Base64OutputStream
+ * is to ENCODE, but this behaviour can be overridden by using a different constructor.
+ * </p>
+ * <p>
+ * This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045 <cite>Multipurpose
+ * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein.
+ * </p>
+ * <p>
+ * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode
+ * character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc).
+ * </p>
+ *
+ * @author Apache Software Foundation
+ * @version $Id: Base64InputStream.java 1064424 2011-01-28 02:02:46Z sebb $
+ * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
+ * @since 1.4
+ */
+public class Base64InputStream extends BaseNCodecInputStream {
+
+ /**
+ * Creates a Base64InputStream such that all data read is Base64-decoded from the original provided InputStream.
+ *
+ * @param in
+ * InputStream to wrap.
+ */
+ public Base64InputStream(InputStream in) {
+ this(in, false);
+ }
+
+ /**
+ * Creates a Base64InputStream such that all data read is either Base64-encoded or Base64-decoded from the original
+ * provided InputStream.
+ *
+ * @param in
+ * InputStream to wrap.
+ * @param doEncode
+ * true if we should encode all data read from us, false if we should decode.
+ */
+ public Base64InputStream(InputStream in, boolean doEncode) {
+ super(in, new Base64(false), doEncode);
+ }
+
+ /**
+ * Creates a Base64InputStream such that all data read is either Base64-encoded or Base64-decoded from the original
+ * provided InputStream.
+ *
+ * @param in
+ * InputStream to wrap.
+ * @param doEncode
+ * true if we should encode all data read from us, false if we should decode.
+ * @param lineLength
+ * If doEncode is true, each line of encoded data will contain lineLength characters (rounded down to
+ * nearest multiple of 4). If lineLength <=0, the encoded data is not divided into lines. If doEncode is
+ * false, lineLength is ignored.
+ * @param lineSeparator
+ * If doEncode is true, each line of encoded data will be terminated with this byte sequence (e.g. \r\n).
+ * If lineLength <= 0, the lineSeparator is not used. If doEncode is false lineSeparator is ignored.
+ */
+ public Base64InputStream(InputStream in, boolean doEncode, int lineLength, byte[] lineSeparator) {
+ super(in, new Base64(lineLength, lineSeparator), doEncode);
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64OutputStream.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64OutputStream.java
new file mode 100644
index 000000000..df880c2b9
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64OutputStream.java
@@ -0,0 +1,89 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.binary;
+
+import java.io.OutputStream;
+
+/**
+ * Provides Base64 encoding and decoding in a streaming fashion (unlimited size). When encoding the default lineLength
+ * is 76 characters and the default lineEnding is CRLF, but these can be overridden by using the appropriate
+ * constructor.
+ * <p>
+ * The default behaviour of the Base64OutputStream is to ENCODE, whereas the default behaviour of the Base64InputStream
+ * is to DECODE. But this behaviour can be overridden by using a different constructor.
+ * </p>
+ * <p>
+ * This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045 <cite>Multipurpose
+ * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein.
+ * </p>
+ * <p>
+ * Since this class operates directly on byte streams, and not character streams, it is hard-coded to only encode/decode
+ * character encodings which are compatible with the lower 127 ASCII chart (ISO-8859-1, Windows-1252, UTF-8, etc).
+ * </p>
+ *
+ * @author Apache Software Foundation
+ * @version $Id: Base64OutputStream.java 1064424 2011-01-28 02:02:46Z sebb $
+ * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
+ * @since 1.4
+ */
+public class Base64OutputStream extends BaseNCodecOutputStream {
+
+ /**
+ * Creates a Base64OutputStream such that all data written is Base64-encoded to the original provided OutputStream.
+ *
+ * @param out
+ * OutputStream to wrap.
+ */
+ public Base64OutputStream(OutputStream out) {
+ this(out, true);
+ }
+
+ /**
+ * Creates a Base64OutputStream such that all data written is either Base64-encoded or Base64-decoded to the
+ * original provided OutputStream.
+ *
+ * @param out
+ * OutputStream to wrap.
+ * @param doEncode
+ * true if we should encode all data written to us, false if we should decode.
+ */
+ public Base64OutputStream(OutputStream out, boolean doEncode) {
+ super(out,new Base64(false), doEncode);
+ }
+
+ /**
+ * Creates a Base64OutputStream such that all data written is either Base64-encoded or Base64-decoded to the
+ * original provided OutputStream.
+ *
+ * @param out
+ * OutputStream to wrap.
+ * @param doEncode
+ * true if we should encode all data written to us, false if we should decode.
+ * @param lineLength
+ * If doEncode is true, each line of encoded data will contain lineLength characters (rounded down to
+ * nearest multiple of 4). If lineLength <=0, the encoded data is not divided into lines. If doEncode is
+ * false, lineLength is ignored.
+ * @param lineSeparator
+ * If doEncode is true, each line of encoded data will be terminated with this byte sequence (e.g. \r\n).
+ * If lineLength <= 0, the lineSeparator is not used. If doEncode is false lineSeparator is ignored.
+ */
+ public Base64OutputStream(OutputStream out, boolean doEncode, int lineLength, byte[] lineSeparator) {
+ super(out, new Base64(lineLength, lineSeparator), doEncode);
+ }
+} \ No newline at end of file
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodec.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodec.java
new file mode 100644
index 000000000..c2ed4efef
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodec.java
@@ -0,0 +1,445 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.binary;
+
+import org.mozilla.apache.commons.codec.BinaryDecoder;
+import org.mozilla.apache.commons.codec.BinaryEncoder;
+import org.mozilla.apache.commons.codec.DecoderException;
+import org.mozilla.apache.commons.codec.EncoderException;
+
+/**
+ * Abstract superclass for Base-N encoders and decoders.
+ *
+ * <p>
+ * This class is not thread-safe.
+ * Each thread should use its own instance.
+ * </p>
+ */
+public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
+
+ /**
+ * MIME chunk size per RFC 2045 section 6.8.
+ *
+ * <p>
+ * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
+ * equal signs.
+ * </p>
+ *
+ * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a>
+ */
+ public static final int MIME_CHUNK_SIZE = 76;
+
+ /**
+ * PEM chunk size per RFC 1421 section 4.3.2.4.
+ *
+ * <p>
+ * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any
+ * equal signs.
+ * </p>
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc1421">RFC 1421 section 4.3.2.4</a>
+ */
+ public static final int PEM_CHUNK_SIZE = 64;
+
+ private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2;
+
+ /**
+ * Defines the default buffer size - currently {@value}
+ * - must be large enough for at least one encoded block+separator
+ */
+ private static final int DEFAULT_BUFFER_SIZE = 8192;
+
+ /** Mask used to extract 8 bits, used in decoding bytes */
+ protected static final int MASK_8BITS = 0xff;
+
+ /**
+ * Byte used to pad output.
+ */
+ protected static final byte PAD_DEFAULT = '='; // Allow static access to default
+
+ protected final byte PAD = PAD_DEFAULT; // instance variable just in case it needs to vary later
+
+ /** Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 for Base32 */
+ private final int unencodedBlockSize;
+
+ /** Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 for Base32 */
+ private final int encodedBlockSize;
+
+ /**
+ * Chunksize for encoding. Not used when decoding.
+ * A value of zero or less implies no chunking of the encoded data.
+ * Rounded down to nearest multiple of encodedBlockSize.
+ */
+ protected final int lineLength;
+
+ /**
+ * Size of chunk separator. Not used unless {@link #lineLength} > 0.
+ */
+ private final int chunkSeparatorLength;
+
+ /**
+ * Buffer for streaming.
+ */
+ protected byte[] buffer;
+
+ /**
+ * Position where next character should be written in the buffer.
+ */
+ protected int pos;
+
+ /**
+ * Position where next character should be read from the buffer.
+ */
+ private int readPos;
+
+ /**
+ * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this object becomes useless,
+ * and must be thrown away.
+ */
+ protected boolean eof;
+
+ /**
+ * Variable tracks how many characters have been written to the current line. Only used when encoding. We use it to
+ * make sure each encoded line never goes beyond lineLength (if lineLength > 0).
+ */
+ protected int currentLinePos;
+
+ /**
+ * Writes to the buffer only occur after every 3/5 reads when encoding, and every 4/8 reads when decoding.
+ * This variable helps track that.
+ */
+ protected int modulus;
+
+ /**
+ * Note <code>lineLength</code> is rounded down to the nearest multiple of {@link #encodedBlockSize}
+ * If <code>chunkSeparatorLength</code> is zero, then chunking is disabled.
+ * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3)
+ * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4)
+ * @param lineLength if &gt; 0, use chunking with a length <code>lineLength</code>
+ * @param chunkSeparatorLength the chunk separator length, if relevant
+ */
+ protected BaseNCodec(int unencodedBlockSize, int encodedBlockSize, int lineLength, int chunkSeparatorLength){
+ this.unencodedBlockSize = unencodedBlockSize;
+ this.encodedBlockSize = encodedBlockSize;
+ this.lineLength = (lineLength > 0 && chunkSeparatorLength > 0) ? (lineLength / encodedBlockSize) * encodedBlockSize : 0;
+ this.chunkSeparatorLength = chunkSeparatorLength;
+ }
+
+ /**
+ * Returns true if this object has buffered data for reading.
+ *
+ * @return true if there is data still available for reading.
+ */
+ boolean hasData() { // package protected for access from I/O streams
+ return this.buffer != null;
+ }
+
+ /**
+ * Returns the amount of buffered data available for reading.
+ *
+ * @return The amount of buffered data available for reading.
+ */
+ int available() { // package protected for access from I/O streams
+ return buffer != null ? pos - readPos : 0;
+ }
+
+ /**
+ * Get the default buffer size. Can be overridden.
+ *
+ * @return {@link #DEFAULT_BUFFER_SIZE}
+ */
+ protected int getDefaultBufferSize() {
+ return DEFAULT_BUFFER_SIZE;
+ }
+
+ /** Increases our buffer by the {@link #DEFAULT_BUFFER_RESIZE_FACTOR}. */
+ private void resizeBuffer() {
+ if (buffer == null) {
+ buffer = new byte[getDefaultBufferSize()];
+ pos = 0;
+ readPos = 0;
+ } else {
+ byte[] b = new byte[buffer.length * DEFAULT_BUFFER_RESIZE_FACTOR];
+ System.arraycopy(buffer, 0, b, 0, buffer.length);
+ buffer = b;
+ }
+ }
+
+ /**
+ * Ensure that the buffer has room for <code>size</code> bytes
+ *
+ * @param size minimum spare space required
+ */
+ protected void ensureBufferSize(int size){
+ if ((buffer == null) || (buffer.length < pos + size)){
+ resizeBuffer();
+ }
+ }
+
+ /**
+ * Extracts buffered data into the provided byte[] array, starting at position bPos,
+ * up to a maximum of bAvail bytes. Returns how many bytes were actually extracted.
+ *
+ * @param b
+ * byte[] array to extract the buffered data into.
+ * @param bPos
+ * position in byte[] array to start extraction at.
+ * @param bAvail
+ * amount of bytes we're allowed to extract. We may extract fewer (if fewer are available).
+ * @return The number of bytes successfully extracted into the provided byte[] array.
+ */
+ int readResults(byte[] b, int bPos, int bAvail) { // package protected for access from I/O streams
+ if (buffer != null) {
+ int len = Math.min(available(), bAvail);
+ System.arraycopy(buffer, readPos, b, bPos, len);
+ readPos += len;
+ if (readPos >= pos) {
+ buffer = null; // so hasData() will return false, and this method can return -1
+ }
+ return len;
+ }
+ return eof ? -1 : 0;
+ }
+
+ /**
+ * Checks if a byte value is whitespace or not.
+ * Whitespace is taken to mean: space, tab, CR, LF
+ * @param byteToCheck
+ * the byte to check
+ * @return true if byte is whitespace, false otherwise
+ */
+ protected static boolean isWhiteSpace(byte byteToCheck) {
+ switch (byteToCheck) {
+ case ' ' :
+ case '\n' :
+ case '\r' :
+ case '\t' :
+ return true;
+ default :
+ return false;
+ }
+ }
+
+ /**
+ * Resets this object to its initial newly constructed state.
+ */
+ private void reset() {
+ buffer = null;
+ pos = 0;
+ readPos = 0;
+ currentLinePos = 0;
+ modulus = 0;
+ eof = false;
+ }
+
+ /**
+ * Encodes an Object using the Base-N algorithm. This method is provided in order to satisfy the requirements of the
+ * Encoder interface, and will throw an EncoderException if the supplied object is not of type byte[].
+ *
+ * @param pObject
+ * Object to encode
+ * @return An object (of type byte[]) containing the Base-N encoded data which corresponds to the byte[] supplied.
+ * @throws EncoderException
+ * if the parameter supplied is not of type byte[]
+ */
+ public Object encode(Object pObject) throws EncoderException {
+ if (!(pObject instanceof byte[])) {
+ throw new EncoderException("Parameter supplied to Base-N encode is not a byte[]");
+ }
+ return encode((byte[]) pObject);
+ }
+
+ /**
+ * Encodes a byte[] containing binary data, into a String containing characters in the Base-N alphabet.
+ *
+ * @param pArray
+ * a byte array containing binary data
+ * @return A String containing only Base-N character data
+ */
+ public String encodeToString(byte[] pArray) {
+ return StringUtils.newStringUtf8(encode(pArray));
+ }
+
+ /**
+ * Decodes an Object using the Base-N algorithm. This method is provided in order to satisfy the requirements of the
+ * Decoder interface, and will throw a DecoderException if the supplied object is not of type byte[] or String.
+ *
+ * @param pObject
+ * Object to decode
+ * @return An object (of type byte[]) containing the binary data which corresponds to the byte[] or String supplied.
+ * @throws DecoderException
+ * if the parameter supplied is not of type byte[]
+ */
+ public Object decode(Object pObject) throws DecoderException {
+ if (pObject instanceof byte[]) {
+ return decode((byte[]) pObject);
+ } else if (pObject instanceof String) {
+ return decode((String) pObject);
+ } else {
+ throw new DecoderException("Parameter supplied to Base-N decode is not a byte[] or a String");
+ }
+ }
+
+ /**
+ * Decodes a String containing characters in the Base-N alphabet.
+ *
+ * @param pArray
+ * A String containing Base-N character data
+ * @return a byte array containing binary data
+ */
+ public byte[] decode(String pArray) {
+ return decode(StringUtils.getBytesUtf8(pArray));
+ }
+
+ /**
+ * Decodes a byte[] containing characters in the Base-N alphabet.
+ *
+ * @param pArray
+ * A byte array containing Base-N character data
+ * @return a byte array containing binary data
+ */
+ public byte[] decode(byte[] pArray) {
+ reset();
+ if (pArray == null || pArray.length == 0) {
+ return pArray;
+ }
+ decode(pArray, 0, pArray.length);
+ decode(pArray, 0, -1); // Notify decoder of EOF.
+ byte[] result = new byte[pos];
+ readResults(result, 0, result.length);
+ return result;
+ }
+
+ /**
+ * Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet.
+ *
+ * @param pArray
+ * a byte array containing binary data
+ * @return A byte array containing only the basen alphabetic character data
+ */
+ public byte[] encode(byte[] pArray) {
+ reset();
+ if (pArray == null || pArray.length == 0) {
+ return pArray;
+ }
+ encode(pArray, 0, pArray.length);
+ encode(pArray, 0, -1); // Notify encoder of EOF.
+ byte[] buf = new byte[pos - readPos];
+ readResults(buf, 0, buf.length);
+ return buf;
+ }
+
+ /**
+ * Encodes a byte[] containing binary data, into a String containing characters in the appropriate alphabet.
+ * Uses UTF8 encoding.
+ *
+ * @param pArray a byte array containing binary data
+ * @return String containing only character data in the appropriate alphabet.
+ */
+ public String encodeAsString(byte[] pArray){
+ return StringUtils.newStringUtf8(encode(pArray));
+ }
+
+ abstract void encode(byte[] pArray, int i, int length); // package protected for access from I/O streams
+
+ abstract void decode(byte[] pArray, int i, int length); // package protected for access from I/O streams
+
+ /**
+ * Returns whether or not the <code>octet</code> is in the current alphabet.
+ * Does not allow whitespace or pad.
+ *
+ * @param value The value to test
+ *
+ * @return <code>true</code> if the value is defined in the current alphabet, <code>false</code> otherwise.
+ */
+ protected abstract boolean isInAlphabet(byte value);
+
+ /**
+ * Tests a given byte array to see if it contains only valid characters within the alphabet.
+ * The method optionally treats whitespace and pad as valid.
+ *
+ * @param arrayOctet byte array to test
+ * @param allowWSPad if <code>true</code>, then whitespace and PAD are also allowed
+ *
+ * @return <code>true</code> if all bytes are valid characters in the alphabet or if the byte array is empty;
+ * <code>false</code>, otherwise
+ */
+ public boolean isInAlphabet(byte[] arrayOctet, boolean allowWSPad) {
+ for (int i = 0; i < arrayOctet.length; i++) {
+ if (!isInAlphabet(arrayOctet[i]) &&
+ (!allowWSPad || (arrayOctet[i] != PAD) && !isWhiteSpace(arrayOctet[i]))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Tests a given String to see if it contains only valid characters within the alphabet.
+ * The method treats whitespace and PAD as valid.
+ *
+ * @param basen String to test
+ * @return <code>true</code> if all characters in the String are valid characters in the alphabet or if
+ * the String is empty; <code>false</code>, otherwise
+ * @see #isInAlphabet(byte[], boolean)
+ */
+ public boolean isInAlphabet(String basen) {
+ return isInAlphabet(StringUtils.getBytesUtf8(basen), true);
+ }
+
+ /**
+ * Tests a given byte array to see if it contains any characters within the alphabet or PAD.
+ *
+ * Intended for use in checking line-ending arrays
+ *
+ * @param arrayOctet
+ * byte array to test
+ * @return <code>true</code> if any byte is a valid character in the alphabet or PAD; <code>false</code> otherwise
+ */
+ protected boolean containsAlphabetOrPad(byte[] arrayOctet) {
+ if (arrayOctet == null) {
+ return false;
+ }
+ for (int i = 0; i < arrayOctet.length; i++) {
+ if (PAD == arrayOctet[i] || isInAlphabet(arrayOctet[i])) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Calculates the amount of space needed to encode the supplied array.
+ *
+ * @param pArray byte[] array which will later be encoded
+ *
+ * @return amount of space needed to encoded the supplied array.
+ * Returns a long since a max-len array will require > Integer.MAX_VALUE
+ */
+ public long getEncodedLength(byte[] pArray) {
+ // Calculate non-chunked size - rounded up to allow for padding
+ // cast to long is needed to avoid possibility of overflow
+ long len = ((pArray.length + unencodedBlockSize-1) / unencodedBlockSize) * (long) encodedBlockSize;
+ if (lineLength > 0) { // We're using chunking
+ // Round up to nearest multiple
+ len += ((len + lineLength-1) / lineLength) * chunkSeparatorLength;
+ }
+ return len;
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodecInputStream.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodecInputStream.java
new file mode 100644
index 000000000..0aa879b15
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodecInputStream.java
@@ -0,0 +1,132 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.binary;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Abstract superclass for Base-N input streams.
+ *
+ * @since 1.5
+ */
+public class BaseNCodecInputStream extends FilterInputStream {
+
+ private final boolean doEncode;
+
+ private final BaseNCodec baseNCodec;
+
+ private final byte[] singleByte = new byte[1];
+
+ protected BaseNCodecInputStream(InputStream in, BaseNCodec baseNCodec, boolean doEncode) {
+ super(in);
+ this.doEncode = doEncode;
+ this.baseNCodec = baseNCodec;
+ }
+
+ /**
+ * Reads one <code>byte</code> from this input stream.
+ *
+ * @return the byte as an integer in the range 0 to 255. Returns -1 if EOF has been reached.
+ * @throws IOException
+ * if an I/O error occurs.
+ */
+ public int read() throws IOException {
+ int r = read(singleByte, 0, 1);
+ while (r == 0) {
+ r = read(singleByte, 0, 1);
+ }
+ if (r > 0) {
+ return singleByte[0] < 0 ? 256 + singleByte[0] : singleByte[0];
+ }
+ return -1;
+ }
+
+ /**
+ * Attempts to read <code>len</code> bytes into the specified <code>b</code> array starting at <code>offset</code>
+ * from this InputStream.
+ *
+ * @param b
+ * destination byte array
+ * @param offset
+ * where to start writing the bytes
+ * @param len
+ * maximum number of bytes to read
+ *
+ * @return number of bytes read
+ * @throws IOException
+ * if an I/O error occurs.
+ * @throws NullPointerException
+ * if the byte array parameter is null
+ * @throws IndexOutOfBoundsException
+ * if offset, len or buffer size are invalid
+ */
+ public int read(byte b[], int offset, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if (offset < 0 || len < 0) {
+ throw new IndexOutOfBoundsException();
+ } else if (offset > b.length || offset + len > b.length) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ } else {
+ int readLen = 0;
+ /*
+ Rationale for while-loop on (readLen == 0):
+ -----
+ Base32.readResults() usually returns > 0 or EOF (-1). In the
+ rare case where it returns 0, we just keep trying.
+
+ This is essentially an undocumented contract for InputStream
+ implementors that want their code to work properly with
+ java.io.InputStreamReader, since the latter hates it when
+ InputStream.read(byte[]) returns a zero. Unfortunately our
+ readResults() call must return 0 if a large amount of the data
+ being decoded was non-base32, so this while-loop enables proper
+ interop with InputStreamReader for that scenario.
+ -----
+ This is a fix for CODEC-101
+ */
+ while (readLen == 0) {
+ if (!baseNCodec.hasData()) {
+ byte[] buf = new byte[doEncode ? 4096 : 8192];
+ int c = in.read(buf);
+ if (doEncode) {
+ baseNCodec.encode(buf, 0, c);
+ } else {
+ baseNCodec.decode(buf, 0, c);
+ }
+ }
+ readLen = baseNCodec.readResults(b, offset, len);
+ }
+ return readLen;
+ }
+ }
+ /**
+ * {@inheritDoc}
+ *
+ * @return false
+ */
+ public boolean markSupported() {
+ return false; // not an easy job to support marks
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodecOutputStream.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodecOutputStream.java
new file mode 100644
index 000000000..bdcbd4d34
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodecOutputStream.java
@@ -0,0 +1,142 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.binary;
+
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Abstract superclass for Base-N output streams.
+ *
+ * @since 1.5
+ */
+public class BaseNCodecOutputStream extends FilterOutputStream {
+
+ private final boolean doEncode;
+
+ private final BaseNCodec baseNCodec;
+
+ private final byte[] singleByte = new byte[1];
+
+ public BaseNCodecOutputStream(OutputStream out, BaseNCodec basedCodec, boolean doEncode) {
+ super(out);
+ this.baseNCodec = basedCodec;
+ this.doEncode = doEncode;
+ }
+
+ /**
+ * Writes the specified <code>byte</code> to this output stream.
+ *
+ * @param i
+ * source byte
+ * @throws IOException
+ * if an I/O error occurs.
+ */
+ public void write(int i) throws IOException {
+ singleByte[0] = (byte) i;
+ write(singleByte, 0, 1);
+ }
+
+ /**
+ * Writes <code>len</code> bytes from the specified <code>b</code> array starting at <code>offset</code> to this
+ * output stream.
+ *
+ * @param b
+ * source byte array
+ * @param offset
+ * where to start reading the bytes
+ * @param len
+ * maximum number of bytes to write
+ *
+ * @throws IOException
+ * if an I/O error occurs.
+ * @throws NullPointerException
+ * if the byte array parameter is null
+ * @throws IndexOutOfBoundsException
+ * if offset, len or buffer size are invalid
+ */
+ public void write(byte b[], int offset, int len) throws IOException {
+ if (b == null) {
+ throw new NullPointerException();
+ } else if (offset < 0 || len < 0) {
+ throw new IndexOutOfBoundsException();
+ } else if (offset > b.length || offset + len > b.length) {
+ throw new IndexOutOfBoundsException();
+ } else if (len > 0) {
+ if (doEncode) {
+ baseNCodec.encode(b, offset, len);
+ } else {
+ baseNCodec.decode(b, offset, len);
+ }
+ flush(false);
+ }
+ }
+
+ /**
+ * Flushes this output stream and forces any buffered output bytes to be written out to the stream. If propogate is
+ * true, the wrapped stream will also be flushed.
+ *
+ * @param propogate
+ * boolean flag to indicate whether the wrapped OutputStream should also be flushed.
+ * @throws IOException
+ * if an I/O error occurs.
+ */
+ private void flush(boolean propogate) throws IOException {
+ int avail = baseNCodec.available();
+ if (avail > 0) {
+ byte[] buf = new byte[avail];
+ int c = baseNCodec.readResults(buf, 0, avail);
+ if (c > 0) {
+ out.write(buf, 0, c);
+ }
+ }
+ if (propogate) {
+ out.flush();
+ }
+ }
+
+ /**
+ * Flushes this output stream and forces any buffered output bytes to be written out to the stream.
+ *
+ * @throws IOException
+ * if an I/O error occurs.
+ */
+ public void flush() throws IOException {
+ flush(true);
+ }
+
+ /**
+ * Closes this output stream and releases any system resources associated with the stream.
+ *
+ * @throws IOException
+ * if an I/O error occurs.
+ */
+ public void close() throws IOException {
+ // Notify encoder of EOF (-1).
+ if (doEncode) {
+ baseNCodec.encode(singleByte, 0, -1);
+ } else {
+ baseNCodec.decode(singleByte, 0, -1);
+ }
+ flush();
+ out.close();
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BinaryCodec.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BinaryCodec.java
new file mode 100644
index 000000000..141474151
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BinaryCodec.java
@@ -0,0 +1,297 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.binary;
+
+import org.mozilla.apache.commons.codec.BinaryDecoder;
+import org.mozilla.apache.commons.codec.BinaryEncoder;
+import org.mozilla.apache.commons.codec.DecoderException;
+import org.mozilla.apache.commons.codec.EncoderException;
+
+/**
+ * Converts between byte arrays and strings of "0"s and "1"s.
+ *
+ * TODO: may want to add more bit vector functions like and/or/xor/nand
+ * TODO: also might be good to generate boolean[] from byte[] et cetera.
+ *
+ * @author Apache Software Foundation
+ * @since 1.3
+ * @version $Id: BinaryCodec.java 1080701 2011-03-11 17:52:27Z ggregory $
+ */
+public class BinaryCodec implements BinaryDecoder, BinaryEncoder {
+ /*
+ * tried to avoid using ArrayUtils to minimize dependencies while using these empty arrays - dep is just not worth
+ * it.
+ */
+ /** Empty char array. */
+ private static final char[] EMPTY_CHAR_ARRAY = new char[0];
+
+ /** Empty byte array. */
+ private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+
+ /** Mask for bit 0 of a byte. */
+ private static final int BIT_0 = 1;
+
+ /** Mask for bit 1 of a byte. */
+ private static final int BIT_1 = 0x02;
+
+ /** Mask for bit 2 of a byte. */
+ private static final int BIT_2 = 0x04;
+
+ /** Mask for bit 3 of a byte. */
+ private static final int BIT_3 = 0x08;
+
+ /** Mask for bit 4 of a byte. */
+ private static final int BIT_4 = 0x10;
+
+ /** Mask for bit 5 of a byte. */
+ private static final int BIT_5 = 0x20;
+
+ /** Mask for bit 6 of a byte. */
+ private static final int BIT_6 = 0x40;
+
+ /** Mask for bit 7 of a byte. */
+ private static final int BIT_7 = 0x80;
+
+ private static final int[] BITS = {BIT_0, BIT_1, BIT_2, BIT_3, BIT_4, BIT_5, BIT_6, BIT_7};
+
+ /**
+ * Converts an array of raw binary data into an array of ASCII 0 and 1 characters.
+ *
+ * @param raw
+ * the raw binary data to convert
+ * @return 0 and 1 ASCII character bytes one for each bit of the argument
+ * @see org.mozilla.apache.commons.codec.BinaryEncoder#encode(byte[])
+ */
+ public byte[] encode(byte[] raw) {
+ return toAsciiBytes(raw);
+ }
+
+ /**
+ * Converts an array of raw binary data into an array of ASCII 0 and 1 chars.
+ *
+ * @param raw
+ * the raw binary data to convert
+ * @return 0 and 1 ASCII character chars one for each bit of the argument
+ * @throws EncoderException
+ * if the argument is not a byte[]
+ * @see org.mozilla.apache.commons.codec.Encoder#encode(Object)
+ */
+ public Object encode(Object raw) throws EncoderException {
+ if (!(raw instanceof byte[])) {
+ throw new EncoderException("argument not a byte array");
+ }
+ return toAsciiChars((byte[]) raw);
+ }
+
+ /**
+ * Decodes a byte array where each byte represents an ASCII '0' or '1'.
+ *
+ * @param ascii
+ * each byte represents an ASCII '0' or '1'
+ * @return the raw encoded binary where each bit corresponds to a byte in the byte array argument
+ * @throws DecoderException
+ * if argument is not a byte[], char[] or String
+ * @see org.mozilla.apache.commons.codec.Decoder#decode(Object)
+ */
+ public Object decode(Object ascii) throws DecoderException {
+ if (ascii == null) {
+ return EMPTY_BYTE_ARRAY;
+ }
+ if (ascii instanceof byte[]) {
+ return fromAscii((byte[]) ascii);
+ }
+ if (ascii instanceof char[]) {
+ return fromAscii((char[]) ascii);
+ }
+ if (ascii instanceof String) {
+ return fromAscii(((String) ascii).toCharArray());
+ }
+ throw new DecoderException("argument not a byte array");
+ }
+
+ /**
+ * Decodes a byte array where each byte represents an ASCII '0' or '1'.
+ *
+ * @param ascii
+ * each byte represents an ASCII '0' or '1'
+ * @return the raw encoded binary where each bit corresponds to a byte in the byte array argument
+ * @see org.mozilla.apache.commons.codec.Decoder#decode(Object)
+ */
+ public byte[] decode(byte[] ascii) {
+ return fromAscii(ascii);
+ }
+
+ /**
+ * Decodes a String where each char of the String represents an ASCII '0' or '1'.
+ *
+ * @param ascii
+ * String of '0' and '1' characters
+ * @return the raw encoded binary where each bit corresponds to a byte in the byte array argument
+ * @see org.mozilla.apache.commons.codec.Decoder#decode(Object)
+ */
+ public byte[] toByteArray(String ascii) {
+ if (ascii == null) {
+ return EMPTY_BYTE_ARRAY;
+ }
+ return fromAscii(ascii.toCharArray());
+ }
+
+ // ------------------------------------------------------------------------
+ //
+ // static codec operations
+ //
+ // ------------------------------------------------------------------------
+ /**
+ * Decodes a char array where each char represents an ASCII '0' or '1'.
+ *
+ * @param ascii
+ * each char represents an ASCII '0' or '1'
+ * @return the raw encoded binary where each bit corresponds to a char in the char array argument
+ */
+ public static byte[] fromAscii(char[] ascii) {
+ if (ascii == null || ascii.length == 0) {
+ return EMPTY_BYTE_ARRAY;
+ }
+ // get length/8 times bytes with 3 bit shifts to the right of the length
+ byte[] l_raw = new byte[ascii.length >> 3];
+ /*
+ * We decr index jj by 8 as we go along to not recompute indices using multiplication every time inside the
+ * loop.
+ */
+ for (int ii = 0, jj = ascii.length - 1; ii < l_raw.length; ii++, jj -= 8) {
+ for (int bits = 0; bits < BITS.length; ++bits) {
+ if (ascii[jj - bits] == '1') {
+ l_raw[ii] |= BITS[bits];
+ }
+ }
+ }
+ return l_raw;
+ }
+
+ /**
+ * Decodes a byte array where each byte represents an ASCII '0' or '1'.
+ *
+ * @param ascii
+ * each byte represents an ASCII '0' or '1'
+ * @return the raw encoded binary where each bit corresponds to a byte in the byte array argument
+ */
+ public static byte[] fromAscii(byte[] ascii) {
+ if (isEmpty(ascii)) {
+ return EMPTY_BYTE_ARRAY;
+ }
+ // get length/8 times bytes with 3 bit shifts to the right of the length
+ byte[] l_raw = new byte[ascii.length >> 3];
+ /*
+ * We decr index jj by 8 as we go along to not recompute indices using multiplication every time inside the
+ * loop.
+ */
+ for (int ii = 0, jj = ascii.length - 1; ii < l_raw.length; ii++, jj -= 8) {
+ for (int bits = 0; bits < BITS.length; ++bits) {
+ if (ascii[jj - bits] == '1') {
+ l_raw[ii] |= BITS[bits];
+ }
+ }
+ }
+ return l_raw;
+ }
+
+ /**
+ * Returns <code>true</code> if the given array is <code>null</code> or empty (size 0.)
+ *
+ * @param array
+ * the source array
+ * @return <code>true</code> if the given array is <code>null</code> or empty (size 0.)
+ */
+ private static boolean isEmpty(byte[] array) {
+ return array == null || array.length == 0;
+ }
+
+ /**
+ * Converts an array of raw binary data into an array of ASCII 0 and 1 character bytes - each byte is a truncated
+ * char.
+ *
+ * @param raw
+ * the raw binary data to convert
+ * @return an array of 0 and 1 character bytes for each bit of the argument
+ * @see org.mozilla.apache.commons.codec.BinaryEncoder#encode(byte[])
+ */
+ public static byte[] toAsciiBytes(byte[] raw) {
+ if (isEmpty(raw)) {
+ return EMPTY_BYTE_ARRAY;
+ }
+ // get 8 times the bytes with 3 bit shifts to the left of the length
+ byte[] l_ascii = new byte[raw.length << 3];
+ /*
+ * We decr index jj by 8 as we go along to not recompute indices using multiplication every time inside the
+ * loop.
+ */
+ for (int ii = 0, jj = l_ascii.length - 1; ii < raw.length; ii++, jj -= 8) {
+ for (int bits = 0; bits < BITS.length; ++bits) {
+ if ((raw[ii] & BITS[bits]) == 0) {
+ l_ascii[jj - bits] = '0';
+ } else {
+ l_ascii[jj - bits] = '1';
+ }
+ }
+ }
+ return l_ascii;
+ }
+
+ /**
+ * Converts an array of raw binary data into an array of ASCII 0 and 1 characters.
+ *
+ * @param raw
+ * the raw binary data to convert
+ * @return an array of 0 and 1 characters for each bit of the argument
+ * @see org.mozilla.apache.commons.codec.BinaryEncoder#encode(byte[])
+ */
+ public static char[] toAsciiChars(byte[] raw) {
+ if (isEmpty(raw)) {
+ return EMPTY_CHAR_ARRAY;
+ }
+ // get 8 times the bytes with 3 bit shifts to the left of the length
+ char[] l_ascii = new char[raw.length << 3];
+ /*
+ * We decr index jj by 8 as we go along to not recompute indices using multiplication every time inside the
+ * loop.
+ */
+ for (int ii = 0, jj = l_ascii.length - 1; ii < raw.length; ii++, jj -= 8) {
+ for (int bits = 0; bits < BITS.length; ++bits) {
+ if ((raw[ii] & BITS[bits]) == 0) {
+ l_ascii[jj - bits] = '0';
+ } else {
+ l_ascii[jj - bits] = '1';
+ }
+ }
+ }
+ return l_ascii;
+ }
+
+ /**
+ * Converts an array of raw binary data into a String of ASCII 0 and 1 characters.
+ *
+ * @param raw
+ * the raw binary data to convert
+ * @return a String of 0 and 1 characters representing the binary data
+ * @see org.mozilla.apache.commons.codec.BinaryEncoder#encode(byte[])
+ */
+ public static String toAsciiString(byte[] raw) {
+ return new String(toAsciiChars(raw));
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Hex.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Hex.java
new file mode 100644
index 000000000..a2e34fe34
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Hex.java
@@ -0,0 +1,302 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.binary;
+
+import java.io.UnsupportedEncodingException;
+
+import org.mozilla.apache.commons.codec.BinaryDecoder;
+import org.mozilla.apache.commons.codec.BinaryEncoder;
+import org.mozilla.apache.commons.codec.CharEncoding;
+import org.mozilla.apache.commons.codec.DecoderException;
+import org.mozilla.apache.commons.codec.EncoderException;
+
+/**
+ * Converts hexadecimal Strings. The charset used for certain operation can be set, the default is set in
+ * {@link #DEFAULT_CHARSET_NAME}
+ *
+ * @since 1.1
+ * @author Apache Software Foundation
+ * @version $Id: Hex.java 1080701 2011-03-11 17:52:27Z ggregory $
+ */
+public class Hex implements BinaryEncoder, BinaryDecoder {
+
+ /**
+ * Default charset name is {@link CharEncoding#UTF_8}
+ *
+ * @since 1.4
+ */
+ public static final String DEFAULT_CHARSET_NAME = CharEncoding.UTF_8;
+
+ /**
+ * Used to build output as Hex
+ */
+ private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+ /**
+ * Used to build output as Hex
+ */
+ private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+ /**
+ * Converts an array of characters representing hexadecimal values into an array of bytes of those same values. The
+ * returned array will be half the length of the passed array, as it takes two characters to represent any given
+ * byte. An exception is thrown if the passed char array has an odd number of elements.
+ *
+ * @param data
+ * An array of characters containing hexadecimal digits
+ * @return A byte array containing binary data decoded from the supplied char array.
+ * @throws DecoderException
+ * Thrown if an odd number or illegal of characters is supplied
+ */
+ public static byte[] decodeHex(char[] data) throws DecoderException {
+
+ int len = data.length;
+
+ if ((len & 0x01) != 0) {
+ throw new DecoderException("Odd number of characters.");
+ }
+
+ byte[] out = new byte[len >> 1];
+
+ // two characters form the hex value.
+ for (int i = 0, j = 0; j < len; i++) {
+ int f = toDigit(data[j], j) << 4;
+ j++;
+ f = f | toDigit(data[j], j);
+ j++;
+ out[i] = (byte) (f & 0xFF);
+ }
+
+ return out;
+ }
+
+ /**
+ * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
+ * The returned array will be double the length of the passed array, as it takes two characters to represent any
+ * given byte.
+ *
+ * @param data
+ * a byte[] to convert to Hex characters
+ * @return A char[] containing hexadecimal characters
+ */
+ public static char[] encodeHex(byte[] data) {
+ return encodeHex(data, true);
+ }
+
+ /**
+ * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
+ * The returned array will be double the length of the passed array, as it takes two characters to represent any
+ * given byte.
+ *
+ * @param data
+ * a byte[] to convert to Hex characters
+ * @param toLowerCase
+ * <code>true</code> converts to lowercase, <code>false</code> to uppercase
+ * @return A char[] containing hexadecimal characters
+ * @since 1.4
+ */
+ public static char[] encodeHex(byte[] data, boolean toLowerCase) {
+ return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
+ }
+
+ /**
+ * Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
+ * The returned array will be double the length of the passed array, as it takes two characters to represent any
+ * given byte.
+ *
+ * @param data
+ * a byte[] to convert to Hex characters
+ * @param toDigits
+ * the output alphabet
+ * @return A char[] containing hexadecimal characters
+ * @since 1.4
+ */
+ protected static char[] encodeHex(byte[] data, char[] toDigits) {
+ int l = data.length;
+ char[] out = new char[l << 1];
+ // two characters form the hex value.
+ for (int i = 0, j = 0; i < l; i++) {
+ out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
+ out[j++] = toDigits[0x0F & data[i]];
+ }
+ return out;
+ }
+
+ /**
+ * Converts an array of bytes into a String representing the hexadecimal values of each byte in order. The returned
+ * String will be double the length of the passed array, as it takes two characters to represent any given byte.
+ *
+ * @param data
+ * a byte[] to convert to Hex characters
+ * @return A String containing hexadecimal characters
+ * @since 1.4
+ */
+ public static String encodeHexString(byte[] data) {
+ return new String(encodeHex(data));
+ }
+
+ /**
+ * Converts a hexadecimal character to an integer.
+ *
+ * @param ch
+ * A character to convert to an integer digit
+ * @param index
+ * The index of the character in the source
+ * @return An integer
+ * @throws DecoderException
+ * Thrown if ch is an illegal hex character
+ */
+ protected static int toDigit(char ch, int index) throws DecoderException {
+ int digit = Character.digit(ch, 16);
+ if (digit == -1) {
+ throw new DecoderException("Illegal hexadecimal character " + ch + " at index " + index);
+ }
+ return digit;
+ }
+
+ private final String charsetName;
+
+ /**
+ * Creates a new codec with the default charset name {@link #DEFAULT_CHARSET_NAME}
+ */
+ public Hex() {
+ // use default encoding
+ this.charsetName = DEFAULT_CHARSET_NAME;
+ }
+
+ /**
+ * Creates a new codec with the given charset name.
+ *
+ * @param csName
+ * the charset name.
+ * @since 1.4
+ */
+ public Hex(String csName) {
+ this.charsetName = csName;
+ }
+
+ /**
+ * Converts an array of character bytes representing hexadecimal values into an array of bytes of those same values.
+ * The returned array will be half the length of the passed array, as it takes two characters to represent any given
+ * byte. An exception is thrown if the passed char array has an odd number of elements.
+ *
+ * @param array
+ * An array of character bytes containing hexadecimal digits
+ * @return A byte array containing binary data decoded from the supplied byte array (representing characters).
+ * @throws DecoderException
+ * Thrown if an odd number of characters is supplied to this function
+ * @see #decodeHex(char[])
+ */
+ public byte[] decode(byte[] array) throws DecoderException {
+ try {
+ return decodeHex(new String(array, getCharsetName()).toCharArray());
+ } catch (UnsupportedEncodingException e) {
+ throw new DecoderException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Converts a String or an array of character bytes representing hexadecimal values into an array of bytes of those
+ * same values. The returned array will be half the length of the passed String or array, as it takes two characters
+ * to represent any given byte. An exception is thrown if the passed char array has an odd number of elements.
+ *
+ * @param object
+ * A String or, an array of character bytes containing hexadecimal digits
+ * @return A byte array containing binary data decoded from the supplied byte array (representing characters).
+ * @throws DecoderException
+ * Thrown if an odd number of characters is supplied to this function or the object is not a String or
+ * char[]
+ * @see #decodeHex(char[])
+ */
+ public Object decode(Object object) throws DecoderException {
+ try {
+ char[] charArray = object instanceof String ? ((String) object).toCharArray() : (char[]) object;
+ return decodeHex(charArray);
+ } catch (ClassCastException e) {
+ throw new DecoderException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Converts an array of bytes into an array of bytes for the characters representing the hexadecimal values of each
+ * byte in order. The returned array will be double the length of the passed array, as it takes two characters to
+ * represent any given byte.
+ * <p>
+ * The conversion from hexadecimal characters to the returned bytes is performed with the charset named by
+ * {@link #getCharsetName()}.
+ * </p>
+ *
+ * @param array
+ * a byte[] to convert to Hex characters
+ * @return A byte[] containing the bytes of the hexadecimal characters
+ * @throws IllegalStateException
+ * if the charsetName is invalid. This API throws {@link IllegalStateException} instead of
+ * {@link UnsupportedEncodingException} for backward compatibility.
+ * @see #encodeHex(byte[])
+ */
+ public byte[] encode(byte[] array) {
+ return StringUtils.getBytesUnchecked(encodeHexString(array), getCharsetName());
+ }
+
+ /**
+ * Converts a String or an array of bytes into an array of characters representing the hexadecimal values of each
+ * byte in order. The returned array will be double the length of the passed String or array, as it takes two
+ * characters to represent any given byte.
+ * <p>
+ * The conversion from hexadecimal characters to bytes to be encoded to performed with the charset named by
+ * {@link #getCharsetName()}.
+ * </p>
+ *
+ * @param object
+ * a String, or byte[] to convert to Hex characters
+ * @return A char[] containing hexadecimal characters
+ * @throws EncoderException
+ * Thrown if the given object is not a String or byte[]
+ * @see #encodeHex(byte[])
+ */
+ public Object encode(Object object) throws EncoderException {
+ try {
+ byte[] byteArray = object instanceof String ? ((String) object).getBytes(getCharsetName()) : (byte[]) object;
+ return encodeHex(byteArray);
+ } catch (ClassCastException e) {
+ throw new EncoderException(e.getMessage(), e);
+ } catch (UnsupportedEncodingException e) {
+ throw new EncoderException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Gets the charset name.
+ *
+ * @return the charset name.
+ * @since 1.4
+ */
+ public String getCharsetName() {
+ return this.charsetName;
+ }
+
+ /**
+ * Returns a string representation of the object, which includes the charset name.
+ *
+ * @return a string representation of the object.
+ */
+ public String toString() {
+ return super.toString() + "[charsetName=" + this.charsetName + "]";
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/StringUtils.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/StringUtils.java
new file mode 100644
index 000000000..7bf960124
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/StringUtils.java
@@ -0,0 +1,287 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.binary;
+
+import java.io.UnsupportedEncodingException;
+
+import org.mozilla.apache.commons.codec.CharEncoding;
+
+/**
+ * Converts String to and from bytes using the encodings required by the Java specification. These encodings are specified in <a
+ * href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ *
+ * @see CharEncoding
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
+ * @version $Id: StringUtils.java 950460 2010-06-02 09:43:02Z sebb $
+ * @since 1.4
+ */
+public class StringUtils {
+
+ /**
+ * Encodes the given string into a sequence of bytes using the ISO-8859-1 charset, storing the result into a new
+ * byte array.
+ *
+ * @param string
+ * the String to encode, may be <code>null</code>
+ * @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
+ * @throws IllegalStateException
+ * Thrown when the charset is missing, which should be never according the the Java specification.
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ * @see #getBytesUnchecked(String, String)
+ */
+ public static byte[] getBytesIso8859_1(String string) {
+ return StringUtils.getBytesUnchecked(string, CharEncoding.ISO_8859_1);
+ }
+
+ /**
+ * Encodes the given string into a sequence of bytes using the US-ASCII charset, storing the result into a new byte
+ * array.
+ *
+ * @param string
+ * the String to encode, may be <code>null</code>
+ * @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
+ * @throws IllegalStateException
+ * Thrown when the charset is missing, which should be never according the the Java specification.
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ * @see #getBytesUnchecked(String, String)
+ */
+ public static byte[] getBytesUsAscii(String string) {
+ return StringUtils.getBytesUnchecked(string, CharEncoding.US_ASCII);
+ }
+
+ /**
+ * Encodes the given string into a sequence of bytes using the UTF-16 charset, storing the result into a new byte
+ * array.
+ *
+ * @param string
+ * the String to encode, may be <code>null</code>
+ * @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
+ * @throws IllegalStateException
+ * Thrown when the charset is missing, which should be never according the the Java specification.
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ * @see #getBytesUnchecked(String, String)
+ */
+ public static byte[] getBytesUtf16(String string) {
+ return StringUtils.getBytesUnchecked(string, CharEncoding.UTF_16);
+ }
+
+ /**
+ * Encodes the given string into a sequence of bytes using the UTF-16BE charset, storing the result into a new byte
+ * array.
+ *
+ * @param string
+ * the String to encode, may be <code>null</code>
+ * @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
+ * @throws IllegalStateException
+ * Thrown when the charset is missing, which should be never according the the Java specification.
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ * @see #getBytesUnchecked(String, String)
+ */
+ public static byte[] getBytesUtf16Be(String string) {
+ return StringUtils.getBytesUnchecked(string, CharEncoding.UTF_16BE);
+ }
+
+ /**
+ * Encodes the given string into a sequence of bytes using the UTF-16LE charset, storing the result into a new byte
+ * array.
+ *
+ * @param string
+ * the String to encode, may be <code>null</code>
+ * @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
+ * @throws IllegalStateException
+ * Thrown when the charset is missing, which should be never according the the Java specification.
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ * @see #getBytesUnchecked(String, String)
+ */
+ public static byte[] getBytesUtf16Le(String string) {
+ return StringUtils.getBytesUnchecked(string, CharEncoding.UTF_16LE);
+ }
+
+ /**
+ * Encodes the given string into a sequence of bytes using the UTF-8 charset, storing the result into a new byte
+ * array.
+ *
+ * @param string
+ * the String to encode, may be <code>null</code>
+ * @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
+ * @throws IllegalStateException
+ * Thrown when the charset is missing, which should be never according the the Java specification.
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ * @see #getBytesUnchecked(String, String)
+ */
+ public static byte[] getBytesUtf8(String string) {
+ return StringUtils.getBytesUnchecked(string, CharEncoding.UTF_8);
+ }
+
+ /**
+ * Encodes the given string into a sequence of bytes using the named charset, storing the result into a new byte
+ * array.
+ * <p>
+ * This method catches {@link UnsupportedEncodingException} and rethrows it as {@link IllegalStateException}, which
+ * should never happen for a required charset name. Use this method when the encoding is required to be in the JRE.
+ * </p>
+ *
+ * @param string
+ * the String to encode, may be <code>null</code>
+ * @param charsetName
+ * The name of a required {@link java.nio.charset.Charset}
+ * @return encoded bytes, or <code>null</code> if the input string was <code>null</code>
+ * @throws IllegalStateException
+ * Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen for a
+ * required charset name.
+ * @see CharEncoding
+ * @see String#getBytes(String)
+ */
+ public static byte[] getBytesUnchecked(String string, String charsetName) {
+ if (string == null) {
+ return null;
+ }
+ try {
+ return string.getBytes(charsetName);
+ } catch (UnsupportedEncodingException e) {
+ throw StringUtils.newIllegalStateException(charsetName, e);
+ }
+ }
+
+ private static IllegalStateException newIllegalStateException(String charsetName, UnsupportedEncodingException e) {
+ return new IllegalStateException(charsetName + ": " + e);
+ }
+
+ /**
+ * Constructs a new <code>String</code> by decoding the specified array of bytes using the given charset.
+ * <p>
+ * This method catches {@link UnsupportedEncodingException} and re-throws it as {@link IllegalStateException}, which
+ * should never happen for a required charset name. Use this method when the encoding is required to be in the JRE.
+ * </p>
+ *
+ * @param bytes
+ * The bytes to be decoded into characters, may be <code>null</code>
+ * @param charsetName
+ * The name of a required {@link java.nio.charset.Charset}
+ * @return A new <code>String</code> decoded from the specified array of bytes using the given charset,
+ * or <code>null</code> if the input byte arrray was <code>null</code>.
+ * @throws IllegalStateException
+ * Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen for a
+ * required charset name.
+ * @see CharEncoding
+ * @see String#String(byte[], String)
+ */
+ public static String newString(byte[] bytes, String charsetName) {
+ if (bytes == null) {
+ return null;
+ }
+ try {
+ return new String(bytes, charsetName);
+ } catch (UnsupportedEncodingException e) {
+ throw StringUtils.newIllegalStateException(charsetName, e);
+ }
+ }
+
+ /**
+ * Constructs a new <code>String</code> by decoding the specified array of bytes using the ISO-8859-1 charset.
+ *
+ * @param bytes
+ * The bytes to be decoded into characters, may be <code>null</code>
+ * @return A new <code>String</code> decoded from the specified array of bytes using the ISO-8859-1 charset,
+ * or <code>null</code> if the input byte array was <code>null</code>.
+ * @throws IllegalStateException
+ * Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen since the
+ * charset is required.
+ */
+ public static String newStringIso8859_1(byte[] bytes) {
+ return StringUtils.newString(bytes, CharEncoding.ISO_8859_1);
+ }
+
+ /**
+ * Constructs a new <code>String</code> by decoding the specified array of bytes using the US-ASCII charset.
+ *
+ * @param bytes
+ * The bytes to be decoded into characters
+ * @return A new <code>String</code> decoded from the specified array of bytes using the US-ASCII charset,
+ * or <code>null</code> if the input byte array was <code>null</code>.
+ * @throws IllegalStateException
+ * Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen since the
+ * charset is required.
+ */
+ public static String newStringUsAscii(byte[] bytes) {
+ return StringUtils.newString(bytes, CharEncoding.US_ASCII);
+ }
+
+ /**
+ * Constructs a new <code>String</code> by decoding the specified array of bytes using the UTF-16 charset.
+ *
+ * @param bytes
+ * The bytes to be decoded into characters
+ * @return A new <code>String</code> decoded from the specified array of bytes using the UTF-16 charset
+ * or <code>null</code> if the input byte array was <code>null</code>.
+ * @throws IllegalStateException
+ * Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen since the
+ * charset is required.
+ */
+ public static String newStringUtf16(byte[] bytes) {
+ return StringUtils.newString(bytes, CharEncoding.UTF_16);
+ }
+
+ /**
+ * Constructs a new <code>String</code> by decoding the specified array of bytes using the UTF-16BE charset.
+ *
+ * @param bytes
+ * The bytes to be decoded into characters
+ * @return A new <code>String</code> decoded from the specified array of bytes using the UTF-16BE charset,
+ * or <code>null</code> if the input byte array was <code>null</code>.
+ * @throws IllegalStateException
+ * Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen since the
+ * charset is required.
+ */
+ public static String newStringUtf16Be(byte[] bytes) {
+ return StringUtils.newString(bytes, CharEncoding.UTF_16BE);
+ }
+
+ /**
+ * Constructs a new <code>String</code> by decoding the specified array of bytes using the UTF-16LE charset.
+ *
+ * @param bytes
+ * The bytes to be decoded into characters
+ * @return A new <code>String</code> decoded from the specified array of bytes using the UTF-16LE charset,
+ * or <code>null</code> if the input byte array was <code>null</code>.
+ * @throws IllegalStateException
+ * Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen since the
+ * charset is required.
+ */
+ public static String newStringUtf16Le(byte[] bytes) {
+ return StringUtils.newString(bytes, CharEncoding.UTF_16LE);
+ }
+
+ /**
+ * Constructs a new <code>String</code> by decoding the specified array of bytes using the UTF-8 charset.
+ *
+ * @param bytes
+ * The bytes to be decoded into characters
+ * @return A new <code>String</code> decoded from the specified array of bytes using the UTF-8 charset,
+ * or <code>null</code> if the input byte array was <code>null</code>.
+ * @throws IllegalStateException
+ * Thrown when a {@link UnsupportedEncodingException} is caught, which should never happen since the
+ * charset is required.
+ */
+ public static String newStringUtf8(byte[] bytes) {
+ return StringUtils.newString(bytes, CharEncoding.UTF_8);
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/package.html b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/package.html
new file mode 100644
index 000000000..13345ece4
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/package.html
@@ -0,0 +1,21 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. 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.
+-->
+<html>
+ <body>
+ Base64, Base32, Binary, and Hexadecimal String encoding and decoding.
+ </body>
+</html>
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/digest/DigestUtils.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/digest/DigestUtils.java
new file mode 100644
index 000000000..2421bb0fe
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/digest/DigestUtils.java
@@ -0,0 +1,583 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.digest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.mozilla.apache.commons.codec.binary.Hex;
+import org.mozilla.apache.commons.codec.binary.StringUtils;
+
+/**
+ * Operations to simplify common {@link java.security.MessageDigest} tasks. This class is thread safe.
+ *
+ * @author Apache Software Foundation
+ * @version $Id: DigestUtils.java 1064793 2011-01-28 17:42:55Z ggregory $
+ */
+public class DigestUtils {
+
+ private static final int STREAM_BUFFER_LENGTH = 1024;
+
+ /**
+ * Read through an InputStream and returns the digest for the data
+ *
+ * @param digest
+ * The MessageDigest to use (e.g. MD5)
+ * @param data
+ * Data to digest
+ * @return MD5 digest
+ * @throws IOException
+ * On error reading from the stream
+ */
+ private static byte[] digest(MessageDigest digest, InputStream data) throws IOException {
+ byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
+ int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
+
+ while (read > -1) {
+ digest.update(buffer, 0, read);
+ read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
+ }
+
+ return digest.digest();
+ }
+
+ /**
+ * Calls {@link StringUtils#getBytesUtf8(String)}
+ *
+ * @param data
+ * the String to encode
+ * @return encoded bytes
+ */
+ private static byte[] getBytesUtf8(String data) {
+ return StringUtils.getBytesUtf8(data);
+ }
+
+ /**
+ * Returns a <code>MessageDigest</code> for the given <code>algorithm</code>.
+ *
+ * @param algorithm
+ * the name of the algorithm requested. See <a
+ * href="http://java.sun.com/j2se/1.3/docs/guide/security/CryptoSpec.html#AppA">Appendix A in the Java
+ * Cryptography Architecture API Specification & Reference</a> for information about standard algorithm
+ * names.
+ * @return An MD5 digest instance.
+ * @see MessageDigest#getInstance(String)
+ * @throws RuntimeException
+ * when a {@link java.security.NoSuchAlgorithmException} is caught.
+ */
+ static MessageDigest getDigest(String algorithm) {
+ try {
+ return MessageDigest.getInstance(algorithm);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ /**
+ * Returns an MD5 MessageDigest.
+ *
+ * @return An MD5 digest instance.
+ * @throws RuntimeException
+ * when a {@link java.security.NoSuchAlgorithmException} is caught.
+ */
+ private static MessageDigest getMd5Digest() {
+ return getDigest("MD5");
+ }
+
+ /**
+ * Returns an SHA-256 digest.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @return An SHA-256 digest instance.
+ * @throws RuntimeException
+ * when a {@link java.security.NoSuchAlgorithmException} is caught.
+ */
+ private static MessageDigest getSha256Digest() {
+ return getDigest("SHA-256");
+ }
+
+ /**
+ * Returns an SHA-384 digest.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @return An SHA-384 digest instance.
+ * @throws RuntimeException
+ * when a {@link java.security.NoSuchAlgorithmException} is caught.
+ */
+ private static MessageDigest getSha384Digest() {
+ return getDigest("SHA-384");
+ }
+
+ /**
+ * Returns an SHA-512 digest.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @return An SHA-512 digest instance.
+ * @throws RuntimeException
+ * when a {@link java.security.NoSuchAlgorithmException} is caught.
+ */
+ private static MessageDigest getSha512Digest() {
+ return getDigest("SHA-512");
+ }
+
+ /**
+ * Returns an SHA-1 digest.
+ *
+ * @return An SHA-1 digest instance.
+ * @throws RuntimeException
+ * when a {@link java.security.NoSuchAlgorithmException} is caught.
+ */
+ private static MessageDigest getShaDigest() {
+ return getDigest("SHA");
+ }
+
+ /**
+ * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
+ *
+ * @param data
+ * Data to digest
+ * @return MD5 digest
+ */
+ public static byte[] md5(byte[] data) {
+ return getMd5Digest().digest(data);
+ }
+
+ /**
+ * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
+ *
+ * @param data
+ * Data to digest
+ * @return MD5 digest
+ * @throws IOException
+ * On error reading from the stream
+ * @since 1.4
+ */
+ public static byte[] md5(InputStream data) throws IOException {
+ return digest(getMd5Digest(), data);
+ }
+
+ /**
+ * Calculates the MD5 digest and returns the value as a 16 element <code>byte[]</code>.
+ *
+ * @param data
+ * Data to digest
+ * @return MD5 digest
+ */
+ public static byte[] md5(String data) {
+ return md5(getBytesUtf8(data));
+ }
+
+ /**
+ * Calculates the MD5 digest and returns the value as a 32 character hex string.
+ *
+ * @param data
+ * Data to digest
+ * @return MD5 digest as a hex string
+ */
+ public static String md5Hex(byte[] data) {
+ return Hex.encodeHexString(md5(data));
+ }
+
+ /**
+ * Calculates the MD5 digest and returns the value as a 32 character hex string.
+ *
+ * @param data
+ * Data to digest
+ * @return MD5 digest as a hex string
+ * @throws IOException
+ * On error reading from the stream
+ * @since 1.4
+ */
+ public static String md5Hex(InputStream data) throws IOException {
+ return Hex.encodeHexString(md5(data));
+ }
+
+ /**
+ * Calculates the MD5 digest and returns the value as a 32 character hex string.
+ *
+ * @param data
+ * Data to digest
+ * @return MD5 digest as a hex string
+ */
+ public static String md5Hex(String data) {
+ return Hex.encodeHexString(md5(data));
+ }
+
+ /**
+ * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-1 digest
+ */
+ public static byte[] sha(byte[] data) {
+ return getShaDigest().digest(data);
+ }
+
+ /**
+ * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-1 digest
+ * @throws IOException
+ * On error reading from the stream
+ * @since 1.4
+ */
+ public static byte[] sha(InputStream data) throws IOException {
+ return digest(getShaDigest(), data);
+ }
+
+ /**
+ * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-1 digest
+ */
+ public static byte[] sha(String data) {
+ return sha(getBytesUtf8(data));
+ }
+
+ /**
+ * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-256 digest
+ * @since 1.4
+ */
+ public static byte[] sha256(byte[] data) {
+ return getSha256Digest().digest(data);
+ }
+
+ /**
+ * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-256 digest
+ * @throws IOException
+ * On error reading from the stream
+ * @since 1.4
+ */
+ public static byte[] sha256(InputStream data) throws IOException {
+ return digest(getSha256Digest(), data);
+ }
+
+ /**
+ * Calculates the SHA-256 digest and returns the value as a <code>byte[]</code>.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-256 digest
+ * @since 1.4
+ */
+ public static byte[] sha256(String data) {
+ return sha256(getBytesUtf8(data));
+ }
+
+ /**
+ * Calculates the SHA-256 digest and returns the value as a hex string.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-256 digest as a hex string
+ * @since 1.4
+ */
+ public static String sha256Hex(byte[] data) {
+ return Hex.encodeHexString(sha256(data));
+ }
+
+ /**
+ * Calculates the SHA-256 digest and returns the value as a hex string.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-256 digest as a hex string
+ * @throws IOException
+ * On error reading from the stream
+ * @since 1.4
+ */
+ public static String sha256Hex(InputStream data) throws IOException {
+ return Hex.encodeHexString(sha256(data));
+ }
+
+ /**
+ * Calculates the SHA-256 digest and returns the value as a hex string.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-256 digest as a hex string
+ * @since 1.4
+ */
+ public static String sha256Hex(String data) {
+ return Hex.encodeHexString(sha256(data));
+ }
+
+ /**
+ * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-384 digest
+ * @since 1.4
+ */
+ public static byte[] sha384(byte[] data) {
+ return getSha384Digest().digest(data);
+ }
+
+ /**
+ * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-384 digest
+ * @throws IOException
+ * On error reading from the stream
+ * @since 1.4
+ */
+ public static byte[] sha384(InputStream data) throws IOException {
+ return digest(getSha384Digest(), data);
+ }
+
+ /**
+ * Calculates the SHA-384 digest and returns the value as a <code>byte[]</code>.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-384 digest
+ * @since 1.4
+ */
+ public static byte[] sha384(String data) {
+ return sha384(getBytesUtf8(data));
+ }
+
+ /**
+ * Calculates the SHA-384 digest and returns the value as a hex string.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-384 digest as a hex string
+ * @since 1.4
+ */
+ public static String sha384Hex(byte[] data) {
+ return Hex.encodeHexString(sha384(data));
+ }
+
+ /**
+ * Calculates the SHA-384 digest and returns the value as a hex string.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-384 digest as a hex string
+ * @throws IOException
+ * On error reading from the stream
+ * @since 1.4
+ */
+ public static String sha384Hex(InputStream data) throws IOException {
+ return Hex.encodeHexString(sha384(data));
+ }
+
+ /**
+ * Calculates the SHA-384 digest and returns the value as a hex string.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-384 digest as a hex string
+ * @since 1.4
+ */
+ public static String sha384Hex(String data) {
+ return Hex.encodeHexString(sha384(data));
+ }
+
+ /**
+ * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-512 digest
+ * @since 1.4
+ */
+ public static byte[] sha512(byte[] data) {
+ return getSha512Digest().digest(data);
+ }
+
+ /**
+ * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-512 digest
+ * @throws IOException
+ * On error reading from the stream
+ * @since 1.4
+ */
+ public static byte[] sha512(InputStream data) throws IOException {
+ return digest(getSha512Digest(), data);
+ }
+
+ /**
+ * Calculates the SHA-512 digest and returns the value as a <code>byte[]</code>.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-512 digest
+ * @since 1.4
+ */
+ public static byte[] sha512(String data) {
+ return sha512(getBytesUtf8(data));
+ }
+
+ /**
+ * Calculates the SHA-512 digest and returns the value as a hex string.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-512 digest as a hex string
+ * @since 1.4
+ */
+ public static String sha512Hex(byte[] data) {
+ return Hex.encodeHexString(sha512(data));
+ }
+
+ /**
+ * Calculates the SHA-512 digest and returns the value as a hex string.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-512 digest as a hex string
+ * @throws IOException
+ * On error reading from the stream
+ * @since 1.4
+ */
+ public static String sha512Hex(InputStream data) throws IOException {
+ return Hex.encodeHexString(sha512(data));
+ }
+
+ /**
+ * Calculates the SHA-512 digest and returns the value as a hex string.
+ * <p>
+ * Throws a <code>RuntimeException</code> on JRE versions prior to 1.4.0.
+ * </p>
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-512 digest as a hex string
+ * @since 1.4
+ */
+ public static String sha512Hex(String data) {
+ return Hex.encodeHexString(sha512(data));
+ }
+
+ /**
+ * Calculates the SHA-1 digest and returns the value as a hex string.
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-1 digest as a hex string
+ */
+ public static String shaHex(byte[] data) {
+ return Hex.encodeHexString(sha(data));
+ }
+
+ /**
+ * Calculates the SHA-1 digest and returns the value as a hex string.
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-1 digest as a hex string
+ * @throws IOException
+ * On error reading from the stream
+ * @since 1.4
+ */
+ public static String shaHex(InputStream data) throws IOException {
+ return Hex.encodeHexString(sha(data));
+ }
+
+ /**
+ * Calculates the SHA-1 digest and returns the value as a hex string.
+ *
+ * @param data
+ * Data to digest
+ * @return SHA-1 digest as a hex string
+ */
+ public static String shaHex(String data) {
+ return Hex.encodeHexString(sha(data));
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/digest/package.html b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/digest/package.html
new file mode 100644
index 000000000..1da976276
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/digest/package.html
@@ -0,0 +1,21 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. 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.
+-->
+<html>
+ <body>
+ Simplifies common {@link java.security.MessageDigest} tasks.
+ </body>
+</html>
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/AbstractCaverphone.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/AbstractCaverphone.java
new file mode 100644
index 000000000..fbcc75943
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/AbstractCaverphone.java
@@ -0,0 +1,78 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.language;
+
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.StringEncoder;
+
+/**
+ * Encodes a string into a Caverphone value.
+ *
+ * This is an algorithm created by the Caversham Project at the University of Otago. It implements the Caverphone 2.0
+ * algorithm:
+ *
+ * @author Apache Software Foundation
+ * @version $Id: Caverphone.java 1075947 2011-03-01 17:56:14Z ggregory $
+ * @see <a href="http://en.wikipedia.org/wiki/Caverphone">Wikipedia - Caverphone</a>
+ * @since 1.5
+ */
+public abstract class AbstractCaverphone implements StringEncoder {
+
+ /**
+ * Creates an instance of the Caverphone encoder
+ */
+ public AbstractCaverphone() {
+ super();
+ }
+
+ /**
+ * Encodes an Object using the caverphone algorithm. This method is provided in order to satisfy the requirements of
+ * the Encoder interface, and will throw an EncoderException if the supplied object is not of type java.lang.String.
+ *
+ * @param source
+ * Object to encode
+ * @return An object (or type java.lang.String) containing the caverphone code which corresponds to the String
+ * supplied.
+ * @throws EncoderException
+ * if the parameter supplied is not of type java.lang.String
+ */
+ public Object encode(Object source) throws EncoderException {
+ if (!(source instanceof String)) {
+ throw new EncoderException("Parameter supplied to Caverphone encode is not of type java.lang.String");
+ }
+ return this.encode((String) source);
+ }
+
+ /**
+ * Tests if the encodings of two strings are equal.
+ *
+ * This method might be promoted to a new AbstractStringEncoder superclass.
+ *
+ * @param str1
+ * First of two strings to compare
+ * @param str2
+ * Second of two strings to compare
+ * @return <code>true</code> if the encodings of these strings are identical, <code>false</code> otherwise.
+ * @throws EncoderException
+ */
+ public boolean isEncodeEqual(String str1, String str2) throws EncoderException {
+ return this.encode(str1).equals(this.encode(str2));
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone.java
new file mode 100644
index 000000000..062fa4135
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone.java
@@ -0,0 +1,104 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.language;
+
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.StringEncoder;
+
+/**
+ * Encodes a string into a Caverphone 2.0 value. Delegate to a {@link Caverphone2} instance.
+ *
+ * This is an algorithm created by the Caversham Project at the University of Otago. It implements the Caverphone 2.0
+ * algorithm:
+ *
+ * @author Apache Software Foundation
+ * @version $Id: Caverphone.java 1079535 2011-03-08 20:54:37Z ggregory $
+ * @see <a href="http://en.wikipedia.org/wiki/Caverphone">Wikipedia - Caverphone</a>
+ * @see <a href="http://caversham.otago.ac.nz/files/working/ctp150804.pdf">Caverphone 2.0 specification</a>
+ * @since 1.4
+ * @deprecated 1.5 Replaced by {@link Caverphone2}, will be removed in 2.0.
+ */
+public class Caverphone implements StringEncoder {
+
+ /**
+ * Delegate to a {@link Caverphone2} instance to avoid code duplication.
+ */
+ final private Caverphone2 encoder = new Caverphone2();
+
+ /**
+ * Creates an instance of the Caverphone encoder
+ */
+ public Caverphone() {
+ super();
+ }
+
+ /**
+ * Encodes the given String into a Caverphone value.
+ *
+ * @param source
+ * String the source string
+ * @return A caverphone code for the given String
+ */
+ public String caverphone(String source) {
+ return this.encoder.encode(source);
+ }
+
+ /**
+ * Encodes an Object using the caverphone algorithm. This method is provided in order to satisfy the requirements of
+ * the Encoder interface, and will throw an EncoderException if the supplied object is not of type java.lang.String.
+ *
+ * @param pObject
+ * Object to encode
+ * @return An object (or type java.lang.String) containing the caverphone code which corresponds to the String
+ * supplied.
+ * @throws EncoderException
+ * if the parameter supplied is not of type java.lang.String
+ */
+ public Object encode(Object pObject) throws EncoderException {
+ if (!(pObject instanceof String)) {
+ throw new EncoderException("Parameter supplied to Caverphone encode is not of type java.lang.String");
+ }
+ return this.caverphone((String) pObject);
+ }
+
+ /**
+ * Encodes a String using the Caverphone algorithm.
+ *
+ * @param pString
+ * String object to encode
+ * @return The caverphone code corresponding to the String supplied
+ */
+ public String encode(String pString) {
+ return this.caverphone(pString);
+ }
+
+ /**
+ * Tests if the caverphones of two strings are identical.
+ *
+ * @param str1
+ * First of two strings to compare
+ * @param str2
+ * Second of two strings to compare
+ * @return <code>true</code> if the caverphones of these strings are identical, <code>false</code> otherwise.
+ */
+ public boolean isCaverphoneEqual(String str1, String str2) {
+ return this.caverphone(str1).equals(this.caverphone(str2));
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone1.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone1.java
new file mode 100644
index 000000000..e0d2e1de3
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone1.java
@@ -0,0 +1,126 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.language;
+
+/**
+ * Encodes a string into a Caverphone 1.0 value.
+ *
+ * This is an algorithm created by the Caversham Project at the University of Otago. It implements the Caverphone 1.0
+ * algorithm:
+ *
+ * @author Apache Software Foundation
+ * @version $Id: Caverphone.java 1075947 2011-03-01 17:56:14Z ggregory $
+ * @see <a href="http://en.wikipedia.org/wiki/Caverphone">Wikipedia - Caverphone</a>
+ * @see <a href="http://caversham.otago.ac.nz/files/working/ctp060902.pdf">Caverphone 1.0 specification</a>
+ * @since 1.5
+ */
+public class Caverphone1 extends AbstractCaverphone {
+
+ private static final String SIX_1 = "111111";
+
+ /**
+ * Encodes the given String into a Caverphone value.
+ *
+ * @param source
+ * String the source string
+ * @return A caverphone code for the given String
+ */
+ public String encode(String source) {
+ String txt = source;
+ if (txt == null || txt.length() == 0) {
+ return SIX_1;
+ }
+
+ // 1. Convert to lowercase
+ txt = txt.toLowerCase(java.util.Locale.ENGLISH);
+
+ // 2. Remove anything not A-Z
+ txt = txt.replaceAll("[^a-z]", "");
+
+ // 3. Handle various start options
+ // 2 is a temporary placeholder to indicate a consonant which we are no longer interested in.
+ txt = txt.replaceAll("^cough", "cou2f");
+ txt = txt.replaceAll("^rough", "rou2f");
+ txt = txt.replaceAll("^tough", "tou2f");
+ txt = txt.replaceAll("^enough", "enou2f");
+ txt = txt.replaceAll("^gn", "2n");
+
+ // End
+ txt = txt.replaceAll("mb$", "m2");
+
+ // 4. Handle replacements
+ txt = txt.replaceAll("cq", "2q");
+ txt = txt.replaceAll("ci", "si");
+ txt = txt.replaceAll("ce", "se");
+ txt = txt.replaceAll("cy", "sy");
+ txt = txt.replaceAll("tch", "2ch");
+ txt = txt.replaceAll("c", "k");
+ txt = txt.replaceAll("q", "k");
+ txt = txt.replaceAll("x", "k");
+ txt = txt.replaceAll("v", "f");
+ txt = txt.replaceAll("dg", "2g");
+ txt = txt.replaceAll("tio", "sio");
+ txt = txt.replaceAll("tia", "sia");
+ txt = txt.replaceAll("d", "t");
+ txt = txt.replaceAll("ph", "fh");
+ txt = txt.replaceAll("b", "p");
+ txt = txt.replaceAll("sh", "s2");
+ txt = txt.replaceAll("z", "s");
+ txt = txt.replaceAll("^[aeiou]", "A");
+ // 3 is a temporary placeholder marking a vowel
+ txt = txt.replaceAll("[aeiou]", "3");
+ txt = txt.replaceAll("3gh3", "3kh3");
+ txt = txt.replaceAll("gh", "22");
+ txt = txt.replaceAll("g", "k");
+ txt = txt.replaceAll("s+", "S");
+ txt = txt.replaceAll("t+", "T");
+ txt = txt.replaceAll("p+", "P");
+ txt = txt.replaceAll("k+", "K");
+ txt = txt.replaceAll("f+", "F");
+ txt = txt.replaceAll("m+", "M");
+ txt = txt.replaceAll("n+", "N");
+ txt = txt.replaceAll("w3", "W3");
+ txt = txt.replaceAll("wy", "Wy"); // 1.0 only
+ txt = txt.replaceAll("wh3", "Wh3");
+ txt = txt.replaceAll("why", "Why"); // 1.0 only
+ txt = txt.replaceAll("w", "2");
+ txt = txt.replaceAll("^h", "A");
+ txt = txt.replaceAll("h", "2");
+ txt = txt.replaceAll("r3", "R3");
+ txt = txt.replaceAll("ry", "Ry"); // 1.0 only
+ txt = txt.replaceAll("r", "2");
+ txt = txt.replaceAll("l3", "L3");
+ txt = txt.replaceAll("ly", "Ly"); // 1.0 only
+ txt = txt.replaceAll("l", "2");
+ txt = txt.replaceAll("j", "y"); // 1.0 only
+ txt = txt.replaceAll("y3", "Y3"); // 1.0 only
+ txt = txt.replaceAll("y", "2"); // 1.0 only
+
+ // 5. Handle removals
+ txt = txt.replaceAll("2", "");
+ txt = txt.replaceAll("3", "");
+
+ // 6. put ten 1s on the end
+ txt = txt + SIX_1;
+
+ // 7. take the first six characters as the code
+ return txt.substring(0, SIX_1.length());
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone2.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone2.java
new file mode 100644
index 000000000..a05b560e7
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone2.java
@@ -0,0 +1,129 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.language;
+
+/**
+ * Encodes a string into a Caverphone 2.0 value.
+ *
+ * This is an algorithm created by the Caversham Project at the University of Otago. It implements the Caverphone 2.0
+ * algorithm:
+ *
+ * @author Apache Software Foundation
+ * @version $Id: Caverphone.java 1075947 2011-03-01 17:56:14Z ggregory $
+ * @see <a href="http://en.wikipedia.org/wiki/Caverphone">Wikipedia - Caverphone</a>
+ * @see <a href="http://caversham.otago.ac.nz/files/working/ctp150804.pdf">Caverphone 2.0 specification</a>
+ * @since 1.5
+ */
+public class Caverphone2 extends AbstractCaverphone {
+
+ private static final String TEN_1 = "1111111111";
+
+ /**
+ * Encodes the given String into a Caverphone 2.0 value.
+ *
+ * @param source
+ * String the source string
+ * @return A caverphone code for the given String
+ */
+ public String encode(String source) {
+ String txt = source;
+ if (txt == null || txt.length() == 0) {
+ return TEN_1;
+ }
+
+ // 1. Convert to lowercase
+ txt = txt.toLowerCase(java.util.Locale.ENGLISH);
+
+ // 2. Remove anything not A-Z
+ txt = txt.replaceAll("[^a-z]", "");
+
+ // 2.5. Remove final e
+ txt = txt.replaceAll("e$", ""); // 2.0 only
+
+ // 3. Handle various start options
+ txt = txt.replaceAll("^cough", "cou2f");
+ txt = txt.replaceAll("^rough", "rou2f");
+ txt = txt.replaceAll("^tough", "tou2f");
+ txt = txt.replaceAll("^enough", "enou2f"); // 2.0 only
+ txt = txt.replaceAll("^trough", "trou2f"); // 2.0 only - note the spec says ^enough here again, c+p error I assume
+ txt = txt.replaceAll("^gn", "2n");
+
+ // End
+ txt = txt.replaceAll("mb$", "m2");
+
+ // 4. Handle replacements
+ txt = txt.replaceAll("cq", "2q");
+ txt = txt.replaceAll("ci", "si");
+ txt = txt.replaceAll("ce", "se");
+ txt = txt.replaceAll("cy", "sy");
+ txt = txt.replaceAll("tch", "2ch");
+ txt = txt.replaceAll("c", "k");
+ txt = txt.replaceAll("q", "k");
+ txt = txt.replaceAll("x", "k");
+ txt = txt.replaceAll("v", "f");
+ txt = txt.replaceAll("dg", "2g");
+ txt = txt.replaceAll("tio", "sio");
+ txt = txt.replaceAll("tia", "sia");
+ txt = txt.replaceAll("d", "t");
+ txt = txt.replaceAll("ph", "fh");
+ txt = txt.replaceAll("b", "p");
+ txt = txt.replaceAll("sh", "s2");
+ txt = txt.replaceAll("z", "s");
+ txt = txt.replaceAll("^[aeiou]", "A");
+ txt = txt.replaceAll("[aeiou]", "3");
+ txt = txt.replaceAll("j", "y"); // 2.0 only
+ txt = txt.replaceAll("^y3", "Y3"); // 2.0 only
+ txt = txt.replaceAll("^y", "A"); // 2.0 only
+ txt = txt.replaceAll("y", "3"); // 2.0 only
+ txt = txt.replaceAll("3gh3", "3kh3");
+ txt = txt.replaceAll("gh", "22");
+ txt = txt.replaceAll("g", "k");
+ txt = txt.replaceAll("s+", "S");
+ txt = txt.replaceAll("t+", "T");
+ txt = txt.replaceAll("p+", "P");
+ txt = txt.replaceAll("k+", "K");
+ txt = txt.replaceAll("f+", "F");
+ txt = txt.replaceAll("m+", "M");
+ txt = txt.replaceAll("n+", "N");
+ txt = txt.replaceAll("w3", "W3");
+ txt = txt.replaceAll("wh3", "Wh3");
+ txt = txt.replaceAll("w$", "3"); // 2.0 only
+ txt = txt.replaceAll("w", "2");
+ txt = txt.replaceAll("^h", "A");
+ txt = txt.replaceAll("h", "2");
+ txt = txt.replaceAll("r3", "R3");
+ txt = txt.replaceAll("r$", "3"); // 2.0 only
+ txt = txt.replaceAll("r", "2");
+ txt = txt.replaceAll("l3", "L3");
+ txt = txt.replaceAll("l$", "3"); // 2.0 only
+ txt = txt.replaceAll("l", "2");
+
+ // 5. Handle removals
+ txt = txt.replaceAll("2", "");
+ txt = txt.replaceAll("3$", "A"); // 2.0 only
+ txt = txt.replaceAll("3", "");
+
+ // 6. put ten 1s on the end
+ txt = txt + TEN_1;
+
+ // 7. take the first ten characters as the code
+ return txt.substring(0, TEN_1.length());
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/ColognePhonetic.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/ColognePhonetic.java
new file mode 100644
index 000000000..ae6285790
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/ColognePhonetic.java
@@ -0,0 +1,417 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.language;
+
+import java.util.Locale;
+
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.StringEncoder;
+
+/**
+ * <p>
+ * Encodes a string into a Cologne Phonetic value.
+ * </p>
+ * <p>
+ * Implements the <a href="http://de.wikipedia.org/wiki/K%C3%B6lner_Phonetik">“Kölner Phonetic”</a> (Cologne Phonetic)
+ * algorithm issued by Hans Joachim Postel in 1969.
+ * </p>
+ *
+ * <p>
+ * The <i>Kölner Phonetik</i> is a phonetic algorithm which is optimized for the German language. It is related to the
+ * well-known soundex algorithm.
+ * </p>
+ *
+ * <h2>Algorithm</h2>
+ *
+ * <ul>
+ *
+ * <li>
+ * <h3>Step 1:</h3>
+ * After preprocessing (convertion to upper case, transcription of <a
+ * href="http://en.wikipedia.org/wiki/Germanic_umlaut">germanic umlauts</a>, removal of non alphabetical characters) the
+ * letters of the supplied text are replaced by their phonetic code according to the folowing table.
+ * <table border="1">
+ * <tbody>
+ * <tr>
+ * <th>Letter</th>
+ * <th>Context</th>
+ * <th align="center">Code</th>
+ * </tr>
+ * <tr>
+ * <td>A, E, I, J, O, U, Y</td>
+ * <td></td>
+ * <td align="center">0</td>
+ * </tr>
+ * <tr>
+ *
+ * <td>H</td>
+ * <td></td>
+ * <td align="center">-</td>
+ * </tr>
+ * <tr>
+ * <td>B</td>
+ * <td></td>
+ * <td rowspan="2" align="center">1</td>
+ * </tr>
+ * <tr>
+ * <td>P</td>
+ * <td>not before H</td>
+ *
+ * </tr>
+ * <tr>
+ * <td>D, T</td>
+ * <td>not before C, S, Z</td>
+ * <td align="center">2</td>
+ * </tr>
+ * <tr>
+ * <td>F, V, W</td>
+ * <td></td>
+ * <td rowspan="2" align="center">3</td>
+ * </tr>
+ * <tr>
+ *
+ * <td>P</td>
+ * <td>before H</td>
+ * </tr>
+ * <tr>
+ * <td>G, K, Q</td>
+ * <td></td>
+ * <td rowspan="3" align="center">4</td>
+ * </tr>
+ * <tr>
+ * <td rowspan="2">C</td>
+ * <td>at onset before A, H, K, L, O, Q, R, U, X</td>
+ *
+ * </tr>
+ * <tr>
+ * <td>before A, H, K, O, Q, U, X except after S, Z</td>
+ * </tr>
+ * <tr>
+ * <td>X</td>
+ * <td>not after C, K, Q</td>
+ * <td align="center">48</td>
+ * </tr>
+ * <tr>
+ * <td>L</td>
+ * <td></td>
+ *
+ * <td align="center">5</td>
+ * </tr>
+ * <tr>
+ * <td>M, N</td>
+ * <td></td>
+ * <td align="center">6</td>
+ * </tr>
+ * <tr>
+ * <td>R</td>
+ * <td></td>
+ * <td align="center">7</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>S, Z</td>
+ * <td></td>
+ * <td rowspan="6" align="center">8</td>
+ * </tr>
+ * <tr>
+ * <td rowspan="3">C</td>
+ * <td>after S, Z</td>
+ * </tr>
+ * <tr>
+ * <td>at onset except before A, H, K, L, O, Q, R, U, X</td>
+ * </tr>
+ *
+ * <tr>
+ * <td>not before A, H, K, O, Q, U, X</td>
+ * </tr>
+ * <tr>
+ * <td>D, T</td>
+ * <td>before C, S, Z</td>
+ * </tr>
+ * <tr>
+ * <td>X</td>
+ * <td>after C, K, Q</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ * <p>
+ * <small><i>(Source: <a href= "http://de.wikipedia.org/wiki/K%C3%B6lner_Phonetik#Buchstabencodes" >Wikipedia (de):
+ * Kölner Phonetik – Buchstabencodes</a>)</i></small>
+ * </p>
+ *
+ * <h4>Example:</h4>
+ *
+ * {@code "Müller-Lüdenscheidt" => "MULLERLUDENSCHEIDT" => "6005507500206880022"}
+ *
+ * </li>
+ *
+ * <li>
+ * <h3>Step 2:</h3>
+ * Collapse of all multiple consecutive code digits.
+ * <h4>Example:</h4>
+ * {@code "6005507500206880022" => "6050750206802"}</li>
+ *
+ * <li>
+ * <h3>Step 3:</h3>
+ * Removal of all codes “0” except at the beginning. This means that two or more identical consecutive digits can occur
+ * if they occur after removing the "0" digits.
+ *
+ * <h4>Example:</h4>
+ * {@code "6050750206802" => "65752682"}</li>
+ *
+ * </ul>
+ *
+ * @see <a href="http://de.wikipedia.org/wiki/K%C3%B6lner_Phonetik">Wikipedia (de): Kölner Phonetik (in German)</a>
+ * @author Apache Software Foundation
+ * @since 1.5
+ */
+public class ColognePhonetic implements StringEncoder {
+
+ private abstract class CologneBuffer {
+
+ protected final char[] data;
+
+ protected int length = 0;
+
+ public CologneBuffer(char[] data) {
+ this.data = data;
+ this.length = data.length;
+ }
+
+ public CologneBuffer(int buffSize) {
+ this.data = new char[buffSize];
+ this.length = 0;
+ }
+
+ protected abstract char[] copyData(int start, final int length);
+
+ public int length() {
+ return length;
+ }
+
+ public String toString() {
+ return new String(copyData(0, length));
+ }
+ }
+
+ private class CologneOutputBuffer extends CologneBuffer {
+
+ public CologneOutputBuffer(int buffSize) {
+ super(buffSize);
+ }
+
+ public void addRight(char chr) {
+ data[length] = chr;
+ length++;
+ }
+
+ protected char[] copyData(int start, final int length) {
+ char[] newData = new char[length];
+ System.arraycopy(data, start, newData, 0, length);
+ return newData;
+ }
+ }
+
+ private class CologneInputBuffer extends CologneBuffer {
+
+ public CologneInputBuffer(char[] data) {
+ super(data);
+ }
+
+ public void addLeft(char ch) {
+ length++;
+ data[getNextPos()] = ch;
+ }
+
+ protected char[] copyData(int start, final int length) {
+ char[] newData = new char[length];
+ System.arraycopy(data, data.length - this.length + start, newData, 0, length);
+ return newData;
+ }
+
+ public char getNextChar() {
+ return data[getNextPos()];
+ }
+
+ protected int getNextPos() {
+ return data.length - length;
+ }
+
+ public char removeNext() {
+ char ch = getNextChar();
+ length--;
+ return ch;
+ }
+ }
+
+ private static final char[][] PREPROCESS_MAP = new char[][]{{'\u00C4', 'A'}, // Ä
+ {'\u00DC', 'U'}, // Ü
+ {'\u00D6', 'O'}, // Ö
+ {'\u00DF', 'S'} // ß
+ };
+
+ /*
+ * Returns whether the array contains the key, or not.
+ */
+ private static boolean arrayContains(char[] arr, char key) {
+ for (int i = 0; i < arr.length; i++) {
+ if (arr[i] == key) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * <p>
+ * <b>colognePhonetic()</b> is the actual implementations of the <i>Kölner Phonetik</i> algorithm.
+ * </p>
+ * <p>
+ * In contrast to the initial description of the algorithm, this implementation does the encoding in one pass.
+ * </p>
+ *
+ * @param text
+ * @return the corresponding encoding according to the <i>Kölner Phonetik</i> algorithm
+ */
+ public String colognePhonetic(String text) {
+ if (text == null) {
+ return null;
+ }
+
+ text = preprocess(text);
+
+ CologneOutputBuffer output = new CologneOutputBuffer(text.length() * 2);
+ CologneInputBuffer input = new CologneInputBuffer(text.toCharArray());
+
+ char nextChar;
+
+ char lastChar = '-';
+ char lastCode = '/';
+ char code;
+ char chr;
+
+ int rightLength = input.length();
+
+ while (rightLength > 0) {
+ chr = input.removeNext();
+
+ if ((rightLength = input.length()) > 0) {
+ nextChar = input.getNextChar();
+ } else {
+ nextChar = '-';
+ }
+
+ if (arrayContains(new char[]{'A', 'E', 'I', 'J', 'O', 'U', 'Y'}, chr)) {
+ code = '0';
+ } else if (chr == 'H' || chr < 'A' || chr > 'Z') {
+ if (lastCode == '/') {
+ continue;
+ }
+ code = '-';
+ } else if (chr == 'B' || (chr == 'P' && nextChar != 'H')) {
+ code = '1';
+ } else if ((chr == 'D' || chr == 'T') && !arrayContains(new char[]{'S', 'C', 'Z'}, nextChar)) {
+ code = '2';
+ } else if (arrayContains(new char[]{'W', 'F', 'P', 'V'}, chr)) {
+ code = '3';
+ } else if (arrayContains(new char[]{'G', 'K', 'Q'}, chr)) {
+ code = '4';
+ } else if (chr == 'X' && !arrayContains(new char[]{'C', 'K', 'Q'}, lastChar)) {
+ code = '4';
+ input.addLeft('S');
+ rightLength++;
+ } else if (chr == 'S' || chr == 'Z') {
+ code = '8';
+ } else if (chr == 'C') {
+ if (lastCode == '/') {
+ if (arrayContains(new char[]{'A', 'H', 'K', 'L', 'O', 'Q', 'R', 'U', 'X'}, nextChar)) {
+ code = '4';
+ } else {
+ code = '8';
+ }
+ } else {
+ if (arrayContains(new char[]{'S', 'Z'}, lastChar) ||
+ !arrayContains(new char[]{'A', 'H', 'O', 'U', 'K', 'Q', 'X'}, nextChar)) {
+ code = '8';
+ } else {
+ code = '4';
+ }
+ }
+ } else if (arrayContains(new char[]{'T', 'D', 'X'}, chr)) {
+ code = '8';
+ } else if (chr == 'R') {
+ code = '7';
+ } else if (chr == 'L') {
+ code = '5';
+ } else if (chr == 'M' || chr == 'N') {
+ code = '6';
+ } else {
+ code = chr;
+ }
+
+ if (code != '-' && (lastCode != code && (code != '0' || lastCode == '/') || code < '0' || code > '8')) {
+ output.addRight(code);
+ }
+
+ lastChar = chr;
+ lastCode = code;
+ }
+ return output.toString();
+ }
+
+ public Object encode(Object object) throws EncoderException {
+ if (!(object instanceof String)) {
+ throw new EncoderException("This method’s parameter was expected to be of the type " +
+ String.class.getName() +
+ ". But actually it was of the type " +
+ object.getClass().getName() +
+ ".");
+ }
+ return encode((String) object);
+ }
+
+ public String encode(String text) {
+ return colognePhonetic(text);
+ }
+
+ public boolean isEncodeEqual(String text1, String text2) {
+ return colognePhonetic(text1).equals(colognePhonetic(text2));
+ }
+
+ /*
+ * Converts the string to upper case and replaces germanic umlauts, and the “ß”.
+ */
+ private String preprocess(String text) {
+ text = text.toUpperCase(Locale.GERMAN);
+
+ char[] chrs = text.toCharArray();
+
+ for (int index = 0; index < chrs.length; index++) {
+ if (chrs[index] > 'Z') {
+ for (int replacement = 0; replacement < PREPROCESS_MAP.length; replacement++) {
+ if (chrs[index] == PREPROCESS_MAP[replacement][0]) {
+ chrs[index] = PREPROCESS_MAP[replacement][1];
+ break;
+ }
+ }
+ }
+ }
+ return new String(chrs);
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/DoubleMetaphone.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/DoubleMetaphone.java
new file mode 100644
index 000000000..5069ade72
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/DoubleMetaphone.java
@@ -0,0 +1,1106 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.language;
+
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.StringEncoder;
+
+/**
+ * Encodes a string into a double metaphone value.
+ * This Implementation is based on the algorithm by <CITE>Lawrence Philips</CITE>.
+ * <ul>
+ * <li>Original Article: <a
+ * href="http://www.cuj.com/documents/s=8038/cuj0006philips/">
+ * http://www.cuj.com/documents/s=8038/cuj0006philips/</a></li>
+ * <li>Original Source Code: <a href="ftp://ftp.cuj.com/pub/2000/1806/philips.zip">
+ * ftp://ftp.cuj.com/pub/2000/1806/philips.zip</a></li>
+ * </ul>
+ *
+ * @author Apache Software Foundation
+ * @version $Id: DoubleMetaphone.java 1072742 2011-02-20 21:39:03Z ggregory $
+ */
+public class DoubleMetaphone implements StringEncoder {
+
+ /**
+ * "Vowels" to test for
+ */
+ private static final String VOWELS = "AEIOUY";
+
+ /**
+ * Prefixes when present which are not pronounced
+ */
+ private static final String[] SILENT_START =
+ { "GN", "KN", "PN", "WR", "PS" };
+ private static final String[] L_R_N_M_B_H_F_V_W_SPACE =
+ { "L", "R", "N", "M", "B", "H", "F", "V", "W", " " };
+ private static final String[] ES_EP_EB_EL_EY_IB_IL_IN_IE_EI_ER =
+ { "ES", "EP", "EB", "EL", "EY", "IB", "IL", "IN", "IE", "EI", "ER" };
+ private static final String[] L_T_K_S_N_M_B_Z =
+ { "L", "T", "K", "S", "N", "M", "B", "Z" };
+
+ /**
+ * Maximum length of an encoding, default is 4
+ */
+ private int maxCodeLen = 4;
+
+ /**
+ * Creates an instance of this DoubleMetaphone encoder
+ */
+ public DoubleMetaphone() {
+ super();
+ }
+
+ /**
+ * Encode a value with Double Metaphone
+ *
+ * @param value String to encode
+ * @return an encoded string
+ */
+ public String doubleMetaphone(String value) {
+ return doubleMetaphone(value, false);
+ }
+
+ /**
+ * Encode a value with Double Metaphone, optionally using the alternate
+ * encoding.
+ *
+ * @param value String to encode
+ * @param alternate use alternate encode
+ * @return an encoded string
+ */
+ public String doubleMetaphone(String value, boolean alternate) {
+ value = cleanInput(value);
+ if (value == null) {
+ return null;
+ }
+
+ boolean slavoGermanic = isSlavoGermanic(value);
+ int index = isSilentStart(value) ? 1 : 0;
+
+ DoubleMetaphoneResult result = new DoubleMetaphoneResult(this.getMaxCodeLen());
+
+ while (!result.isComplete() && index <= value.length() - 1) {
+ switch (value.charAt(index)) {
+ case 'A':
+ case 'E':
+ case 'I':
+ case 'O':
+ case 'U':
+ case 'Y':
+ index = handleAEIOUY(result, index);
+ break;
+ case 'B':
+ result.append('P');
+ index = charAt(value, index + 1) == 'B' ? index + 2 : index + 1;
+ break;
+ case '\u00C7':
+ // A C with a Cedilla
+ result.append('S');
+ index++;
+ break;
+ case 'C':
+ index = handleC(value, result, index);
+ break;
+ case 'D':
+ index = handleD(value, result, index);
+ break;
+ case 'F':
+ result.append('F');
+ index = charAt(value, index + 1) == 'F' ? index + 2 : index + 1;
+ break;
+ case 'G':
+ index = handleG(value, result, index, slavoGermanic);
+ break;
+ case 'H':
+ index = handleH(value, result, index);
+ break;
+ case 'J':
+ index = handleJ(value, result, index, slavoGermanic);
+ break;
+ case 'K':
+ result.append('K');
+ index = charAt(value, index + 1) == 'K' ? index + 2 : index + 1;
+ break;
+ case 'L':
+ index = handleL(value, result, index);
+ break;
+ case 'M':
+ result.append('M');
+ index = conditionM0(value, index) ? index + 2 : index + 1;
+ break;
+ case 'N':
+ result.append('N');
+ index = charAt(value, index + 1) == 'N' ? index + 2 : index + 1;
+ break;
+ case '\u00D1':
+ // N with a tilde (spanish ene)
+ result.append('N');
+ index++;
+ break;
+ case 'P':
+ index = handleP(value, result, index);
+ break;
+ case 'Q':
+ result.append('K');
+ index = charAt(value, index + 1) == 'Q' ? index + 2 : index + 1;
+ break;
+ case 'R':
+ index = handleR(value, result, index, slavoGermanic);
+ break;
+ case 'S':
+ index = handleS(value, result, index, slavoGermanic);
+ break;
+ case 'T':
+ index = handleT(value, result, index);
+ break;
+ case 'V':
+ result.append('F');
+ index = charAt(value, index + 1) == 'V' ? index + 2 : index + 1;
+ break;
+ case 'W':
+ index = handleW(value, result, index);
+ break;
+ case 'X':
+ index = handleX(value, result, index);
+ break;
+ case 'Z':
+ index = handleZ(value, result, index, slavoGermanic);
+ break;
+ default:
+ index++;
+ break;
+ }
+ }
+
+ return alternate ? result.getAlternate() : result.getPrimary();
+ }
+
+ /**
+ * Encode the value using DoubleMetaphone. It will only work if
+ * <code>obj</code> is a <code>String</code> (like <code>Metaphone</code>).
+ *
+ * @param obj Object to encode (should be of type String)
+ * @return An encoded Object (will be of type String)
+ * @throws EncoderException encode parameter is not of type String
+ */
+ public Object encode(Object obj) throws EncoderException {
+ if (!(obj instanceof String)) {
+ throw new EncoderException("DoubleMetaphone encode parameter is not of type String");
+ }
+ return doubleMetaphone((String) obj);
+ }
+
+ /**
+ * Encode the value using DoubleMetaphone.
+ *
+ * @param value String to encode
+ * @return An encoded String
+ */
+ public String encode(String value) {
+ return doubleMetaphone(value);
+ }
+
+ /**
+ * Check if the Double Metaphone values of two <code>String</code> values
+ * are equal.
+ *
+ * @param value1 The left-hand side of the encoded {@link String#equals(Object)}.
+ * @param value2 The right-hand side of the encoded {@link String#equals(Object)}.
+ * @return <code>true</code> if the encoded <code>String</code>s are equal;
+ * <code>false</code> otherwise.
+ * @see #isDoubleMetaphoneEqual(String,String,boolean)
+ */
+ public boolean isDoubleMetaphoneEqual(String value1, String value2) {
+ return isDoubleMetaphoneEqual(value1, value2, false);
+ }
+
+ /**
+ * Check if the Double Metaphone values of two <code>String</code> values
+ * are equal, optionally using the alternate value.
+ *
+ * @param value1 The left-hand side of the encoded {@link String#equals(Object)}.
+ * @param value2 The right-hand side of the encoded {@link String#equals(Object)}.
+ * @param alternate use the alternate value if <code>true</code>.
+ * @return <code>true</code> if the encoded <code>String</code>s are equal;
+ * <code>false</code> otherwise.
+ */
+ public boolean isDoubleMetaphoneEqual(String value1,
+ String value2,
+ boolean alternate) {
+ return doubleMetaphone(value1, alternate).equals(doubleMetaphone
+ (value2, alternate));
+ }
+
+ /**
+ * Returns the maxCodeLen.
+ * @return int
+ */
+ public int getMaxCodeLen() {
+ return this.maxCodeLen;
+ }
+
+ /**
+ * Sets the maxCodeLen.
+ * @param maxCodeLen The maxCodeLen to set
+ */
+ public void setMaxCodeLen(int maxCodeLen) {
+ this.maxCodeLen = maxCodeLen;
+ }
+
+ //-- BEGIN HANDLERS --//
+
+ /**
+ * Handles 'A', 'E', 'I', 'O', 'U', and 'Y' cases
+ */
+ private int handleAEIOUY(DoubleMetaphoneResult result, int
+ index) {
+ if (index == 0) {
+ result.append('A');
+ }
+ return index + 1;
+ }
+
+ /**
+ * Handles 'C' cases
+ */
+ private int handleC(String value,
+ DoubleMetaphoneResult result,
+ int index) {
+ if (conditionC0(value, index)) { // very confusing, moved out
+ result.append('K');
+ index += 2;
+ } else if (index == 0 && contains(value, index, 6, "CAESAR")) {
+ result.append('S');
+ index += 2;
+ } else if (contains(value, index, 2, "CH")) {
+ index = handleCH(value, result, index);
+ } else if (contains(value, index, 2, "CZ") &&
+ !contains(value, index - 2, 4, "WICZ")) {
+ //-- "Czerny" --//
+ result.append('S', 'X');
+ index += 2;
+ } else if (contains(value, index + 1, 3, "CIA")) {
+ //-- "focaccia" --//
+ result.append('X');
+ index += 3;
+ } else if (contains(value, index, 2, "CC") &&
+ !(index == 1 && charAt(value, 0) == 'M')) {
+ //-- double "cc" but not "McClelland" --//
+ return handleCC(value, result, index);
+ } else if (contains(value, index, 2, "CK", "CG", "CQ")) {
+ result.append('K');
+ index += 2;
+ } else if (contains(value, index, 2, "CI", "CE", "CY")) {
+ //-- Italian vs. English --//
+ if (contains(value, index, 3, "CIO", "CIE", "CIA")) {
+ result.append('S', 'X');
+ } else {
+ result.append('S');
+ }
+ index += 2;
+ } else {
+ result.append('K');
+ if (contains(value, index + 1, 2, " C", " Q", " G")) {
+ //-- Mac Caffrey, Mac Gregor --//
+ index += 3;
+ } else if (contains(value, index + 1, 1, "C", "K", "Q") &&
+ !contains(value, index + 1, 2, "CE", "CI")) {
+ index += 2;
+ } else {
+ index++;
+ }
+ }
+
+ return index;
+ }
+
+ /**
+ * Handles 'CC' cases
+ */
+ private int handleCC(String value,
+ DoubleMetaphoneResult result,
+ int index) {
+ if (contains(value, index + 2, 1, "I", "E", "H") &&
+ !contains(value, index + 2, 2, "HU")) {
+ //-- "bellocchio" but not "bacchus" --//
+ if ((index == 1 && charAt(value, index - 1) == 'A') ||
+ contains(value, index - 1, 5, "UCCEE", "UCCES")) {
+ //-- "accident", "accede", "succeed" --//
+ result.append("KS");
+ } else {
+ //-- "bacci", "bertucci", other Italian --//
+ result.append('X');
+ }
+ index += 3;
+ } else { // Pierce's rule
+ result.append('K');
+ index += 2;
+ }
+
+ return index;
+ }
+
+ /**
+ * Handles 'CH' cases
+ */
+ private int handleCH(String value,
+ DoubleMetaphoneResult result,
+ int index) {
+ if (index > 0 && contains(value, index, 4, "CHAE")) { // Michael
+ result.append('K', 'X');
+ return index + 2;
+ } else if (conditionCH0(value, index)) {
+ //-- Greek roots ("chemistry", "chorus", etc.) --//
+ result.append('K');
+ return index + 2;
+ } else if (conditionCH1(value, index)) {
+ //-- Germanic, Greek, or otherwise 'ch' for 'kh' sound --//
+ result.append('K');
+ return index + 2;
+ } else {
+ if (index > 0) {
+ if (contains(value, 0, 2, "MC")) {
+ result.append('K');
+ } else {
+ result.append('X', 'K');
+ }
+ } else {
+ result.append('X');
+ }
+ return index + 2;
+ }
+ }
+
+ /**
+ * Handles 'D' cases
+ */
+ private int handleD(String value,
+ DoubleMetaphoneResult result,
+ int index) {
+ if (contains(value, index, 2, "DG")) {
+ //-- "Edge" --//
+ if (contains(value, index + 2, 1, "I", "E", "Y")) {
+ result.append('J');
+ index += 3;
+ //-- "Edgar" --//
+ } else {
+ result.append("TK");
+ index += 2;
+ }
+ } else if (contains(value, index, 2, "DT", "DD")) {
+ result.append('T');
+ index += 2;
+ } else {
+ result.append('T');
+ index++;
+ }
+ return index;
+ }
+
+ /**
+ * Handles 'G' cases
+ */
+ private int handleG(String value,
+ DoubleMetaphoneResult result,
+ int index,
+ boolean slavoGermanic) {
+ if (charAt(value, index + 1) == 'H') {
+ index = handleGH(value, result, index);
+ } else if (charAt(value, index + 1) == 'N') {
+ if (index == 1 && isVowel(charAt(value, 0)) && !slavoGermanic) {
+ result.append("KN", "N");
+ } else if (!contains(value, index + 2, 2, "EY") &&
+ charAt(value, index + 1) != 'Y' && !slavoGermanic) {
+ result.append("N", "KN");
+ } else {
+ result.append("KN");
+ }
+ index = index + 2;
+ } else if (contains(value, index + 1, 2, "LI") && !slavoGermanic) {
+ result.append("KL", "L");
+ index += 2;
+ } else if (index == 0 && (charAt(value, index + 1) == 'Y' || contains(value, index + 1, 2, ES_EP_EB_EL_EY_IB_IL_IN_IE_EI_ER))) {
+ //-- -ges-, -gep-, -gel-, -gie- at beginning --//
+ result.append('K', 'J');
+ index += 2;
+ } else if ((contains(value, index + 1, 2, "ER") ||
+ charAt(value, index + 1) == 'Y') &&
+ !contains(value, 0, 6, "DANGER", "RANGER", "MANGER") &&
+ !contains(value, index - 1, 1, "E", "I") &&
+ !contains(value, index - 1, 3, "RGY", "OGY")) {
+ //-- -ger-, -gy- --//
+ result.append('K', 'J');
+ index += 2;
+ } else if (contains(value, index + 1, 1, "E", "I", "Y") ||
+ contains(value, index - 1, 4, "AGGI", "OGGI")) {
+ //-- Italian "biaggi" --//
+ if ((contains(value, 0 ,4, "VAN ", "VON ") || contains(value, 0, 3, "SCH")) || contains(value, index + 1, 2, "ET")) {
+ //-- obvious germanic --//
+ result.append('K');
+ } else if (contains(value, index + 1, 3, "IER")) {
+ result.append('J');
+ } else {
+ result.append('J', 'K');
+ }
+ index += 2;
+ } else if (charAt(value, index + 1) == 'G') {
+ index += 2;
+ result.append('K');
+ } else {
+ index++;
+ result.append('K');
+ }
+ return index;
+ }
+
+ /**
+ * Handles 'GH' cases
+ */
+ private int handleGH(String value,
+ DoubleMetaphoneResult result,
+ int index) {
+ if (index > 0 && !isVowel(charAt(value, index - 1))) {
+ result.append('K');
+ index += 2;
+ } else if (index == 0) {
+ if (charAt(value, index + 2) == 'I') {
+ result.append('J');
+ } else {
+ result.append('K');
+ }
+ index += 2;
+ } else if ((index > 1 && contains(value, index - 2, 1, "B", "H", "D")) ||
+ (index > 2 && contains(value, index - 3, 1, "B", "H", "D")) ||
+ (index > 3 && contains(value, index - 4, 1, "B", "H"))) {
+ //-- Parker's rule (with some further refinements) - "hugh"
+ index += 2;
+ } else {
+ if (index > 2 && charAt(value, index - 1) == 'U' &&
+ contains(value, index - 3, 1, "C", "G", "L", "R", "T")) {
+ //-- "laugh", "McLaughlin", "cough", "gough", "rough", "tough"
+ result.append('F');
+ } else if (index > 0 && charAt(value, index - 1) != 'I') {
+ result.append('K');
+ }
+ index += 2;
+ }
+ return index;
+ }
+
+ /**
+ * Handles 'H' cases
+ */
+ private int handleH(String value,
+ DoubleMetaphoneResult result,
+ int index) {
+ //-- only keep if first & before vowel or between 2 vowels --//
+ if ((index == 0 || isVowel(charAt(value, index - 1))) &&
+ isVowel(charAt(value, index + 1))) {
+ result.append('H');
+ index += 2;
+ //-- also takes car of "HH" --//
+ } else {
+ index++;
+ }
+ return index;
+ }
+
+ /**
+ * Handles 'J' cases
+ */
+ private int handleJ(String value, DoubleMetaphoneResult result, int index,
+ boolean slavoGermanic) {
+ if (contains(value, index, 4, "JOSE") || contains(value, 0, 4, "SAN ")) {
+ //-- obvious Spanish, "Jose", "San Jacinto" --//
+ if ((index == 0 && (charAt(value, index + 4) == ' ') ||
+ value.length() == 4) || contains(value, 0, 4, "SAN ")) {
+ result.append('H');
+ } else {
+ result.append('J', 'H');
+ }
+ index++;
+ } else {
+ if (index == 0 && !contains(value, index, 4, "JOSE")) {
+ result.append('J', 'A');
+ } else if (isVowel(charAt(value, index - 1)) && !slavoGermanic &&
+ (charAt(value, index + 1) == 'A' || charAt(value, index + 1) == 'O')) {
+ result.append('J', 'H');
+ } else if (index == value.length() - 1) {
+ result.append('J', ' ');
+ } else if (!contains(value, index + 1, 1, L_T_K_S_N_M_B_Z) && !contains(value, index - 1, 1, "S", "K", "L")) {
+ result.append('J');
+ }
+
+ if (charAt(value, index + 1) == 'J') {
+ index += 2;
+ } else {
+ index++;
+ }
+ }
+ return index;
+ }
+
+ /**
+ * Handles 'L' cases
+ */
+ private int handleL(String value,
+ DoubleMetaphoneResult result,
+ int index) {
+ if (charAt(value, index + 1) == 'L') {
+ if (conditionL0(value, index)) {
+ result.appendPrimary('L');
+ } else {
+ result.append('L');
+ }
+ index += 2;
+ } else {
+ index++;
+ result.append('L');
+ }
+ return index;
+ }
+
+ /**
+ * Handles 'P' cases
+ */
+ private int handleP(String value,
+ DoubleMetaphoneResult result,
+ int index) {
+ if (charAt(value, index + 1) == 'H') {
+ result.append('F');
+ index += 2;
+ } else {
+ result.append('P');
+ index = contains(value, index + 1, 1, "P", "B") ? index + 2 : index + 1;
+ }
+ return index;
+ }
+
+ /**
+ * Handles 'R' cases
+ */
+ private int handleR(String value,
+ DoubleMetaphoneResult result,
+ int index,
+ boolean slavoGermanic) {
+ if (index == value.length() - 1 && !slavoGermanic &&
+ contains(value, index - 2, 2, "IE") &&
+ !contains(value, index - 4, 2, "ME", "MA")) {
+ result.appendAlternate('R');
+ } else {
+ result.append('R');
+ }
+ return charAt(value, index + 1) == 'R' ? index + 2 : index + 1;
+ }
+
+ /**
+ * Handles 'S' cases
+ */
+ private int handleS(String value,
+ DoubleMetaphoneResult result,
+ int index,
+ boolean slavoGermanic) {
+ if (contains(value, index - 1, 3, "ISL", "YSL")) {
+ //-- special cases "island", "isle", "carlisle", "carlysle" --//
+ index++;
+ } else if (index == 0 && contains(value, index, 5, "SUGAR")) {
+ //-- special case "sugar-" --//
+ result.append('X', 'S');
+ index++;
+ } else if (contains(value, index, 2, "SH")) {
+ if (contains(value, index + 1, 4,
+ "HEIM", "HOEK", "HOLM", "HOLZ")) {
+ //-- germanic --//
+ result.append('S');
+ } else {
+ result.append('X');
+ }
+ index += 2;
+ } else if (contains(value, index, 3, "SIO", "SIA") || contains(value, index, 4, "SIAN")) {
+ //-- Italian and Armenian --//
+ if (slavoGermanic) {
+ result.append('S');
+ } else {
+ result.append('S', 'X');
+ }
+ index += 3;
+ } else if ((index == 0 && contains(value, index + 1, 1, "M", "N", "L", "W")) || contains(value, index + 1, 1, "Z")) {
+ //-- german & anglicisations, e.g. "smith" match "schmidt" //
+ // "snider" match "schneider" --//
+ //-- also, -sz- in slavic language altho in hungarian it //
+ // is pronounced "s" --//
+ result.append('S', 'X');
+ index = contains(value, index + 1, 1, "Z") ? index + 2 : index + 1;
+ } else if (contains(value, index, 2, "SC")) {
+ index = handleSC(value, result, index);
+ } else {
+ if (index == value.length() - 1 && contains(value, index - 2,
+ 2, "AI", "OI")){
+ //-- french e.g. "resnais", "artois" --//
+ result.appendAlternate('S');
+ } else {
+ result.append('S');
+ }
+ index = contains(value, index + 1, 1, "S", "Z") ? index + 2 : index + 1;
+ }
+ return index;
+ }
+
+ /**
+ * Handles 'SC' cases
+ */
+ private int handleSC(String value,
+ DoubleMetaphoneResult result,
+ int index) {
+ if (charAt(value, index + 2) == 'H') {
+ //-- Schlesinger's rule --//
+ if (contains(value, index + 3,
+ 2, "OO", "ER", "EN", "UY", "ED", "EM")) {
+ //-- Dutch origin, e.g. "school", "schooner" --//
+ if (contains(value, index + 3, 2, "ER", "EN")) {
+ //-- "schermerhorn", "schenker" --//
+ result.append("X", "SK");
+ } else {
+ result.append("SK");
+ }
+ } else {
+ if (index == 0 && !isVowel(charAt(value, 3)) && charAt(value, 3) != 'W') {
+ result.append('X', 'S');
+ } else {
+ result.append('X');
+ }
+ }
+ } else if (contains(value, index + 2, 1, "I", "E", "Y")) {
+ result.append('S');
+ } else {
+ result.append("SK");
+ }
+ return index + 3;
+ }
+
+ /**
+ * Handles 'T' cases
+ */
+ private int handleT(String value,
+ DoubleMetaphoneResult result,
+ int index) {
+ if (contains(value, index, 4, "TION")) {
+ result.append('X');
+ index += 3;
+ } else if (contains(value, index, 3, "TIA", "TCH")) {
+ result.append('X');
+ index += 3;
+ } else if (contains(value, index, 2, "TH") || contains(value, index,
+ 3, "TTH")) {
+ if (contains(value, index + 2, 2, "OM", "AM") ||
+ //-- special case "thomas", "thames" or germanic --//
+ contains(value, 0, 4, "VAN ", "VON ") ||
+ contains(value, 0, 3, "SCH")) {
+ result.append('T');
+ } else {
+ result.append('0', 'T');
+ }
+ index += 2;
+ } else {
+ result.append('T');
+ index = contains(value, index + 1, 1, "T", "D") ? index + 2 : index + 1;
+ }
+ return index;
+ }
+
+ /**
+ * Handles 'W' cases
+ */
+ private int handleW(String value,
+ DoubleMetaphoneResult result,
+ int index) {
+ if (contains(value, index, 2, "WR")) {
+ //-- can also be in middle of word --//
+ result.append('R');
+ index += 2;
+ } else {
+ if (index == 0 && (isVowel(charAt(value, index + 1)) ||
+ contains(value, index, 2, "WH"))) {
+ if (isVowel(charAt(value, index + 1))) {
+ //-- Wasserman should match Vasserman --//
+ result.append('A', 'F');
+ } else {
+ //-- need Uomo to match Womo --//
+ result.append('A');
+ }
+ index++;
+ } else if ((index == value.length() - 1 && isVowel(charAt(value, index - 1))) ||
+ contains(value, index - 1,
+ 5, "EWSKI", "EWSKY", "OWSKI", "OWSKY") ||
+ contains(value, 0, 3, "SCH")) {
+ //-- Arnow should match Arnoff --//
+ result.appendAlternate('F');
+ index++;
+ } else if (contains(value, index, 4, "WICZ", "WITZ")) {
+ //-- Polish e.g. "filipowicz" --//
+ result.append("TS", "FX");
+ index += 4;
+ } else {
+ index++;
+ }
+ }
+ return index;
+ }
+
+ /**
+ * Handles 'X' cases
+ */
+ private int handleX(String value,
+ DoubleMetaphoneResult result,
+ int index) {
+ if (index == 0) {
+ result.append('S');
+ index++;
+ } else {
+ if (!((index == value.length() - 1) &&
+ (contains(value, index - 3, 3, "IAU", "EAU") ||
+ contains(value, index - 2, 2, "AU", "OU")))) {
+ //-- French e.g. breaux --//
+ result.append("KS");
+ }
+ index = contains(value, index + 1, 1, "C", "X") ? index + 2 : index + 1;
+ }
+ return index;
+ }
+
+ /**
+ * Handles 'Z' cases
+ */
+ private int handleZ(String value, DoubleMetaphoneResult result, int index,
+ boolean slavoGermanic) {
+ if (charAt(value, index + 1) == 'H') {
+ //-- Chinese pinyin e.g. "zhao" or Angelina "Zhang" --//
+ result.append('J');
+ index += 2;
+ } else {
+ if (contains(value, index + 1, 2, "ZO", "ZI", "ZA") || (slavoGermanic && (index > 0 && charAt(value, index - 1) != 'T'))) {
+ result.append("S", "TS");
+ } else {
+ result.append('S');
+ }
+ index = charAt(value, index + 1) == 'Z' ? index + 2 : index + 1;
+ }
+ return index;
+ }
+
+ //-- BEGIN CONDITIONS --//
+
+ /**
+ * Complex condition 0 for 'C'
+ */
+ private boolean conditionC0(String value, int index) {
+ if (contains(value, index, 4, "CHIA")) {
+ return true;
+ } else if (index <= 1) {
+ return false;
+ } else if (isVowel(charAt(value, index - 2))) {
+ return false;
+ } else if (!contains(value, index - 1, 3, "ACH")) {
+ return false;
+ } else {
+ char c = charAt(value, index + 2);
+ return (c != 'I' && c != 'E') ||
+ contains(value, index - 2, 6, "BACHER", "MACHER");
+ }
+ }
+
+ /**
+ * Complex condition 0 for 'CH'
+ */
+ private boolean conditionCH0(String value, int index) {
+ if (index != 0) {
+ return false;
+ } else if (!contains(value, index + 1, 5, "HARAC", "HARIS") &&
+ !contains(value, index + 1, 3, "HOR", "HYM", "HIA", "HEM")) {
+ return false;
+ } else if (contains(value, 0, 5, "CHORE")) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * Complex condition 1 for 'CH'
+ */
+ private boolean conditionCH1(String value, int index) {
+ return ((contains(value, 0, 4, "VAN ", "VON ") || contains(value, 0,
+ 3, "SCH")) ||
+ contains(value, index - 2, 6, "ORCHES", "ARCHIT", "ORCHID") ||
+ contains(value, index + 2, 1, "T", "S") ||
+ ((contains(value, index - 1, 1, "A", "O", "U", "E") || index == 0) &&
+ (contains(value, index + 2, 1, L_R_N_M_B_H_F_V_W_SPACE) || index + 1 == value.length() - 1)));
+ }
+
+ /**
+ * Complex condition 0 for 'L'
+ */
+ private boolean conditionL0(String value, int index) {
+ if (index == value.length() - 3 &&
+ contains(value, index - 1, 4, "ILLO", "ILLA", "ALLE")) {
+ return true;
+ } else if ((contains(value, value.length() - 2, 2, "AS", "OS") ||
+ contains(value, value.length() - 1, 1, "A", "O")) &&
+ contains(value, index - 1, 4, "ALLE")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Complex condition 0 for 'M'
+ */
+ private boolean conditionM0(String value, int index) {
+ if (charAt(value, index + 1) == 'M') {
+ return true;
+ }
+ return contains(value, index - 1, 3, "UMB") &&
+ ((index + 1) == value.length() - 1 || contains(value,
+ index + 2, 2, "ER"));
+ }
+
+ //-- BEGIN HELPER FUNCTIONS --//
+
+ /**
+ * Determines whether or not a value is of slavo-germanic orgin. A value is
+ * of slavo-germanic origin if it contians any of 'W', 'K', 'CZ', or 'WITZ'.
+ */
+ private boolean isSlavoGermanic(String value) {
+ return value.indexOf('W') > -1 || value.indexOf('K') > -1 ||
+ value.indexOf("CZ") > -1 || value.indexOf("WITZ") > -1;
+ }
+
+ /**
+ * Determines whether or not a character is a vowel or not
+ */
+ private boolean isVowel(char ch) {
+ return VOWELS.indexOf(ch) != -1;
+ }
+
+ /**
+ * Determines whether or not the value starts with a silent letter. It will
+ * return <code>true</code> if the value starts with any of 'GN', 'KN',
+ * 'PN', 'WR' or 'PS'.
+ */
+ private boolean isSilentStart(String value) {
+ boolean result = false;
+ for (int i = 0; i < SILENT_START.length; i++) {
+ if (value.startsWith(SILENT_START[i])) {
+ result = true;
+ break;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Cleans the input
+ */
+ private String cleanInput(String input) {
+ if (input == null) {
+ return null;
+ }
+ input = input.trim();
+ if (input.length() == 0) {
+ return null;
+ }
+ return input.toUpperCase(java.util.Locale.ENGLISH);
+ }
+
+ /**
+ * Gets the character at index <code>index</code> if available, otherwise
+ * it returns <code>Character.MIN_VALUE</code> so that there is some sort
+ * of a default
+ */
+ protected char charAt(String value, int index) {
+ if (index < 0 || index >= value.length()) {
+ return Character.MIN_VALUE;
+ }
+ return value.charAt(index);
+ }
+
+ /**
+ * Shortcut method with 1 criteria
+ */
+ private static boolean contains(String value, int start, int length,
+ String criteria) {
+ return contains(value, start, length,
+ new String[] { criteria });
+ }
+
+ /**
+ * Shortcut method with 2 criteria
+ */
+ private static boolean contains(String value, int start, int length,
+ String criteria1, String criteria2) {
+ return contains(value, start, length,
+ new String[] { criteria1, criteria2 });
+ }
+
+ /**
+ * Shortcut method with 3 criteria
+ */
+ private static boolean contains(String value, int start, int length,
+ String criteria1, String criteria2,
+ String criteria3) {
+ return contains(value, start, length,
+ new String[] { criteria1, criteria2, criteria3 });
+ }
+
+ /**
+ * Shortcut method with 4 criteria
+ */
+ private static boolean contains(String value, int start, int length,
+ String criteria1, String criteria2,
+ String criteria3, String criteria4) {
+ return contains(value, start, length,
+ new String[] { criteria1, criteria2, criteria3,
+ criteria4 });
+ }
+
+ /**
+ * Shortcut method with 5 criteria
+ */
+ private static boolean contains(String value, int start, int length,
+ String criteria1, String criteria2,
+ String criteria3, String criteria4,
+ String criteria5) {
+ return contains(value, start, length,
+ new String[] { criteria1, criteria2, criteria3,
+ criteria4, criteria5 });
+ }
+
+ /**
+ * Shortcut method with 6 criteria
+ */
+ private static boolean contains(String value, int start, int length,
+ String criteria1, String criteria2,
+ String criteria3, String criteria4,
+ String criteria5, String criteria6) {
+ return contains(value, start, length,
+ new String[] { criteria1, criteria2, criteria3,
+ criteria4, criteria5, criteria6 });
+ }
+
+ /**
+ * Determines whether <code>value</code> contains any of the criteria starting at index <code>start</code> and
+ * matching up to length <code>length</code>
+ */
+ protected static boolean contains(String value, int start, int length,
+ String[] criteria) {
+ boolean result = false;
+ if (start >= 0 && start + length <= value.length()) {
+ String target = value.substring(start, start + length);
+
+ for (int i = 0; i < criteria.length; i++) {
+ if (target.equals(criteria[i])) {
+ result = true;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ //-- BEGIN INNER CLASSES --//
+
+ /**
+ * Inner class for storing results, since there is the optional alternate
+ * encoding.
+ */
+ public class DoubleMetaphoneResult {
+
+ private StringBuffer primary = new StringBuffer(getMaxCodeLen());
+ private StringBuffer alternate = new StringBuffer(getMaxCodeLen());
+ private int maxLength;
+
+ public DoubleMetaphoneResult(int maxLength) {
+ this.maxLength = maxLength;
+ }
+
+ public void append(char value) {
+ appendPrimary(value);
+ appendAlternate(value);
+ }
+
+ public void append(char primary, char alternate) {
+ appendPrimary(primary);
+ appendAlternate(alternate);
+ }
+
+ public void appendPrimary(char value) {
+ if (this.primary.length() < this.maxLength) {
+ this.primary.append(value);
+ }
+ }
+
+ public void appendAlternate(char value) {
+ if (this.alternate.length() < this.maxLength) {
+ this.alternate.append(value);
+ }
+ }
+
+ public void append(String value) {
+ appendPrimary(value);
+ appendAlternate(value);
+ }
+
+ public void append(String primary, String alternate) {
+ appendPrimary(primary);
+ appendAlternate(alternate);
+ }
+
+ public void appendPrimary(String value) {
+ int addChars = this.maxLength - this.primary.length();
+ if (value.length() <= addChars) {
+ this.primary.append(value);
+ } else {
+ this.primary.append(value.substring(0, addChars));
+ }
+ }
+
+ public void appendAlternate(String value) {
+ int addChars = this.maxLength - this.alternate.length();
+ if (value.length() <= addChars) {
+ this.alternate.append(value);
+ } else {
+ this.alternate.append(value.substring(0, addChars));
+ }
+ }
+
+ public String getPrimary() {
+ return this.primary.toString();
+ }
+
+ public String getAlternate() {
+ return this.alternate.toString();
+ }
+
+ public boolean isComplete() {
+ return this.primary.length() >= this.maxLength &&
+ this.alternate.length() >= this.maxLength;
+ }
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Metaphone.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Metaphone.java
new file mode 100644
index 000000000..ec7cd3813
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Metaphone.java
@@ -0,0 +1,408 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.language;
+
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.StringEncoder;
+
+/**
+ * Encodes a string into a Metaphone value.
+ * <p>
+ * Initial Java implementation by <CITE>William B. Brogden. December, 1997</CITE>.
+ * Permission given by <CITE>wbrogden</CITE> for code to be used anywhere.
+ * </p>
+ * <p>
+ * <CITE>Hanging on the Metaphone</CITE> by <CITE>Lawrence Philips</CITE> in <CITE>Computer Language of Dec. 1990, p
+ * 39.</CITE>
+ * </p>
+ * <p>
+ * Note, that this does not match the algorithm that ships with PHP, or the algorithm
+ * found in the Perl <a href="http://search.cpan.org/~mschwern/Text-Metaphone-1.96/Metaphone.pm">Text:Metaphone-1.96</a>.
+ * They have had undocumented changes from the originally published algorithm.
+ * For more information, see <a href="https://issues.apache.org/jira/browse/CODEC-57">CODEC-57</a>.
+ * </p>
+ *
+ * @author Apache Software Foundation
+ * @version $Id: Metaphone.java 1080867 2011-03-12 06:06:46Z ggregory $
+ */
+public class Metaphone implements StringEncoder {
+
+ /**
+ * Five values in the English language
+ */
+ private static final String VOWELS = "AEIOU" ;
+
+ /**
+ * Variable used in Metaphone algorithm
+ */
+ private static final String FRONTV = "EIY" ;
+
+ /**
+ * Variable used in Metaphone algorithm
+ */
+ private static final String VARSON = "CSPTG" ;
+
+ /**
+ * The max code length for metaphone is 4
+ */
+ private int maxCodeLen = 4 ;
+
+ /**
+ * Creates an instance of the Metaphone encoder
+ */
+ public Metaphone() {
+ super();
+ }
+
+ /**
+ * Find the metaphone value of a String. This is similar to the
+ * soundex algorithm, but better at finding similar sounding words.
+ * All input is converted to upper case.
+ * Limitations: Input format is expected to be a single ASCII word
+ * with only characters in the A - Z range, no punctuation or numbers.
+ *
+ * @param txt String to find the metaphone code for
+ * @return A metaphone code corresponding to the String supplied
+ */
+ public String metaphone(String txt) {
+ boolean hard = false ;
+ if ((txt == null) || (txt.length() == 0)) {
+ return "" ;
+ }
+ // single character is itself
+ if (txt.length() == 1) {
+ return txt.toUpperCase(java.util.Locale.ENGLISH) ;
+ }
+
+ char[] inwd = txt.toUpperCase(java.util.Locale.ENGLISH).toCharArray() ;
+
+ StringBuffer local = new StringBuffer(40); // manipulate
+ StringBuffer code = new StringBuffer(10) ; // output
+ // handle initial 2 characters exceptions
+ switch(inwd[0]) {
+ case 'K' :
+ case 'G' :
+ case 'P' : /* looking for KN, etc*/
+ if (inwd[1] == 'N') {
+ local.append(inwd, 1, inwd.length - 1);
+ } else {
+ local.append(inwd);
+ }
+ break;
+ case 'A': /* looking for AE */
+ if (inwd[1] == 'E') {
+ local.append(inwd, 1, inwd.length - 1);
+ } else {
+ local.append(inwd);
+ }
+ break;
+ case 'W' : /* looking for WR or WH */
+ if (inwd[1] == 'R') { // WR -> R
+ local.append(inwd, 1, inwd.length - 1);
+ break ;
+ }
+ if (inwd[1] == 'H') {
+ local.append(inwd, 1, inwd.length - 1);
+ local.setCharAt(0, 'W'); // WH -> W
+ } else {
+ local.append(inwd);
+ }
+ break;
+ case 'X' : /* initial X becomes S */
+ inwd[0] = 'S';
+ local.append(inwd);
+ break ;
+ default :
+ local.append(inwd);
+ } // now local has working string with initials fixed
+
+ int wdsz = local.length();
+ int n = 0 ;
+
+ while ((code.length() < this.getMaxCodeLen()) &&
+ (n < wdsz) ) { // max code size of 4 works well
+ char symb = local.charAt(n) ;
+ // remove duplicate letters except C
+ if ((symb != 'C') && (isPreviousChar( local, n, symb )) ) {
+ n++ ;
+ } else { // not dup
+ switch(symb) {
+ case 'A' : case 'E' : case 'I' : case 'O' : case 'U' :
+ if (n == 0) {
+ code.append(symb);
+ }
+ break ; // only use vowel if leading char
+ case 'B' :
+ if ( isPreviousChar(local, n, 'M') &&
+ isLastChar(wdsz, n) ) { // B is silent if word ends in MB
+ break;
+ }
+ code.append(symb);
+ break;
+ case 'C' : // lots of C special cases
+ /* discard if SCI, SCE or SCY */
+ if ( isPreviousChar(local, n, 'S') &&
+ !isLastChar(wdsz, n) &&
+ (FRONTV.indexOf(local.charAt(n + 1)) >= 0) ) {
+ break;
+ }
+ if (regionMatch(local, n, "CIA")) { // "CIA" -> X
+ code.append('X');
+ break;
+ }
+ if (!isLastChar(wdsz, n) &&
+ (FRONTV.indexOf(local.charAt(n + 1)) >= 0)) {
+ code.append('S');
+ break; // CI,CE,CY -> S
+ }
+ if (isPreviousChar(local, n, 'S') &&
+ isNextChar(local, n, 'H') ) { // SCH->sk
+ code.append('K') ;
+ break ;
+ }
+ if (isNextChar(local, n, 'H')) { // detect CH
+ if ((n == 0) &&
+ (wdsz >= 3) &&
+ isVowel(local,2) ) { // CH consonant -> K consonant
+ code.append('K');
+ } else {
+ code.append('X'); // CHvowel -> X
+ }
+ } else {
+ code.append('K');
+ }
+ break ;
+ case 'D' :
+ if (!isLastChar(wdsz, n + 1) &&
+ isNextChar(local, n, 'G') &&
+ (FRONTV.indexOf(local.charAt(n + 2)) >= 0)) { // DGE DGI DGY -> J
+ code.append('J'); n += 2 ;
+ } else {
+ code.append('T');
+ }
+ break ;
+ case 'G' : // GH silent at end or before consonant
+ if (isLastChar(wdsz, n + 1) &&
+ isNextChar(local, n, 'H')) {
+ break;
+ }
+ if (!isLastChar(wdsz, n + 1) &&
+ isNextChar(local,n,'H') &&
+ !isVowel(local,n+2)) {
+ break;
+ }
+ if ((n > 0) &&
+ ( regionMatch(local, n, "GN") ||
+ regionMatch(local, n, "GNED") ) ) {
+ break; // silent G
+ }
+ if (isPreviousChar(local, n, 'G')) {
+ // NOTE: Given that duplicated chars are removed, I don't see how this can ever be true
+ hard = true ;
+ } else {
+ hard = false ;
+ }
+ if (!isLastChar(wdsz, n) &&
+ (FRONTV.indexOf(local.charAt(n + 1)) >= 0) &&
+ (!hard)) {
+ code.append('J');
+ } else {
+ code.append('K');
+ }
+ break ;
+ case 'H':
+ if (isLastChar(wdsz, n)) {
+ break ; // terminal H
+ }
+ if ((n > 0) &&
+ (VARSON.indexOf(local.charAt(n - 1)) >= 0)) {
+ break;
+ }
+ if (isVowel(local,n+1)) {
+ code.append('H'); // Hvowel
+ }
+ break;
+ case 'F':
+ case 'J' :
+ case 'L' :
+ case 'M':
+ case 'N' :
+ case 'R' :
+ code.append(symb);
+ break;
+ case 'K' :
+ if (n > 0) { // not initial
+ if (!isPreviousChar(local, n, 'C')) {
+ code.append(symb);
+ }
+ } else {
+ code.append(symb); // initial K
+ }
+ break ;
+ case 'P' :
+ if (isNextChar(local,n,'H')) {
+ // PH -> F
+ code.append('F');
+ } else {
+ code.append(symb);
+ }
+ break ;
+ case 'Q' :
+ code.append('K');
+ break;
+ case 'S' :
+ if (regionMatch(local,n,"SH") ||
+ regionMatch(local,n,"SIO") ||
+ regionMatch(local,n,"SIA")) {
+ code.append('X');
+ } else {
+ code.append('S');
+ }
+ break;
+ case 'T' :
+ if (regionMatch(local,n,"TIA") ||
+ regionMatch(local,n,"TIO")) {
+ code.append('X');
+ break;
+ }
+ if (regionMatch(local,n,"TCH")) {
+ // Silent if in "TCH"
+ break;
+ }
+ // substitute numeral 0 for TH (resembles theta after all)
+ if (regionMatch(local,n,"TH")) {
+ code.append('0');
+ } else {
+ code.append('T');
+ }
+ break ;
+ case 'V' :
+ code.append('F'); break ;
+ case 'W' : case 'Y' : // silent if not followed by vowel
+ if (!isLastChar(wdsz,n) &&
+ isVowel(local,n+1)) {
+ code.append(symb);
+ }
+ break ;
+ case 'X' :
+ code.append('K'); code.append('S');
+ break ;
+ case 'Z' :
+ code.append('S'); break ;
+ } // end switch
+ n++ ;
+ } // end else from symb != 'C'
+ if (code.length() > this.getMaxCodeLen()) {
+ code.setLength(this.getMaxCodeLen());
+ }
+ }
+ return code.toString();
+ }
+
+ private boolean isVowel(StringBuffer string, int index) {
+ return VOWELS.indexOf(string.charAt(index)) >= 0;
+ }
+
+ private boolean isPreviousChar(StringBuffer string, int index, char c) {
+ boolean matches = false;
+ if( index > 0 &&
+ index < string.length() ) {
+ matches = string.charAt(index - 1) == c;
+ }
+ return matches;
+ }
+
+ private boolean isNextChar(StringBuffer string, int index, char c) {
+ boolean matches = false;
+ if( index >= 0 &&
+ index < string.length() - 1 ) {
+ matches = string.charAt(index + 1) == c;
+ }
+ return matches;
+ }
+
+ private boolean regionMatch(StringBuffer string, int index, String test) {
+ boolean matches = false;
+ if( index >= 0 &&
+ (index + test.length() - 1) < string.length() ) {
+ String substring = string.substring( index, index + test.length());
+ matches = substring.equals( test );
+ }
+ return matches;
+ }
+
+ private boolean isLastChar(int wdsz, int n) {
+ return n + 1 == wdsz;
+ }
+
+
+ /**
+ * Encodes an Object using the metaphone algorithm. This method
+ * is provided in order to satisfy the requirements of the
+ * Encoder interface, and will throw an EncoderException if the
+ * supplied object is not of type java.lang.String.
+ *
+ * @param pObject Object to encode
+ * @return An object (or type java.lang.String) containing the
+ * metaphone code which corresponds to the String supplied.
+ * @throws EncoderException if the parameter supplied is not
+ * of type java.lang.String
+ */
+ public Object encode(Object pObject) throws EncoderException {
+ if (!(pObject instanceof String)) {
+ throw new EncoderException("Parameter supplied to Metaphone encode is not of type java.lang.String");
+ }
+ return metaphone((String) pObject);
+ }
+
+ /**
+ * Encodes a String using the Metaphone algorithm.
+ *
+ * @param pString String object to encode
+ * @return The metaphone code corresponding to the String supplied
+ */
+ public String encode(String pString) {
+ return metaphone(pString);
+ }
+
+ /**
+ * Tests is the metaphones of two strings are identical.
+ *
+ * @param str1 First of two strings to compare
+ * @param str2 Second of two strings to compare
+ * @return <code>true</code> if the metaphones of these strings are identical,
+ * <code>false</code> otherwise.
+ */
+ public boolean isMetaphoneEqual(String str1, String str2) {
+ return metaphone(str1).equals(metaphone(str2));
+ }
+
+ /**
+ * Returns the maxCodeLen.
+ * @return int
+ */
+ public int getMaxCodeLen() { return this.maxCodeLen; }
+
+ /**
+ * Sets the maxCodeLen.
+ * @param maxCodeLen The maxCodeLen to set
+ */
+ public void setMaxCodeLen(int maxCodeLen) { this.maxCodeLen = maxCodeLen; }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/RefinedSoundex.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/RefinedSoundex.java
new file mode 100644
index 000000000..7fb730cea
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/RefinedSoundex.java
@@ -0,0 +1,203 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.language;
+
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.StringEncoder;
+
+/**
+ * Encodes a string into a Refined Soundex value. A refined soundex code is
+ * optimized for spell checking words. Soundex method originally developed by
+ * <CITE>Margaret Odell</CITE> and <CITE>Robert Russell</CITE>.
+ *
+ * @author Apache Software Foundation
+ * @version $Id: RefinedSoundex.java 1064455 2011-01-28 04:40:27Z ggregory $
+ */
+public class RefinedSoundex implements StringEncoder {
+
+ /**
+ * @since 1.4
+ */
+ public static final String US_ENGLISH_MAPPING_STRING = "01360240043788015936020505";
+
+ /**
+ * RefinedSoundex is *refined* for a number of reasons one being that the
+ * mappings have been altered. This implementation contains default
+ * mappings for US English.
+ */
+ private static final char[] US_ENGLISH_MAPPING = US_ENGLISH_MAPPING_STRING.toCharArray();
+
+ /**
+ * Every letter of the alphabet is "mapped" to a numerical value. This char
+ * array holds the values to which each letter is mapped. This
+ * implementation contains a default map for US_ENGLISH
+ */
+ private final char[] soundexMapping;
+
+ /**
+ * This static variable contains an instance of the RefinedSoundex using
+ * the US_ENGLISH mapping.
+ */
+ public static final RefinedSoundex US_ENGLISH = new RefinedSoundex();
+
+ /**
+ * Creates an instance of the RefinedSoundex object using the default US
+ * English mapping.
+ */
+ public RefinedSoundex() {
+ this.soundexMapping = US_ENGLISH_MAPPING;
+ }
+
+ /**
+ * Creates a refined soundex instance using a custom mapping. This
+ * constructor can be used to customize the mapping, and/or possibly
+ * provide an internationalized mapping for a non-Western character set.
+ *
+ * @param mapping
+ * Mapping array to use when finding the corresponding code for
+ * a given character
+ */
+ public RefinedSoundex(char[] mapping) {
+ this.soundexMapping = new char[mapping.length];
+ System.arraycopy(mapping, 0, this.soundexMapping, 0, mapping.length);
+ }
+
+ /**
+ * Creates a refined Soundex instance using a custom mapping. This constructor can be used to customize the mapping,
+ * and/or possibly provide an internationalized mapping for a non-Western character set.
+ *
+ * @param mapping
+ * Mapping string to use when finding the corresponding code for a given character
+ * @since 1.4
+ */
+ public RefinedSoundex(String mapping) {
+ this.soundexMapping = mapping.toCharArray();
+ }
+
+ /**
+ * Returns the number of characters in the two encoded Strings that are the
+ * same. This return value ranges from 0 to the length of the shortest
+ * encoded String: 0 indicates little or no similarity, and 4 out of 4 (for
+ * example) indicates strong similarity or identical values. For refined
+ * Soundex, the return value can be greater than 4.
+ *
+ * @param s1
+ * A String that will be encoded and compared.
+ * @param s2
+ * A String that will be encoded and compared.
+ * @return The number of characters in the two encoded Strings that are the
+ * same from 0 to to the length of the shortest encoded String.
+ *
+ * @see SoundexUtils#difference(StringEncoder,String,String)
+ * @see <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_de-dz_8co5.asp">
+ * MS T-SQL DIFFERENCE</a>
+ *
+ * @throws EncoderException
+ * if an error occurs encoding one of the strings
+ * @since 1.3
+ */
+ public int difference(String s1, String s2) throws EncoderException {
+ return SoundexUtils.difference(this, s1, s2);
+ }
+
+ /**
+ * Encodes an Object using the refined soundex algorithm. This method is
+ * provided in order to satisfy the requirements of the Encoder interface,
+ * and will throw an EncoderException if the supplied object is not of type
+ * java.lang.String.
+ *
+ * @param pObject
+ * Object to encode
+ * @return An object (or type java.lang.String) containing the refined
+ * soundex code which corresponds to the String supplied.
+ * @throws EncoderException
+ * if the parameter supplied is not of type java.lang.String
+ */
+ public Object encode(Object pObject) throws EncoderException {
+ if (!(pObject instanceof String)) {
+ throw new EncoderException("Parameter supplied to RefinedSoundex encode is not of type java.lang.String");
+ }
+ return soundex((String) pObject);
+ }
+
+ /**
+ * Encodes a String using the refined soundex algorithm.
+ *
+ * @param pString
+ * A String object to encode
+ * @return A Soundex code corresponding to the String supplied
+ */
+ public String encode(String pString) {
+ return soundex(pString);
+ }
+
+ /**
+ * Returns the mapping code for a given character. The mapping codes are
+ * maintained in an internal char array named soundexMapping, and the
+ * default values of these mappings are US English.
+ *
+ * @param c
+ * char to get mapping for
+ * @return A character (really a numeral) to return for the given char
+ */
+ char getMappingCode(char c) {
+ if (!Character.isLetter(c)) {
+ return 0;
+ }
+ return this.soundexMapping[Character.toUpperCase(c) - 'A'];
+ }
+
+ /**
+ * Retreives the Refined Soundex code for a given String object.
+ *
+ * @param str
+ * String to encode using the Refined Soundex algorithm
+ * @return A soundex code for the String supplied
+ */
+ public String soundex(String str) {
+ if (str == null) {
+ return null;
+ }
+ str = SoundexUtils.clean(str);
+ if (str.length() == 0) {
+ return str;
+ }
+
+ StringBuffer sBuf = new StringBuffer();
+ sBuf.append(str.charAt(0));
+
+ char last, current;
+ last = '*';
+
+ for (int i = 0; i < str.length(); i++) {
+
+ current = getMappingCode(str.charAt(i));
+ if (current == last) {
+ continue;
+ } else if (current != 0) {
+ sBuf.append(current);
+ }
+
+ last = current;
+
+ }
+
+ return sBuf.toString();
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Soundex.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Soundex.java
new file mode 100644
index 000000000..76805bca3
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Soundex.java
@@ -0,0 +1,279 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.language;
+
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.StringEncoder;
+
+/**
+ * Encodes a string into a Soundex value. Soundex is an encoding used to relate similar names, but can also be used as a
+ * general purpose scheme to find word with similar phonemes.
+ *
+ * @author Apache Software Foundation
+ * @version $Id: Soundex.java 1064454 2011-01-28 04:40:02Z ggregory $
+ */
+public class Soundex implements StringEncoder {
+
+ /**
+ * This is a default mapping of the 26 letters used in US English. A value of <code>0</code> for a letter position
+ * means do not encode.
+ * <p>
+ * (This constant is provided as both an implementation convenience and to allow Javadoc to pick
+ * up the value for the constant values page.)
+ * </p>
+ *
+ * @see #US_ENGLISH_MAPPING
+ */
+ public static final String US_ENGLISH_MAPPING_STRING = "01230120022455012623010202";
+
+ /**
+ * This is a default mapping of the 26 letters used in US English. A value of <code>0</code> for a letter position
+ * means do not encode.
+ *
+ * @see Soundex#Soundex(char[])
+ */
+ private static final char[] US_ENGLISH_MAPPING = US_ENGLISH_MAPPING_STRING.toCharArray();
+
+ /**
+ * An instance of Soundex using the US_ENGLISH_MAPPING mapping.
+ *
+ * @see #US_ENGLISH_MAPPING
+ */
+ public static final Soundex US_ENGLISH = new Soundex();
+
+
+ /**
+ * Encodes the Strings and returns the number of characters in the two encoded Strings that are the same. This
+ * return value ranges from 0 through 4: 0 indicates little or no similarity, and 4 indicates strong similarity or
+ * identical values.
+ *
+ * @param s1
+ * A String that will be encoded and compared.
+ * @param s2
+ * A String that will be encoded and compared.
+ * @return The number of characters in the two encoded Strings that are the same from 0 to 4.
+ *
+ * @see SoundexUtils#difference(StringEncoder,String,String)
+ * @see <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_de-dz_8co5.asp"> MS
+ * T-SQL DIFFERENCE </a>
+ *
+ * @throws EncoderException
+ * if an error occurs encoding one of the strings
+ * @since 1.3
+ */
+ public int difference(String s1, String s2) throws EncoderException {
+ return SoundexUtils.difference(this, s1, s2);
+ }
+
+ /**
+ * The maximum length of a Soundex code - Soundex codes are only four characters by definition.
+ *
+ * @deprecated This feature is not needed since the encoding size must be constant. Will be removed in 2.0.
+ */
+ private int maxLength = 4;
+
+ /**
+ * Every letter of the alphabet is "mapped" to a numerical value. This char array holds the values to which each
+ * letter is mapped. This implementation contains a default map for US_ENGLISH
+ */
+ private final char[] soundexMapping;
+
+ /**
+ * Creates an instance using US_ENGLISH_MAPPING
+ *
+ * @see Soundex#Soundex(char[])
+ * @see Soundex#US_ENGLISH_MAPPING
+ */
+ public Soundex() {
+ this.soundexMapping = US_ENGLISH_MAPPING;
+ }
+
+ /**
+ * Creates a soundex instance using the given mapping. This constructor can be used to provide an internationalized
+ * mapping for a non-Western character set.
+ *
+ * Every letter of the alphabet is "mapped" to a numerical value. This char array holds the values to which each
+ * letter is mapped. This implementation contains a default map for US_ENGLISH
+ *
+ * @param mapping
+ * Mapping array to use when finding the corresponding code for a given character
+ */
+ public Soundex(char[] mapping) {
+ this.soundexMapping = new char[mapping.length];
+ System.arraycopy(mapping, 0, this.soundexMapping, 0, mapping.length);
+ }
+
+ /**
+ * Creates a refined soundex instance using a custom mapping. This constructor can be used to customize the mapping,
+ * and/or possibly provide an internationalized mapping for a non-Western character set.
+ *
+ * @param mapping
+ * Mapping string to use when finding the corresponding code for a given character
+ * @since 1.4
+ */
+ public Soundex(String mapping) {
+ this.soundexMapping = mapping.toCharArray();
+ }
+
+ /**
+ * Encodes an Object using the soundex algorithm. This method is provided in order to satisfy the requirements of
+ * the Encoder interface, and will throw an EncoderException if the supplied object is not of type java.lang.String.
+ *
+ * @param pObject
+ * Object to encode
+ * @return An object (or type java.lang.String) containing the soundex code which corresponds to the String
+ * supplied.
+ * @throws EncoderException
+ * if the parameter supplied is not of type java.lang.String
+ * @throws IllegalArgumentException
+ * if a character is not mapped
+ */
+ public Object encode(Object pObject) throws EncoderException {
+ if (!(pObject instanceof String)) {
+ throw new EncoderException("Parameter supplied to Soundex encode is not of type java.lang.String");
+ }
+ return soundex((String) pObject);
+ }
+
+ /**
+ * Encodes a String using the soundex algorithm.
+ *
+ * @param pString
+ * A String object to encode
+ * @return A Soundex code corresponding to the String supplied
+ * @throws IllegalArgumentException
+ * if a character is not mapped
+ */
+ public String encode(String pString) {
+ return soundex(pString);
+ }
+
+ /**
+ * Used internally by the SoundEx algorithm.
+ *
+ * Consonants from the same code group separated by W or H are treated as one.
+ *
+ * @param str
+ * the cleaned working string to encode (in upper case).
+ * @param index
+ * the character position to encode
+ * @return Mapping code for a particular character
+ * @throws IllegalArgumentException
+ * if the character is not mapped
+ */
+ private char getMappingCode(String str, int index) {
+ // map() throws IllegalArgumentException
+ char mappedChar = this.map(str.charAt(index));
+ // HW rule check
+ if (index > 1 && mappedChar != '0') {
+ char hwChar = str.charAt(index - 1);
+ if ('H' == hwChar || 'W' == hwChar) {
+ char preHWChar = str.charAt(index - 2);
+ char firstCode = this.map(preHWChar);
+ if (firstCode == mappedChar || 'H' == preHWChar || 'W' == preHWChar) {
+ return 0;
+ }
+ }
+ }
+ return mappedChar;
+ }
+
+ /**
+ * Returns the maxLength. Standard Soundex
+ *
+ * @deprecated This feature is not needed since the encoding size must be constant. Will be removed in 2.0.
+ * @return int
+ */
+ public int getMaxLength() {
+ return this.maxLength;
+ }
+
+ /**
+ * Returns the soundex mapping.
+ *
+ * @return soundexMapping.
+ */
+ private char[] getSoundexMapping() {
+ return this.soundexMapping;
+ }
+
+ /**
+ * Maps the given upper-case character to its Soundex code.
+ *
+ * @param ch
+ * An upper-case character.
+ * @return A Soundex code.
+ * @throws IllegalArgumentException
+ * Thrown if <code>ch</code> is not mapped.
+ */
+ private char map(char ch) {
+ int index = ch - 'A';
+ if (index < 0 || index >= this.getSoundexMapping().length) {
+ throw new IllegalArgumentException("The character is not mapped: " + ch);
+ }
+ return this.getSoundexMapping()[index];
+ }
+
+ /**
+ * Sets the maxLength.
+ *
+ * @deprecated This feature is not needed since the encoding size must be constant. Will be removed in 2.0.
+ * @param maxLength
+ * The maxLength to set
+ */
+ public void setMaxLength(int maxLength) {
+ this.maxLength = maxLength;
+ }
+
+ /**
+ * Retrieves the Soundex code for a given String object.
+ *
+ * @param str
+ * String to encode using the Soundex algorithm
+ * @return A soundex code for the String supplied
+ * @throws IllegalArgumentException
+ * if a character is not mapped
+ */
+ public String soundex(String str) {
+ if (str == null) {
+ return null;
+ }
+ str = SoundexUtils.clean(str);
+ if (str.length() == 0) {
+ return str;
+ }
+ char out[] = {'0', '0', '0', '0'};
+ char last, mapped;
+ int incount = 1, count = 1;
+ out[0] = str.charAt(0);
+ // getMappingCode() throws IllegalArgumentException
+ last = getMappingCode(str, 0);
+ while ((incount < str.length()) && (count < out.length)) {
+ mapped = getMappingCode(str, incount++);
+ if (mapped != 0) {
+ if ((mapped != '0') && (mapped != last)) {
+ out[count++] = mapped;
+ }
+ last = mapped;
+ }
+ }
+ return new String(out);
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/SoundexUtils.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/SoundexUtils.java
new file mode 100644
index 000000000..3e5a16a5a
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/SoundexUtils.java
@@ -0,0 +1,124 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.language;
+
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.StringEncoder;
+
+/**
+ * Utility methods for {@link Soundex} and {@link RefinedSoundex} classes.
+ *
+ * @author Apache Software Foundation
+ * @version $Id: SoundexUtils.java 658834 2008-05-21 19:57:51Z niallp $
+ * @since 1.3
+ */
+final class SoundexUtils {
+
+ /**
+ * Cleans up the input string before Soundex processing by only returning
+ * upper case letters.
+ *
+ * @param str
+ * The String to clean.
+ * @return A clean String.
+ */
+ static String clean(String str) {
+ if (str == null || str.length() == 0) {
+ return str;
+ }
+ int len = str.length();
+ char[] chars = new char[len];
+ int count = 0;
+ for (int i = 0; i < len; i++) {
+ if (Character.isLetter(str.charAt(i))) {
+ chars[count++] = str.charAt(i);
+ }
+ }
+ if (count == len) {
+ return str.toUpperCase(java.util.Locale.ENGLISH);
+ }
+ return new String(chars, 0, count).toUpperCase(java.util.Locale.ENGLISH);
+ }
+
+ /**
+ * Encodes the Strings and returns the number of characters in the two
+ * encoded Strings that are the same.
+ * <ul>
+ * <li>For Soundex, this return value ranges from 0 through 4: 0 indicates
+ * little or no similarity, and 4 indicates strong similarity or identical
+ * values.</li>
+ * <li>For refined Soundex, the return value can be greater than 4.</li>
+ * </ul>
+ *
+ * @param encoder
+ * The encoder to use to encode the Strings.
+ * @param s1
+ * A String that will be encoded and compared.
+ * @param s2
+ * A String that will be encoded and compared.
+ * @return The number of characters in the two Soundex encoded Strings that
+ * are the same.
+ *
+ * @see #differenceEncoded(String,String)
+ * @see <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_de-dz_8co5.asp">
+ * MS T-SQL DIFFERENCE</a>
+ *
+ * @throws EncoderException
+ * if an error occurs encoding one of the strings
+ */
+ static int difference(StringEncoder encoder, String s1, String s2) throws EncoderException {
+ return differenceEncoded(encoder.encode(s1), encoder.encode(s2));
+ }
+
+ /**
+ * Returns the number of characters in the two Soundex encoded Strings that
+ * are the same.
+ * <ul>
+ * <li>For Soundex, this return value ranges from 0 through 4: 0 indicates
+ * little or no similarity, and 4 indicates strong similarity or identical
+ * values.</li>
+ * <li>For refined Soundex, the return value can be greater than 4.</li>
+ * </ul>
+ *
+ * @param es1
+ * An encoded String.
+ * @param es2
+ * An encoded String.
+ * @return The number of characters in the two Soundex encoded Strings that
+ * are the same.
+ *
+ * @see <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_de-dz_8co5.asp">
+ * MS T-SQL DIFFERENCE</a>
+ */
+ static int differenceEncoded(String es1, String es2) {
+
+ if (es1 == null || es2 == null) {
+ return 0;
+ }
+ int lengthToMatch = Math.min(es1.length(), es2.length());
+ int diff = 0;
+ for (int i = 0; i < lengthToMatch; i++) {
+ if (es1.charAt(i) == es2.charAt(i)) {
+ diff++;
+ }
+ }
+ return diff;
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/package.html b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/package.html
new file mode 100644
index 000000000..6e3376689
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/package.html
@@ -0,0 +1,21 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. 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.
+-->
+<html>
+ <body>
+ Language and phonetic encoders.
+ </body>
+</html>
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/BCodec.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/BCodec.java
new file mode 100644
index 000000000..b694888eb
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/BCodec.java
@@ -0,0 +1,209 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.net;
+
+import java.io.UnsupportedEncodingException;
+
+import org.mozilla.apache.commons.codec.DecoderException;
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.CharEncoding;
+import org.mozilla.apache.commons.codec.StringDecoder;
+import org.mozilla.apache.commons.codec.StringEncoder;
+import org.mozilla.apache.commons.codec.binary.Base64;
+
+/**
+ * <p>
+ * Identical to the Base64 encoding defined by <a href="http://www.ietf.org/rfc/rfc1521.txt">RFC
+ * 1521</a> and allows a character set to be specified.
+ * </p>
+ *
+ * <p>
+ * <a href="http://www.ietf.org/rfc/rfc1522.txt">RFC 1522</a> describes techniques to allow the encoding of non-ASCII
+ * text in various portions of a RFC 822 [2] message header, in a manner which is unlikely to confuse existing message
+ * handling software.
+ * </p>
+ *
+ * @see <a href="http://www.ietf.org/rfc/rfc1522.txt">MIME (Multipurpose Internet Mail Extensions) Part Two: Message
+ * Header Extensions for Non-ASCII Text</a>
+ *
+ * @author Apache Software Foundation
+ * @since 1.3
+ * @version $Id: BCodec.java 797857 2009-07-25 23:43:33Z ggregory $
+ */
+public class BCodec extends RFC1522Codec implements StringEncoder, StringDecoder {
+ /**
+ * The default charset used for string decoding and encoding.
+ */
+ private final String charset;
+
+ /**
+ * Default constructor.
+ */
+ public BCodec() {
+ this(CharEncoding.UTF_8);
+ }
+
+ /**
+ * Constructor which allows for the selection of a default charset
+ *
+ * @param charset
+ * the default string charset to use.
+ *
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ */
+ public BCodec(final String charset) {
+ super();
+ this.charset = charset;
+ }
+
+ protected String getEncoding() {
+ return "B";
+ }
+
+ protected byte[] doEncoding(byte[] bytes) {
+ if (bytes == null) {
+ return null;
+ }
+ return Base64.encodeBase64(bytes);
+ }
+
+ protected byte[] doDecoding(byte[] bytes) {
+ if (bytes == null) {
+ return null;
+ }
+ return Base64.decodeBase64(bytes);
+ }
+
+ /**
+ * Encodes a string into its Base64 form using the specified charset. Unsafe characters are escaped.
+ *
+ * @param value
+ * string to convert to Base64 form
+ * @param charset
+ * the charset for <code>value</code>
+ * @return Base64 string
+ *
+ * @throws EncoderException
+ * thrown if a failure condition is encountered during the encoding process.
+ */
+ public String encode(final String value, final String charset) throws EncoderException {
+ if (value == null) {
+ return null;
+ }
+ try {
+ return encodeText(value, charset);
+ } catch (UnsupportedEncodingException e) {
+ throw new EncoderException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Encodes a string into its Base64 form using the default charset. Unsafe characters are escaped.
+ *
+ * @param value
+ * string to convert to Base64 form
+ * @return Base64 string
+ *
+ * @throws EncoderException
+ * thrown if a failure condition is encountered during the encoding process.
+ */
+ public String encode(String value) throws EncoderException {
+ if (value == null) {
+ return null;
+ }
+ return encode(value, getDefaultCharset());
+ }
+
+ /**
+ * Decodes a Base64 string into its original form. Escaped characters are converted back to their original
+ * representation.
+ *
+ * @param value
+ * Base64 string to convert into its original form
+ * @return original string
+ * @throws DecoderException
+ * A decoder exception is thrown if a failure condition is encountered during the decode process.
+ */
+ public String decode(String value) throws DecoderException {
+ if (value == null) {
+ return null;
+ }
+ try {
+ return decodeText(value);
+ } catch (UnsupportedEncodingException e) {
+ throw new DecoderException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Encodes an object into its Base64 form using the default charset. Unsafe characters are escaped.
+ *
+ * @param value
+ * object to convert to Base64 form
+ * @return Base64 object
+ *
+ * @throws EncoderException
+ * thrown if a failure condition is encountered during the encoding process.
+ */
+ public Object encode(Object value) throws EncoderException {
+ if (value == null) {
+ return null;
+ } else if (value instanceof String) {
+ return encode((String) value);
+ } else {
+ throw new EncoderException("Objects of type " +
+ value.getClass().getName() +
+ " cannot be encoded using BCodec");
+ }
+ }
+
+ /**
+ * Decodes a Base64 object into its original form. Escaped characters are converted back to their original
+ * representation.
+ *
+ * @param value
+ * Base64 object to convert into its original form
+ *
+ * @return original object
+ *
+ * @throws DecoderException
+ * Thrown if the argument is not a <code>String</code>. Thrown if a failure condition is
+ * encountered during the decode process.
+ */
+ public Object decode(Object value) throws DecoderException {
+ if (value == null) {
+ return null;
+ } else if (value instanceof String) {
+ return decode((String) value);
+ } else {
+ throw new DecoderException("Objects of type " +
+ value.getClass().getName() +
+ " cannot be decoded using BCodec");
+ }
+ }
+
+ /**
+ * The default charset used for string decoding and encoding.
+ *
+ * @return the default string charset.
+ */
+ public String getDefaultCharset() {
+ return this.charset;
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/QCodec.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/QCodec.java
new file mode 100644
index 000000000..d174bcdff
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/QCodec.java
@@ -0,0 +1,312 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.net;
+
+import java.io.UnsupportedEncodingException;
+import java.util.BitSet;
+
+import org.mozilla.apache.commons.codec.DecoderException;
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.CharEncoding;
+import org.mozilla.apache.commons.codec.StringDecoder;
+import org.mozilla.apache.commons.codec.StringEncoder;
+
+/**
+ * <p>
+ * Similar to the Quoted-Printable content-transfer-encoding defined in <a
+ * href="http://www.ietf.org/rfc/rfc1521.txt">RFC 1521</a> and designed to allow text containing mostly ASCII
+ * characters to be decipherable on an ASCII terminal without decoding.
+ * </p>
+ *
+ * <p>
+ * <a href="http://www.ietf.org/rfc/rfc1522.txt">RFC 1522</a> describes techniques to allow the encoding of non-ASCII
+ * text in various portions of a RFC 822 [2] message header, in a manner which is unlikely to confuse existing message
+ * handling software.
+ * </p>
+ *
+ * @see <a href="http://www.ietf.org/rfc/rfc1522.txt">MIME (Multipurpose Internet Mail Extensions) Part Two: Message
+ * Header Extensions for Non-ASCII Text</a>
+ *
+ * @author Apache Software Foundation
+ * @since 1.3
+ * @version $Id: QCodec.java 797857 2009-07-25 23:43:33Z ggregory $
+ */
+public class QCodec extends RFC1522Codec implements StringEncoder, StringDecoder {
+ /**
+ * The default charset used for string decoding and encoding.
+ */
+ private final String charset;
+
+ /**
+ * BitSet of printable characters as defined in RFC 1522.
+ */
+ private static final BitSet PRINTABLE_CHARS = new BitSet(256);
+ // Static initializer for printable chars collection
+ static {
+ // alpha characters
+ PRINTABLE_CHARS.set(' ');
+ PRINTABLE_CHARS.set('!');
+ PRINTABLE_CHARS.set('"');
+ PRINTABLE_CHARS.set('#');
+ PRINTABLE_CHARS.set('$');
+ PRINTABLE_CHARS.set('%');
+ PRINTABLE_CHARS.set('&');
+ PRINTABLE_CHARS.set('\'');
+ PRINTABLE_CHARS.set('(');
+ PRINTABLE_CHARS.set(')');
+ PRINTABLE_CHARS.set('*');
+ PRINTABLE_CHARS.set('+');
+ PRINTABLE_CHARS.set(',');
+ PRINTABLE_CHARS.set('-');
+ PRINTABLE_CHARS.set('.');
+ PRINTABLE_CHARS.set('/');
+ for (int i = '0'; i <= '9'; i++) {
+ PRINTABLE_CHARS.set(i);
+ }
+ PRINTABLE_CHARS.set(':');
+ PRINTABLE_CHARS.set(';');
+ PRINTABLE_CHARS.set('<');
+ PRINTABLE_CHARS.set('>');
+ PRINTABLE_CHARS.set('@');
+ for (int i = 'A'; i <= 'Z'; i++) {
+ PRINTABLE_CHARS.set(i);
+ }
+ PRINTABLE_CHARS.set('[');
+ PRINTABLE_CHARS.set('\\');
+ PRINTABLE_CHARS.set(']');
+ PRINTABLE_CHARS.set('^');
+ PRINTABLE_CHARS.set('`');
+ for (int i = 'a'; i <= 'z'; i++) {
+ PRINTABLE_CHARS.set(i);
+ }
+ PRINTABLE_CHARS.set('{');
+ PRINTABLE_CHARS.set('|');
+ PRINTABLE_CHARS.set('}');
+ PRINTABLE_CHARS.set('~');
+ }
+
+ private static final byte BLANK = 32;
+
+ private static final byte UNDERSCORE = 95;
+
+ private boolean encodeBlanks = false;
+
+ /**
+ * Default constructor.
+ */
+ public QCodec() {
+ this(CharEncoding.UTF_8);
+ }
+
+ /**
+ * Constructor which allows for the selection of a default charset
+ *
+ * @param charset
+ * the default string charset to use.
+ *
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ */
+ public QCodec(final String charset) {
+ super();
+ this.charset = charset;
+ }
+
+ protected String getEncoding() {
+ return "Q";
+ }
+
+ protected byte[] doEncoding(byte[] bytes) {
+ if (bytes == null) {
+ return null;
+ }
+ byte[] data = QuotedPrintableCodec.encodeQuotedPrintable(PRINTABLE_CHARS, bytes);
+ if (this.encodeBlanks) {
+ for (int i = 0; i < data.length; i++) {
+ if (data[i] == BLANK) {
+ data[i] = UNDERSCORE;
+ }
+ }
+ }
+ return data;
+ }
+
+ protected byte[] doDecoding(byte[] bytes) throws DecoderException {
+ if (bytes == null) {
+ return null;
+ }
+ boolean hasUnderscores = false;
+ for (int i = 0; i < bytes.length; i++) {
+ if (bytes[i] == UNDERSCORE) {
+ hasUnderscores = true;
+ break;
+ }
+ }
+ if (hasUnderscores) {
+ byte[] tmp = new byte[bytes.length];
+ for (int i = 0; i < bytes.length; i++) {
+ byte b = bytes[i];
+ if (b != UNDERSCORE) {
+ tmp[i] = b;
+ } else {
+ tmp[i] = BLANK;
+ }
+ }
+ return QuotedPrintableCodec.decodeQuotedPrintable(tmp);
+ }
+ return QuotedPrintableCodec.decodeQuotedPrintable(bytes);
+ }
+
+ /**
+ * Encodes a string into its quoted-printable form using the specified charset. Unsafe characters are escaped.
+ *
+ * @param pString
+ * string to convert to quoted-printable form
+ * @param charset
+ * the charset for pString
+ * @return quoted-printable string
+ *
+ * @throws EncoderException
+ * thrown if a failure condition is encountered during the encoding process.
+ */
+ public String encode(final String pString, final String charset) throws EncoderException {
+ if (pString == null) {
+ return null;
+ }
+ try {
+ return encodeText(pString, charset);
+ } catch (UnsupportedEncodingException e) {
+ throw new EncoderException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Encodes a string into its quoted-printable form using the default charset. Unsafe characters are escaped.
+ *
+ * @param pString
+ * string to convert to quoted-printable form
+ * @return quoted-printable string
+ *
+ * @throws EncoderException
+ * thrown if a failure condition is encountered during the encoding process.
+ */
+ public String encode(String pString) throws EncoderException {
+ if (pString == null) {
+ return null;
+ }
+ return encode(pString, getDefaultCharset());
+ }
+
+ /**
+ * Decodes a quoted-printable string into its original form. Escaped characters are converted back to their original
+ * representation.
+ *
+ * @param pString
+ * quoted-printable string to convert into its original form
+ *
+ * @return original string
+ *
+ * @throws DecoderException
+ * A decoder exception is thrown if a failure condition is encountered during the decode process.
+ */
+ public String decode(String pString) throws DecoderException {
+ if (pString == null) {
+ return null;
+ }
+ try {
+ return decodeText(pString);
+ } catch (UnsupportedEncodingException e) {
+ throw new DecoderException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Encodes an object into its quoted-printable form using the default charset. Unsafe characters are escaped.
+ *
+ * @param pObject
+ * object to convert to quoted-printable form
+ * @return quoted-printable object
+ *
+ * @throws EncoderException
+ * thrown if a failure condition is encountered during the encoding process.
+ */
+ public Object encode(Object pObject) throws EncoderException {
+ if (pObject == null) {
+ return null;
+ } else if (pObject instanceof String) {
+ return encode((String) pObject);
+ } else {
+ throw new EncoderException("Objects of type " +
+ pObject.getClass().getName() +
+ " cannot be encoded using Q codec");
+ }
+ }
+
+ /**
+ * Decodes a quoted-printable object into its original form. Escaped characters are converted back to their original
+ * representation.
+ *
+ * @param pObject
+ * quoted-printable object to convert into its original form
+ *
+ * @return original object
+ *
+ * @throws DecoderException
+ * Thrown if the argument is not a <code>String</code>. Thrown if a failure condition is
+ * encountered during the decode process.
+ */
+ public Object decode(Object pObject) throws DecoderException {
+ if (pObject == null) {
+ return null;
+ } else if (pObject instanceof String) {
+ return decode((String) pObject);
+ } else {
+ throw new DecoderException("Objects of type " +
+ pObject.getClass().getName() +
+ " cannot be decoded using Q codec");
+ }
+ }
+
+ /**
+ * The default charset used for string decoding and encoding.
+ *
+ * @return the default string charset.
+ */
+ public String getDefaultCharset() {
+ return this.charset;
+ }
+
+ /**
+ * Tests if optional tranformation of SPACE characters is to be used
+ *
+ * @return <code>true</code> if SPACE characters are to be transformed, <code>false</code> otherwise
+ */
+ public boolean isEncodeBlanks() {
+ return this.encodeBlanks;
+ }
+
+ /**
+ * Defines whether optional tranformation of SPACE characters is to be used
+ *
+ * @param b
+ * <code>true</code> if SPACE characters are to be transformed, <code>false</code> otherwise
+ */
+ public void setEncodeBlanks(boolean b) {
+ this.encodeBlanks = b;
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/QuotedPrintableCodec.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/QuotedPrintableCodec.java
new file mode 100644
index 000000000..c9b5e6172
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/QuotedPrintableCodec.java
@@ -0,0 +1,388 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.net;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.BitSet;
+
+import org.mozilla.apache.commons.codec.BinaryDecoder;
+import org.mozilla.apache.commons.codec.BinaryEncoder;
+import org.mozilla.apache.commons.codec.DecoderException;
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.CharEncoding;
+import org.mozilla.apache.commons.codec.StringDecoder;
+import org.mozilla.apache.commons.codec.StringEncoder;
+import org.mozilla.apache.commons.codec.binary.StringUtils;
+
+/**
+ * <p>
+ * Codec for the Quoted-Printable section of <a href="http://www.ietf.org/rfc/rfc1521.txt">RFC 1521</a>.
+ * </p>
+ * <p>
+ * The Quoted-Printable encoding is intended to represent data that largely consists of octets that correspond to
+ * printable characters in the ASCII character set. It encodes the data in such a way that the resulting octets are
+ * unlikely to be modified by mail transport. If the data being encoded are mostly ASCII text, the encoded form of the
+ * data remains largely recognizable by humans. A body which is entirely ASCII may also be encoded in Quoted-Printable
+ * to ensure the integrity of the data should the message pass through a character- translating, and/or line-wrapping
+ * gateway.
+ * </p>
+ *
+ * <p>
+ * Note:
+ * </p>
+ * <p>
+ * Rules #3, #4, and #5 of the quoted-printable spec are not implemented yet because the complete quoted-printable spec
+ * does not lend itself well into the byte[] oriented codec framework. Complete the codec once the steamable codec
+ * framework is ready. The motivation behind providing the codec in a partial form is that it can already come in handy
+ * for those applications that do not require quoted-printable line formatting (rules #3, #4, #5), for instance Q codec.
+ * </p>
+ *
+ * @see <a href="http://www.ietf.org/rfc/rfc1521.txt"> RFC 1521 MIME (Multipurpose Internet Mail Extensions) Part One:
+ * Mechanisms for Specifying and Describing the Format of Internet Message Bodies </a>
+ *
+ * @author Apache Software Foundation
+ * @since 1.3
+ * @version $Id: QuotedPrintableCodec.java 1080712 2011-03-11 18:26:59Z ggregory $
+ */
+public class QuotedPrintableCodec implements BinaryEncoder, BinaryDecoder, StringEncoder, StringDecoder {
+ /**
+ * The default charset used for string decoding and encoding.
+ */
+ private final String charset;
+
+ /**
+ * BitSet of printable characters as defined in RFC 1521.
+ */
+ private static final BitSet PRINTABLE_CHARS = new BitSet(256);
+
+ private static final byte ESCAPE_CHAR = '=';
+
+ private static final byte TAB = 9;
+
+ private static final byte SPACE = 32;
+ // Static initializer for printable chars collection
+ static {
+ // alpha characters
+ for (int i = 33; i <= 60; i++) {
+ PRINTABLE_CHARS.set(i);
+ }
+ for (int i = 62; i <= 126; i++) {
+ PRINTABLE_CHARS.set(i);
+ }
+ PRINTABLE_CHARS.set(TAB);
+ PRINTABLE_CHARS.set(SPACE);
+ }
+
+ /**
+ * Default constructor.
+ */
+ public QuotedPrintableCodec() {
+ this(CharEncoding.UTF_8);
+ }
+
+ /**
+ * Constructor which allows for the selection of a default charset
+ *
+ * @param charset
+ * the default string charset to use.
+ */
+ public QuotedPrintableCodec(String charset) {
+ super();
+ this.charset = charset;
+ }
+
+ /**
+ * Encodes byte into its quoted-printable representation.
+ *
+ * @param b
+ * byte to encode
+ * @param buffer
+ * the buffer to write to
+ */
+ private static final void encodeQuotedPrintable(int b, ByteArrayOutputStream buffer) {
+ buffer.write(ESCAPE_CHAR);
+ char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, 16));
+ char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, 16));
+ buffer.write(hex1);
+ buffer.write(hex2);
+ }
+
+ /**
+ * Encodes an array of bytes into an array of quoted-printable 7-bit characters. Unsafe characters are escaped.
+ *
+ * <p>
+ * This function implements a subset of quoted-printable encoding specification (rule #1 and rule #2) as defined in
+ * RFC 1521 and is suitable for encoding binary data and unformatted text.
+ * </p>
+ *
+ * @param printable
+ * bitset of characters deemed quoted-printable
+ * @param bytes
+ * array of bytes to be encoded
+ * @return array of bytes containing quoted-printable data
+ */
+ public static final byte[] encodeQuotedPrintable(BitSet printable, byte[] bytes) {
+ if (bytes == null) {
+ return null;
+ }
+ if (printable == null) {
+ printable = PRINTABLE_CHARS;
+ }
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ for (int i = 0; i < bytes.length; i++) {
+ int b = bytes[i];
+ if (b < 0) {
+ b = 256 + b;
+ }
+ if (printable.get(b)) {
+ buffer.write(b);
+ } else {
+ encodeQuotedPrintable(b, buffer);
+ }
+ }
+ return buffer.toByteArray();
+ }
+
+ /**
+ * Decodes an array quoted-printable characters into an array of original bytes. Escaped characters are converted
+ * back to their original representation.
+ *
+ * <p>
+ * This function implements a subset of quoted-printable encoding specification (rule #1 and rule #2) as defined in
+ * RFC 1521.
+ * </p>
+ *
+ * @param bytes
+ * array of quoted-printable characters
+ * @return array of original bytes
+ * @throws DecoderException
+ * Thrown if quoted-printable decoding is unsuccessful
+ */
+ public static final byte[] decodeQuotedPrintable(byte[] bytes) throws DecoderException {
+ if (bytes == null) {
+ return null;
+ }
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ for (int i = 0; i < bytes.length; i++) {
+ int b = bytes[i];
+ if (b == ESCAPE_CHAR) {
+ try {
+ int u = Utils.digit16(bytes[++i]);
+ int l = Utils.digit16(bytes[++i]);
+ buffer.write((char) ((u << 4) + l));
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new DecoderException("Invalid quoted-printable encoding", e);
+ }
+ } else {
+ buffer.write(b);
+ }
+ }
+ return buffer.toByteArray();
+ }
+
+ /**
+ * Encodes an array of bytes into an array of quoted-printable 7-bit characters. Unsafe characters are escaped.
+ *
+ * <p>
+ * This function implements a subset of quoted-printable encoding specification (rule #1 and rule #2) as defined in
+ * RFC 1521 and is suitable for encoding binary data and unformatted text.
+ * </p>
+ *
+ * @param bytes
+ * array of bytes to be encoded
+ * @return array of bytes containing quoted-printable data
+ */
+ public byte[] encode(byte[] bytes) {
+ return encodeQuotedPrintable(PRINTABLE_CHARS, bytes);
+ }
+
+ /**
+ * Decodes an array of quoted-printable characters into an array of original bytes. Escaped characters are converted
+ * back to their original representation.
+ *
+ * <p>
+ * This function implements a subset of quoted-printable encoding specification (rule #1 and rule #2) as defined in
+ * RFC 1521.
+ * </p>
+ *
+ * @param bytes
+ * array of quoted-printable characters
+ * @return array of original bytes
+ * @throws DecoderException
+ * Thrown if quoted-printable decoding is unsuccessful
+ */
+ public byte[] decode(byte[] bytes) throws DecoderException {
+ return decodeQuotedPrintable(bytes);
+ }
+
+ /**
+ * Encodes a string into its quoted-printable form using the default string charset. Unsafe characters are escaped.
+ *
+ * <p>
+ * This function implements a subset of quoted-printable encoding specification (rule #1 and rule #2) as defined in
+ * RFC 1521 and is suitable for encoding binary data.
+ * </p>
+ *
+ * @param pString
+ * string to convert to quoted-printable form
+ * @return quoted-printable string
+ *
+ * @throws EncoderException
+ * Thrown if quoted-printable encoding is unsuccessful
+ *
+ * @see #getDefaultCharset()
+ */
+ public String encode(String pString) throws EncoderException {
+ if (pString == null) {
+ return null;
+ }
+ try {
+ return encode(pString, getDefaultCharset());
+ } catch (UnsupportedEncodingException e) {
+ throw new EncoderException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Decodes a quoted-printable string into its original form using the specified string charset. Escaped characters
+ * are converted back to their original representation.
+ *
+ * @param pString
+ * quoted-printable string to convert into its original form
+ * @param charset
+ * the original string charset
+ * @return original string
+ * @throws DecoderException
+ * Thrown if quoted-printable decoding is unsuccessful
+ * @throws UnsupportedEncodingException
+ * Thrown if charset is not supported
+ */
+ public String decode(String pString, String charset) throws DecoderException, UnsupportedEncodingException {
+ if (pString == null) {
+ return null;
+ }
+ return new String(decode(StringUtils.getBytesUsAscii(pString)), charset);
+ }
+
+ /**
+ * Decodes a quoted-printable string into its original form using the default string charset. Escaped characters are
+ * converted back to their original representation.
+ *
+ * @param pString
+ * quoted-printable string to convert into its original form
+ * @return original string
+ * @throws DecoderException
+ * Thrown if quoted-printable decoding is unsuccessful.
+ * Thrown if charset is not supported.
+ * @see #getDefaultCharset()
+ */
+ public String decode(String pString) throws DecoderException {
+ if (pString == null) {
+ return null;
+ }
+ try {
+ return decode(pString, getDefaultCharset());
+ } catch (UnsupportedEncodingException e) {
+ throw new DecoderException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Encodes an object into its quoted-printable safe form. Unsafe characters are escaped.
+ *
+ * @param pObject
+ * string to convert to a quoted-printable form
+ * @return quoted-printable object
+ * @throws EncoderException
+ * Thrown if quoted-printable encoding is not applicable to objects of this type or if encoding is
+ * unsuccessful
+ */
+ public Object encode(Object pObject) throws EncoderException {
+ if (pObject == null) {
+ return null;
+ } else if (pObject instanceof byte[]) {
+ return encode((byte[]) pObject);
+ } else if (pObject instanceof String) {
+ return encode((String) pObject);
+ } else {
+ throw new EncoderException("Objects of type " +
+ pObject.getClass().getName() +
+ " cannot be quoted-printable encoded");
+ }
+ }
+
+ /**
+ * Decodes a quoted-printable object into its original form. Escaped characters are converted back to their original
+ * representation.
+ *
+ * @param pObject
+ * quoted-printable object to convert into its original form
+ * @return original object
+ * @throws DecoderException
+ * Thrown if the argument is not a <code>String</code> or <code>byte[]</code>. Thrown if a failure condition is
+ * encountered during the decode process.
+ */
+ public Object decode(Object pObject) throws DecoderException {
+ if (pObject == null) {
+ return null;
+ } else if (pObject instanceof byte[]) {
+ return decode((byte[]) pObject);
+ } else if (pObject instanceof String) {
+ return decode((String) pObject);
+ } else {
+ throw new DecoderException("Objects of type " +
+ pObject.getClass().getName() +
+ " cannot be quoted-printable decoded");
+ }
+ }
+
+ /**
+ * Returns the default charset used for string decoding and encoding.
+ *
+ * @return the default string charset.
+ */
+ public String getDefaultCharset() {
+ return this.charset;
+ }
+
+ /**
+ * Encodes a string into its quoted-printable form using the specified charset. Unsafe characters are escaped.
+ *
+ * <p>
+ * This function implements a subset of quoted-printable encoding specification (rule #1 and rule #2) as defined in
+ * RFC 1521 and is suitable for encoding binary data and unformatted text.
+ * </p>
+ *
+ * @param pString
+ * string to convert to quoted-printable form
+ * @param charset
+ * the charset for pString
+ * @return quoted-printable string
+ *
+ * @throws UnsupportedEncodingException
+ * Thrown if the charset is not supported
+ */
+ public String encode(String pString, String charset) throws UnsupportedEncodingException {
+ if (pString == null) {
+ return null;
+ }
+ return StringUtils.newStringUsAscii(encode(pString.getBytes(charset)));
+ }
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/RFC1522Codec.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/RFC1522Codec.java
new file mode 100644
index 000000000..f11a450cb
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/RFC1522Codec.java
@@ -0,0 +1,179 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.net;
+
+import java.io.UnsupportedEncodingException;
+
+import org.mozilla.apache.commons.codec.DecoderException;
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.binary.StringUtils;
+
+/**
+ * <p>
+ * Implements methods common to all codecs defined in RFC 1522.
+ * </p>
+ *
+ * <p>
+ * <a href="http://www.ietf.org/rfc/rfc1522.txt">RFC 1522</a>
+ * describes techniques to allow the encoding of non-ASCII text in
+ * various portions of a RFC 822 [2] message header, in a manner which
+ * is unlikely to confuse existing message handling software.
+ * </p>
+
+ * @see <a href="http://www.ietf.org/rfc/rfc1522.txt">
+ * MIME (Multipurpose Internet Mail Extensions) Part Two:
+ * Message Header Extensions for Non-ASCII Text</a>
+ * </p>
+ *
+ * @author Apache Software Foundation
+ * @since 1.3
+ * @version $Id: RFC1522Codec.java 798428 2009-07-28 07:32:49Z ggregory $
+ */
+abstract class RFC1522Codec {
+
+ /**
+ * Separator.
+ */
+ protected static final char SEP = '?';
+
+ /**
+ * Prefix
+ */
+ protected static final String POSTFIX = "?=";
+
+ /**
+ * Postfix
+ */
+ protected static final String PREFIX = "=?";
+
+ /**
+ * Applies an RFC 1522 compliant encoding scheme to the given string of text with the
+ * given charset. This method constructs the "encoded-word" header common to all the
+ * RFC 1522 codecs and then invokes {@link #doEncoding(byte [])} method of a concrete
+ * class to perform the specific enconding.
+ *
+ * @param text a string to encode
+ * @param charset a charset to be used
+ *
+ * @return RFC 1522 compliant "encoded-word"
+ *
+ * @throws EncoderException thrown if there is an error conidition during the Encoding
+ * process.
+ * @throws UnsupportedEncodingException thrown if charset is not supported
+ *
+ * @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
+ */
+ protected String encodeText(final String text, final String charset)
+ throws EncoderException, UnsupportedEncodingException
+ {
+ if (text == null) {
+ return null;
+ }
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(PREFIX);
+ buffer.append(charset);
+ buffer.append(SEP);
+ buffer.append(getEncoding());
+ buffer.append(SEP);
+ byte [] rawdata = doEncoding(text.getBytes(charset));
+ buffer.append(StringUtils.newStringUsAscii(rawdata));
+ buffer.append(POSTFIX);
+ return buffer.toString();
+ }
+
+ /**
+ * Applies an RFC 1522 compliant decoding scheme to the given string of text. This method
+ * processes the "encoded-word" header common to all the RFC 1522 codecs and then invokes
+ * {@link #doEncoding(byte [])} method of a concrete class to perform the specific deconding.
+ *
+ * @param text a string to decode
+ * @return A new decoded String or <code>null</code> if the input is <code>null</code>.
+ *
+ * @throws DecoderException thrown if there is an error conidition during the Decoding
+ * process.
+ * @throws UnsupportedEncodingException thrown if charset specified in the "encoded-word"
+ * header is not supported
+ */
+ protected String decodeText(final String text)
+ throws DecoderException, UnsupportedEncodingException
+ {
+ if (text == null) {
+ return null;
+ }
+ if ((!text.startsWith(PREFIX)) || (!text.endsWith(POSTFIX))) {
+ throw new DecoderException("RFC 1522 violation: malformed encoded content");
+ }
+ int terminator = text.length() - 2;
+ int from = 2;
+ int to = text.indexOf(SEP, from);
+ if (to == terminator) {
+ throw new DecoderException("RFC 1522 violation: charset token not found");
+ }
+ String charset = text.substring(from, to);
+ if (charset.equals("")) {
+ throw new DecoderException("RFC 1522 violation: charset not specified");
+ }
+ from = to + 1;
+ to = text.indexOf(SEP, from);
+ if (to == terminator) {
+ throw new DecoderException("RFC 1522 violation: encoding token not found");
+ }
+ String encoding = text.substring(from, to);
+ if (!getEncoding().equalsIgnoreCase(encoding)) {
+ throw new DecoderException("This codec cannot decode " +
+ encoding + " encoded content");
+ }
+ from = to + 1;
+ to = text.indexOf(SEP, from);
+ byte[] data = StringUtils.getBytesUsAscii(text.substring(from, to));
+ data = doDecoding(data);
+ return new String(data, charset);
+ }
+
+ /**
+ * Returns the codec name (referred to as encoding in the RFC 1522)
+ *
+ * @return name of the codec
+ */
+ protected abstract String getEncoding();
+
+ /**
+ * Encodes an array of bytes using the defined encoding scheme
+ *
+ * @param bytes Data to be encoded
+ *
+ * @return A byte array containing the encoded data
+ *
+ * @throws EncoderException thrown if the Encoder encounters a failure condition
+ * during the encoding process.
+ */
+ protected abstract byte[] doEncoding(byte[] bytes) throws EncoderException;
+
+ /**
+ * Decodes an array of bytes using the defined encoding scheme
+ *
+ * @param bytes Data to be decoded
+ *
+ * @return a byte array that contains decoded data
+ *
+ * @throws DecoderException A decoder exception is thrown if a Decoder encounters a
+ * failure condition during the decode process.
+ */
+ protected abstract byte[] doDecoding(byte[] bytes) throws DecoderException;
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/URLCodec.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/URLCodec.java
new file mode 100644
index 000000000..74699310f
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/URLCodec.java
@@ -0,0 +1,362 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.net;
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.BitSet;
+
+import org.mozilla.apache.commons.codec.BinaryDecoder;
+import org.mozilla.apache.commons.codec.BinaryEncoder;
+import org.mozilla.apache.commons.codec.DecoderException;
+import org.mozilla.apache.commons.codec.EncoderException;
+import org.mozilla.apache.commons.codec.CharEncoding;
+import org.mozilla.apache.commons.codec.StringDecoder;
+import org.mozilla.apache.commons.codec.StringEncoder;
+import org.mozilla.apache.commons.codec.binary.StringUtils;
+
+/**
+ * <p>Implements the 'www-form-urlencoded' encoding scheme,
+ * also misleadingly known as URL encoding.</p>
+ *
+ * <p>For more detailed information please refer to
+ * <a href="http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4.1">
+ * Chapter 17.13.4 'Form content types'</a> of the
+ * <a href="http://www.w3.org/TR/html4/">HTML 4.01 Specification<a></p>
+ *
+ * <p>
+ * This codec is meant to be a replacement for standard Java classes
+ * {@link java.net.URLEncoder} and {@link java.net.URLDecoder}
+ * on older Java platforms, as these classes in Java versions below
+ * 1.4 rely on the platform's default charset encoding.
+ * </p>
+ *
+ * @author Apache Software Foundation
+ * @since 1.2
+ * @version $Id: URLCodec.java 1079537 2011-03-08 20:56:19Z ggregory $
+ */
+public class URLCodec implements BinaryEncoder, BinaryDecoder, StringEncoder, StringDecoder {
+
+ /**
+ * Radix used in encoding and decoding.
+ */
+ static final int RADIX = 16;
+
+ /**
+ * The default charset used for string decoding and encoding. Consider this field final. The next major release may
+ * break compatibility and make this field be final.
+ */
+ protected String charset;
+
+ /**
+ * Release 1.5 made this field final.
+ */
+ protected static final byte ESCAPE_CHAR = '%';
+ /**
+ * BitSet of www-form-url safe characters.
+ */
+ protected static final BitSet WWW_FORM_URL = new BitSet(256);
+
+ // Static initializer for www_form_url
+ static {
+ // alpha characters
+ for (int i = 'a'; i <= 'z'; i++) {
+ WWW_FORM_URL.set(i);
+ }
+ for (int i = 'A'; i <= 'Z'; i++) {
+ WWW_FORM_URL.set(i);
+ }
+ // numeric characters
+ for (int i = '0'; i <= '9'; i++) {
+ WWW_FORM_URL.set(i);
+ }
+ // special chars
+ WWW_FORM_URL.set('-');
+ WWW_FORM_URL.set('_');
+ WWW_FORM_URL.set('.');
+ WWW_FORM_URL.set('*');
+ // blank to be replaced with +
+ WWW_FORM_URL.set(' ');
+ }
+
+
+ /**
+ * Default constructor.
+ */
+ public URLCodec() {
+ this(CharEncoding.UTF_8);
+ }
+
+ /**
+ * Constructor which allows for the selection of a default charset
+ *
+ * @param charset the default string charset to use.
+ */
+ public URLCodec(String charset) {
+ super();
+ this.charset = charset;
+ }
+
+ /**
+ * Encodes an array of bytes into an array of URL safe 7-bit characters. Unsafe characters are escaped.
+ *
+ * @param urlsafe
+ * bitset of characters deemed URL safe
+ * @param bytes
+ * array of bytes to convert to URL safe characters
+ * @return array of bytes containing URL safe characters
+ */
+ public static final byte[] encodeUrl(BitSet urlsafe, byte[] bytes) {
+ if (bytes == null) {
+ return null;
+ }
+ if (urlsafe == null) {
+ urlsafe = WWW_FORM_URL;
+ }
+
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ for (int i = 0; i < bytes.length; i++) {
+ int b = bytes[i];
+ if (b < 0) {
+ b = 256 + b;
+ }
+ if (urlsafe.get(b)) {
+ if (b == ' ') {
+ b = '+';
+ }
+ buffer.write(b);
+ } else {
+ buffer.write(ESCAPE_CHAR);
+ char hex1 = Character.toUpperCase(Character.forDigit((b >> 4) & 0xF, RADIX));
+ char hex2 = Character.toUpperCase(Character.forDigit(b & 0xF, RADIX));
+ buffer.write(hex1);
+ buffer.write(hex2);
+ }
+ }
+ return buffer.toByteArray();
+ }
+
+ /**
+ * Decodes an array of URL safe 7-bit characters into an array of
+ * original bytes. Escaped characters are converted back to their
+ * original representation.
+ *
+ * @param bytes array of URL safe characters
+ * @return array of original bytes
+ * @throws DecoderException Thrown if URL decoding is unsuccessful
+ */
+ public static final byte[] decodeUrl(byte[] bytes) throws DecoderException {
+ if (bytes == null) {
+ return null;
+ }
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ for (int i = 0; i < bytes.length; i++) {
+ int b = bytes[i];
+ if (b == '+') {
+ buffer.write(' ');
+ } else if (b == ESCAPE_CHAR) {
+ try {
+ int u = Utils.digit16(bytes[++i]);
+ int l = Utils.digit16(bytes[++i]);
+ buffer.write((char) ((u << 4) + l));
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new DecoderException("Invalid URL encoding: ", e);
+ }
+ } else {
+ buffer.write(b);
+ }
+ }
+ return buffer.toByteArray();
+ }
+
+ /**
+ * Encodes an array of bytes into an array of URL safe 7-bit
+ * characters. Unsafe characters are escaped.
+ *
+ * @param bytes array of bytes to convert to URL safe characters
+ * @return array of bytes containing URL safe characters
+ */
+ public byte[] encode(byte[] bytes) {
+ return encodeUrl(WWW_FORM_URL, bytes);
+ }
+
+
+ /**
+ * Decodes an array of URL safe 7-bit characters into an array of
+ * original bytes. Escaped characters are converted back to their
+ * original representation.
+ *
+ * @param bytes array of URL safe characters
+ * @return array of original bytes
+ * @throws DecoderException Thrown if URL decoding is unsuccessful
+ */
+ public byte[] decode(byte[] bytes) throws DecoderException {
+ return decodeUrl(bytes);
+ }
+
+ /**
+ * Encodes a string into its URL safe form using the specified string charset. Unsafe characters are escaped.
+ *
+ * @param pString
+ * string to convert to a URL safe form
+ * @param charset
+ * the charset for pString
+ * @return URL safe string
+ * @throws UnsupportedEncodingException
+ * Thrown if charset is not supported
+ */
+ public String encode(String pString, String charset) throws UnsupportedEncodingException {
+ if (pString == null) {
+ return null;
+ }
+ return StringUtils.newStringUsAscii(encode(pString.getBytes(charset)));
+ }
+
+ /**
+ * Encodes a string into its URL safe form using the default string
+ * charset. Unsafe characters are escaped.
+ *
+ * @param pString string to convert to a URL safe form
+ * @return URL safe string
+ * @throws EncoderException Thrown if URL encoding is unsuccessful
+ *
+ * @see #getDefaultCharset()
+ */
+ public String encode(String pString) throws EncoderException {
+ if (pString == null) {
+ return null;
+ }
+ try {
+ return encode(pString, getDefaultCharset());
+ } catch (UnsupportedEncodingException e) {
+ throw new EncoderException(e.getMessage(), e);
+ }
+ }
+
+
+ /**
+ * Decodes a URL safe string into its original form using the
+ * specified encoding. Escaped characters are converted back
+ * to their original representation.
+ *
+ * @param pString URL safe string to convert into its original form
+ * @param charset the original string charset
+ * @return original string
+ * @throws DecoderException Thrown if URL decoding is unsuccessful
+ * @throws UnsupportedEncodingException Thrown if charset is not
+ * supported
+ */
+ public String decode(String pString, String charset) throws DecoderException, UnsupportedEncodingException {
+ if (pString == null) {
+ return null;
+ }
+ return new String(decode(StringUtils.getBytesUsAscii(pString)), charset);
+ }
+
+ /**
+ * Decodes a URL safe string into its original form using the default
+ * string charset. Escaped characters are converted back to their
+ * original representation.
+ *
+ * @param pString URL safe string to convert into its original form
+ * @return original string
+ * @throws DecoderException Thrown if URL decoding is unsuccessful
+ *
+ * @see #getDefaultCharset()
+ */
+ public String decode(String pString) throws DecoderException {
+ if (pString == null) {
+ return null;
+ }
+ try {
+ return decode(pString, getDefaultCharset());
+ } catch (UnsupportedEncodingException e) {
+ throw new DecoderException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Encodes an object into its URL safe form. Unsafe characters are
+ * escaped.
+ *
+ * @param pObject string to convert to a URL safe form
+ * @return URL safe object
+ * @throws EncoderException Thrown if URL encoding is not
+ * applicable to objects of this type or
+ * if encoding is unsuccessful
+ */
+ public Object encode(Object pObject) throws EncoderException {
+ if (pObject == null) {
+ return null;
+ } else if (pObject instanceof byte[]) {
+ return encode((byte[])pObject);
+ } else if (pObject instanceof String) {
+ return encode((String)pObject);
+ } else {
+ throw new EncoderException("Objects of type " +
+ pObject.getClass().getName() + " cannot be URL encoded");
+
+ }
+ }
+
+ /**
+ * Decodes a URL safe object into its original form. Escaped characters are converted back to their original
+ * representation.
+ *
+ * @param pObject
+ * URL safe object to convert into its original form
+ * @return original object
+ * @throws DecoderException
+ * Thrown if the argument is not a <code>String</code> or <code>byte[]</code>. Thrown if a failure condition is
+ * encountered during the decode process.
+ */
+ public Object decode(Object pObject) throws DecoderException {
+ if (pObject == null) {
+ return null;
+ } else if (pObject instanceof byte[]) {
+ return decode((byte[]) pObject);
+ } else if (pObject instanceof String) {
+ return decode((String) pObject);
+ } else {
+ throw new DecoderException("Objects of type " + pObject.getClass().getName() + " cannot be URL decoded");
+
+ }
+ }
+
+ /**
+ * The <code>String</code> encoding used for decoding and encoding.
+ *
+ * @return Returns the encoding.
+ *
+ * @deprecated Use {@link #getDefaultCharset()}, will be removed in 2.0.
+ */
+ public String getEncoding() {
+ return this.charset;
+ }
+
+ /**
+ * The default charset used for string decoding and encoding.
+ *
+ * @return the default string charset.
+ */
+ public String getDefaultCharset() {
+ return this.charset;
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/Utils.java b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/Utils.java
new file mode 100644
index 000000000..adfe84513
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/Utils.java
@@ -0,0 +1,50 @@
+// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. 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 org.mozilla.apache.commons.codec.net;
+
+import org.mozilla.apache.commons.codec.DecoderException;
+
+/**
+ * Utility methods for this package.
+ *
+ * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
+ * @version $Id: Utils.java 798611 2009-07-28 17:10:44Z ggregory $
+ * @since 1.4
+ */
+class Utils {
+
+ /**
+ * Returns the numeric value of the character <code>b</code> in radix 16.
+ *
+ * @param b
+ * The byte to be converted.
+ * @return The numeric value represented by the character in radix 16.
+ *
+ * @throws DecoderException
+ * Thrown when the byte is not valid per {@link Character#digit(char,int)}
+ */
+ static int digit16(byte b) throws DecoderException {
+ int i = Character.digit((char) b, 16);
+ if (i == -1) {
+ throw new DecoderException("Invalid URL encoding: not a valid digit (radix " + URLCodec.RADIX + "): " + b);
+ }
+ return i;
+ }
+
+}
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/package.html b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/package.html
new file mode 100644
index 000000000..2b8ceab2e
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/net/package.html
@@ -0,0 +1,23 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. 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.
+-->
+<html>
+ <body>
+ <p>
+ Network related encoding and decoding.
+ </p>
+ </body>
+</html>
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/overview.html b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/overview.html
new file mode 100644
index 000000000..29939dba5
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/overview.html
@@ -0,0 +1,29 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. 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.
+-->
+<!-- $Id: overview.html 561548 2007-07-31 21:16:26Z mbenson $ -->
+<html>
+<body>
+<p>
+This document is the API specification for the Apache Commons Codec Library, version 1.3.
+</p>
+<p>
+This library requires a JRE version of 1.2.2 or greater.
+The hypertext links originating from this document point to Sun's version 1.3 API as the 1.2.2 API documentation
+is no longer on-line.
+</p>
+</body>
+</html>
diff --git a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/package.html b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/package.html
new file mode 100644
index 000000000..da4a3ea52
--- /dev/null
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/package.html
@@ -0,0 +1,100 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements. See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License. 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.
+-->
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ </head>
+ <body>
+ <p>Interfaces and classes used by
+ the various implementations in the sub-packages.</p>
+
+ <p>Definitive implementations of commonly used encoders and decoders.</p>
+
+ <p>Codec is currently comprised of a modest set of utilities and a
+ simple framework for String encoding and decoding in three categories:
+ Binary Encoders, Language Encoders, and Network Encoders. </p>
+
+ <h4><a name="Common Encoders">Binary Encoders</a></h4>
+
+ <table border="1" width="100%" cellspacing="2" cellpadding="3">
+ <tbody>
+ <tr>
+ <td>
+ <a href="binary/Base64.html">
+ org.apache.commons.codec.binary.Base64</a>
+ </td>
+ <td>
+ Provides Base64 content-transfer-encoding as defined in
+ <a href="http://www.ietf.org/rfc/rfc2045.txt"> RFC 2045</a>
+ </td>
+ <td>Production</td>
+ </tr>
+ <tr>
+ <td>
+ <a href="binary/Hex.html">
+ org.apache.commons.codec.binary.Hex</a>
+ </td>
+ <td>
+ Converts an array of bytes into an array of characters
+ representing the hexidecimal values of each byte in order
+ </td>
+ <td>Production</td>
+ </tr>
+ </tbody>
+ </table>
+ <h4>
+ <a name="Language Encoders">Language Encoders</a>
+ </h4>
+ <p>
+ Codec contains a number of commonly used language and phonetic
+ encoders
+ </p>
+ <table border="1" width="100%" cellspacing="2" cellpadding="3">
+ <tbody>
+ <tr>
+ <td>
+ <a href="#">org.apache.commons.codec.language.Soundex</a>
+ </td>
+ <td>Implementation of the Soundex algorithm.</td>
+ <td>Production</td>
+ </tr>
+ <tr>
+ <td>
+ <a href="#">org.apache.commons.codec.language.Metaphone</a>
+ </td>
+ <td>Implementation of the Metaphone algorithm.</td>
+ <td>Production</td>
+ </tr>
+ </tbody>
+ </table>
+ <h4><a name="Network_Encoders">Network Encoders</a></h4>
+ <h4> </h4>
+ <p> Codec contains network related encoders </p>
+ <table border="1" width="100%" cellspacing="2" cellpadding="3">
+ <tbody>
+ <tr>
+ <td>
+ <a href="#">org.apache.commons.codec.net.URLCodec</a>
+ </td>
+ <td>Implements the 'www-form-urlencoded' encoding scheme.</td>
+ <td>Production</td>
+ </tr>
+ </tbody>
+ </table>
+ <br>
+ </body>
+</html>