diff --git a/app/src/main/java/com/monke/monkeybook/ProxyManager.java b/app/src/main/java/com/monke/monkeybook/ProxyManager.java
index ad80c47..87e89dc 100644
--- a/app/src/main/java/com/monke/monkeybook/ProxyManager.java
+++ b/app/src/main/java/com/monke/monkeybook/ProxyManager.java
@@ -2,7 +2,7 @@ package com.monke.monkeybook;
import android.content.SharedPreferences;
-import com.monke.monkeybook.utils.AESUtil;
+import com.monke.monkeybook.utils.aes.AESUtil;
import org.jsoup.helper.StringUtil;
diff --git a/app/src/main/java/com/monke/monkeybook/utils/AESUtil.java b/app/src/main/java/com/monke/monkeybook/utils/AESUtil.java
deleted file mode 100644
index bedc0c8..0000000
--- a/app/src/main/java/com/monke/monkeybook/utils/AESUtil.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package com.monke.monkeybook.utils;
-
-import javax.crypto.*;
-import javax.crypto.spec.SecretKeySpec;
-import java.io.UnsupportedEncodingException;
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
-import java.util.Scanner;
-
-
-public class AESUtil {
-
- public static String aesEncode(String content,String password){
- byte[] result = encrypt(content,password);
- if(result!=null && result.length>0){
- return ParseSystemUtil.parseByte2HexStr(result);
- }
- return null;
- }
-
- public static String aesDecode(String content,String password){
- byte[] temp = ParseSystemUtil.parseHexStr2Byte(content);
- if(temp!=null && temp.length>0){
- byte[] result = decrypt(temp,password);
- if(result!=null && result.length>0){
- return new String(result);
- }
- }
- return null;
- }
-
- /**
- * AES加密字符串
- *
- * @param content
- * 需要被加密的字符串
- * @param keyWord
- * 加密需要的密码
- * @return 密文
- */
- private static byte[] encrypt(String content, String keyWord) {
- try {
- KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
-
- SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
- random.setSeed(keyWord.getBytes());
- kgen.init(128, random);// 利用用户密码作为随机数初始化出
- // 128位的key生产者
- //加密没关系,SecureRandom是生成安全随机数序列,password.getBytes()是种子,只要种子相同,序列就一样,所以解密只要有password就行
-
- SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥
-
- byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥,如果此密钥不支持编码,则返回
- // null。
-
- SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
-
- Cipher cipher = Cipher.getInstance("AES");// 创建密码器
-
- byte[] byteContent = content.getBytes("utf-8");
-
- cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化为加密模式的密码器
-
- byte[] result = cipher.doFinal(byteContent);// 加密
-
- return result;
-
- } catch (NoSuchPaddingException e) {
- e.printStackTrace();
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- } catch (InvalidKeyException e) {
- e.printStackTrace();
- } catch (IllegalBlockSizeException e) {
- e.printStackTrace();
- } catch (BadPaddingException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- /**
- * 解密AES加密过的字符串
- *
- * @param content
- * AES加密过过的内容
- * @param keyWord
- * 加密时的密码
- * @return 明文
- */
- private static byte[] decrypt(byte[] content, String keyWord) {
- try {
- KeyGenerator kgen = KeyGenerator.getInstance("AES");// 创建AES的Key生产者
- SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
- random.setSeed(keyWord.getBytes());
- kgen.init(128, random);
- SecretKey secretKey = kgen.generateKey();// 根据用户密码,生成一个密钥
- byte[] enCodeFormat = secretKey.getEncoded();// 返回基本编码格式的密钥
- SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");// 转换为AES专用密钥
- Cipher cipher = Cipher.getInstance("AES");// 创建密码器
- cipher.init(Cipher.DECRYPT_MODE, key);// 初始化为解密模式的密码器
- byte[] result = cipher.doFinal(content);
- return result; // 明文
-
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- } catch (NoSuchPaddingException e) {
- e.printStackTrace();
- } catch (InvalidKeyException e) {
- e.printStackTrace();
- } catch (IllegalBlockSizeException e) {
- e.printStackTrace();
- } catch (BadPaddingException e) {
- e.printStackTrace();
- }
- return null;
- }
-
- public static void main(String[] args){
- while (true){
- Scanner sn = new Scanner(System.in);
- String content = sn.next();
-// System.out.println(aesDecode(content,ServerConfig.AES_ENCODE_KEY));
- System.out.println();
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/utils/aes/AESUtil.java b/app/src/main/java/com/monke/monkeybook/utils/aes/AESUtil.java
new file mode 100644
index 0000000..9195c1b
--- /dev/null
+++ b/app/src/main/java/com/monke/monkeybook/utils/aes/AESUtil.java
@@ -0,0 +1,47 @@
+package com.monke.monkeybook.utils.aes;
+
+import com.monke.monkeybook.utils.ParseSystemUtil;
+
+import javax.crypto.*;
+import javax.crypto.spec.SecretKeySpec;
+
+import java.io.UnsupportedEncodingException;
+
+public class AESUtil {
+ public static String aesEncode(String cleartext, String seed) throws Exception {
+ byte[] rawKey = deriveKeyInsecurely(seed, 32).getEncoded();
+ byte[] result = encrypt(rawKey, cleartext.getBytes());
+ return ParseSystemUtil.parseByte2HexStr(result);
+ }
+
+ public static String aesDecode(String encrypted, String seed) throws Exception {
+ byte[] rawKey = deriveKeyInsecurely(seed, 32).getEncoded();
+ byte[] enc = ParseSystemUtil.parseHexStr2Byte(encrypted);
+ byte[] result = decrypt(rawKey, enc);
+ return new String(result);
+ }
+
+ private static SecretKey deriveKeyInsecurely(String password, int keySizeInBytes) throws UnsupportedEncodingException {
+ byte[] passwordBytes = password.getBytes("UTF-8");
+ return new SecretKeySpec(
+ InsecureSHA1PRNGKeyDerivator.deriveInsecureKey(
+ passwordBytes, keySizeInBytes),
+ "AES");
+ }
+
+ private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
+ SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+ Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+ cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
+ byte[] encrypted = cipher.doFinal(clear);
+ return encrypted;
+ }
+
+ private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
+ SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+ Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+ cipher.init(Cipher.DECRYPT_MODE, skeySpec);
+ byte[] decrypted = cipher.doFinal(encrypted);
+ return decrypted;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/utils/aes/InsecureSHA1PRNGKeyDerivator.java b/app/src/main/java/com/monke/monkeybook/utils/aes/InsecureSHA1PRNGKeyDerivator.java
new file mode 100644
index 0000000..3d55d6c
--- /dev/null
+++ b/app/src/main/java/com/monke/monkeybook/utils/aes/InsecureSHA1PRNGKeyDerivator.java
@@ -0,0 +1,609 @@
+/*
+ * 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 com.monke.monkeybook.utils.aes;
+
+/**
+ * Stripped-down version of the SHA1PRNG provided by the Crypto provider.
+ *
+ * The Crypto provider that offers this functionality was deprecated on Android.
+ *
+ * Use this class only to retrieve encrypted data that couldn't be retrieved otherwise.
+ */
+class InsecureSHA1PRNGKeyDerivator {
+
+ /**
+ * Only public method. Derive a key from the given seed.
+ *
+ * Use this method only to retrieve encrypted data that couldn't be retrieved otherwise.
+ *
+ * @param seed seed used for the random generator, usually coming from a password
+ * @param keySizeInBytes length of the array returned
+ */
+ public static byte[] deriveInsecureKey(byte[] seed, int keySizeInBytes) {
+ InsecureSHA1PRNGKeyDerivator derivator = new InsecureSHA1PRNGKeyDerivator();
+ derivator.setSeed(seed);
+ byte[] key = new byte[keySizeInBytes];
+ derivator.nextBytes(key);
+ return key;
+ }
+
+ // constants to use in expressions operating on bytes in int and long variables:
+ // END_FLAGS - final bytes in words to append to message;
+ // see "ch.5.1 Padding the Message, FIPS 180-2"
+ // RIGHT1 - shifts to right for left half of long
+ // RIGHT2 - shifts to right for right half of long
+ // LEFT - shifts to left for bytes
+ // MASK - mask to select counter's bytes after shift to right
+
+ private static final int[] END_FLAGS = { 0x80000000, 0x800000, 0x8000, 0x80 };
+
+ private static final int[] RIGHT1 = { 0, 40, 48, 56 };
+
+ private static final int[] RIGHT2 = { 0, 8, 16, 24 };
+
+ private static final int[] LEFT = { 0, 24, 16, 8 };
+
+ private static final int[] MASK = { 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF,
+ 0x000000FF };
+
+ // HASHBYTES_TO_USE defines # of bytes returned by "computeHash(byte[])"
+ // to use to form byte array returning by the "nextBytes(byte[])" method
+ // Note, that this implementation uses more bytes than it is defined
+ // in the above specification.
+ private static final int HASHBYTES_TO_USE = 20;
+
+ // value of 16 defined in the "SECURE HASH STANDARD", FIPS PUB 180-2
+ private static final int FRAME_LENGTH = 16;
+
+ // miscellaneous constants defined in this implementation:
+ // COUNTER_BASE - initial value to set to "counter" before computing "nextBytes(..)";
+ // note, that the exact value is not defined in STANDARD
+ // HASHCOPY_OFFSET - offset for copy of current hash in "copies" array
+ // EXTRAFRAME_OFFSET - offset for extra frame in "copies" array;
+ // as the extra frame follows the current hash frame,
+ // EXTRAFRAME_OFFSET is equal to length of current hash frame
+ // FRAME_OFFSET - offset for frame in "copies" array
+ // MAX_BYTES - maximum # of seed bytes processing which doesn't require extra frame
+ // see (1) comments on usage of "seed" array below and
+ // (2) comments in "engineNextBytes(byte[])" method
+ //
+ // UNDEFINED - three states of engine; initially its state is "UNDEFINED"
+ // SET_SEED call to "engineSetSeed" sets up "SET_SEED" state,
+ // NEXT_BYTES call to "engineNextByte" sets up "NEXT_BYTES" state
+
+ private static final int COUNTER_BASE = 0;
+
+ private static final int HASHCOPY_OFFSET = 0;
+
+ private static final int EXTRAFRAME_OFFSET = 5;
+
+ private static final int FRAME_OFFSET = 21;
+
+ private static final int MAX_BYTES = 48;
+
+ private static final int UNDEFINED = 0;
+
+ private static final int SET_SEED = 1;
+
+ private static final int NEXT_BYTES = 2;
+
+ // Structure of "seed" array:
+ // - 0-79 - words for computing hash
+ // - 80 - unused
+ // - 81 - # of seed bytes in current seed frame
+ // - 82-86 - 5 words, current seed hash
+ private transient int[] seed;
+
+ // total length of seed bytes, including all processed
+ private transient long seedLength;
+
+ // Structure of "copies" array
+ // - 0-4 - 5 words, copy of current seed hash
+ // - 5-20 - extra 16 words frame;
+ // is used if final padding exceeds 512-bit length
+ // - 21-36 - 16 word frame to store a copy of remaining bytes
+ private transient int[] copies;
+
+ // ready "next" bytes; needed because words are returned
+ private transient byte[] nextBytes;
+
+ // index of used bytes in "nextBytes" array
+ private transient int nextBIndex;
+
+ // variable required according to "SECURE HASH STANDARD"
+ private transient long counter;
+
+ // contains int value corresponding to engine's current state
+ private transient int state;
+
+ /**
+ * constant defined in "SECURE HASH STANDARD"
+ */
+ private static final int H0 = 0x67452301;
+
+
+ /**
+ * constant defined in "SECURE HASH STANDARD"
+ */
+ private static final int H1 = 0xEFCDAB89;
+
+
+ /**
+ * constant defined in "SECURE HASH STANDARD"
+ */
+ private static final int H2 = 0x98BADCFE;
+
+
+ /**
+ * constant defined in "SECURE HASH STANDARD"
+ */
+ private static final int H3 = 0x10325476;
+
+
+ /**
+ * constant defined in "SECURE HASH STANDARD"
+ */
+ private static final int H4 = 0xC3D2E1F0;
+
+
+ /**
+ * offset in buffer to store number of bytes in 0-15 word frame
+ */
+ private static final int BYTES_OFFSET = 81;
+
+
+ /**
+ * offset in buffer to store current hash value
+ */
+ private static final int HASH_OFFSET = 82;
+
+
+ /**
+ * # of bytes in H0-H4 words;
+ * in this implementation # is set to 20 (in general # varies from 1 to 20)
+ */
+ private static final int DIGEST_LENGTH = 20;
+
+ // The "seed" array is used to compute both "current seed hash" and "next bytes".
+ //
+ // As the "SHA1" algorithm computes a hash of entire seed by splitting it into
+ // a number of the 512-bit length frames (512 bits = 64 bytes = 16 words),
+ // "current seed hash" is a hash (5 words, 20 bytes) for all previous full frames;
+ // remaining bytes are stored in the 0-15 word frame of the "seed" array.
+ //
+ // As for calculating "next bytes",
+ // both remaining bytes and "current seed hash" are used,
+ // to preserve the latter for following "setSeed(..)" commands,
+ // the following technique is used:
+ // - upon getting "nextBytes(byte[])" invoked, single or first in row,
+ // which requires computing new hash, that is,
+ // there is no more bytes remaining from previous "next bytes" computation,
+ // remaining bytes are copied into the 21-36 word frame of the "copies" array;
+ // - upon getting "setSeed(byte[])" invoked, single or first in row,
+ // remaining bytes are copied back.
+
+ private InsecureSHA1PRNGKeyDerivator() {
+ seed = new int[HASH_OFFSET + EXTRAFRAME_OFFSET];
+ seed[HASH_OFFSET] = H0;
+ seed[HASH_OFFSET + 1] = H1;
+ seed[HASH_OFFSET + 2] = H2;
+ seed[HASH_OFFSET + 3] = H3;
+ seed[HASH_OFFSET + 4] = H4;
+
+ seedLength = 0;
+ copies = new int[2 * FRAME_LENGTH + EXTRAFRAME_OFFSET];
+ nextBytes = new byte[DIGEST_LENGTH];
+ nextBIndex = HASHBYTES_TO_USE;
+ counter = COUNTER_BASE;
+ state = UNDEFINED;
+ }
+
+ /*
+ * The method invokes the SHA1Impl's "updateHash(..)" method
+ * to update current seed frame and
+ * to compute new intermediate hash value if the frame is full.
+ *
+ * After that it computes a length of whole seed.
+ */
+ private void updateSeed(byte[] bytes) {
+
+ // on call: "seed" contains current bytes and current hash;
+ // on return: "seed" contains new current bytes and possibly new current hash
+ // if after adding, seed bytes overfill its buffer
+ updateHash(seed, bytes, 0, bytes.length - 1);
+
+ seedLength += bytes.length;
+ }
+
+ /**
+ * Changes current seed by supplementing a seed argument to the current seed,
+ * if this already set;
+ * the argument is used as first seed otherwise.
+ *
+ * The method overrides "engineSetSeed(byte[])" in class SecureRandomSpi.
+ *
+ * @param
+ * seed - byte array
+ * @throws
+ * NullPointerException - if null is passed to the "seed" argument
+ */
+ private void setSeed(byte[] seed) {
+ if (seed == null) {
+ throw new NullPointerException("seed == null");
+ }
+
+ if (state == NEXT_BYTES) { // first setSeed after NextBytes; restoring hash
+ System.arraycopy(copies, HASHCOPY_OFFSET, this.seed, HASH_OFFSET,
+ EXTRAFRAME_OFFSET);
+ }
+ state = SET_SEED;
+
+ if (seed.length != 0) {
+ updateSeed(seed);
+ }
+ }
+
+ /**
+ * Writes random bytes into an array supplied.
+ * Bits in a byte are from left to right.
+ *
+ * To generate random bytes, the "expansion of source bits" method is used,
+ * that is,
+ * the current seed with a 64-bit counter appended is used to compute new bits.
+ * The counter is incremented by 1 for each 20-byte output.
+ *
+ * The method overrides engineNextBytes in class SecureRandomSpi.
+ *
+ * @param
+ * bytes - byte array to be filled in with bytes
+ * @throws
+ * NullPointerException - if null is passed to the "bytes" argument
+ */
+ protected synchronized void nextBytes(byte[] bytes) {
+
+ int i, n;
+
+ long bits; // number of bits required by Secure Hash Standard
+ int nextByteToReturn; // index of ready bytes in "bytes" array
+ int lastWord; // index of last word in frame containing bytes
+
+ // This is a bug since words are 4 bytes. Android used to keep it this way for backward
+ // compatibility.
+ final int extrabytes = 7;// # of bytes to add in order to computer # of 8 byte words
+
+ if (bytes == null) {
+ throw new NullPointerException("bytes == null");
+ }
+
+ // This is a bug since extraBytes == 7 instead of 3. Android used to keep it this way for
+ // backward compatibility.
+ lastWord = seed[BYTES_OFFSET] == 0 ? 0
+ : (seed[BYTES_OFFSET] + extrabytes) >> 3 - 1;
+
+ if (state == UNDEFINED) {
+
+ throw new IllegalStateException("No seed supplied!");
+
+ } else if (state == SET_SEED) {
+
+ System.arraycopy(seed, HASH_OFFSET, copies, HASHCOPY_OFFSET,
+ EXTRAFRAME_OFFSET);
+
+ // possible cases for 64-byte frame:
+ //
+ // seed bytes < 48 - remaining bytes are enough for all, 8 counter bytes,
+ // 0x80, and 8 seedLength bytes; no extra frame required
+ // 48 < seed bytes < 56 - remaining 9 bytes are for 0x80 and 8 counter bytes
+ // extra frame contains only seedLength value at the end
+ // seed bytes > 55 - extra frame contains both counter's bytes
+ // at the beginning and seedLength value at the end;
+ // note, that beginning extra bytes are not more than 8,
+ // that is, only 2 extra words may be used
+
+ // no need to set to "0" 3 words after "lastWord" and
+ // more than two words behind frame
+ for (i = lastWord + 3; i < FRAME_LENGTH + 2; i++) {
+ seed[i] = 0;
+ }
+
+ bits = (seedLength << 3) + 64; // transforming # of bytes into # of bits
+
+ // putting # of bits into two last words (14,15) of 16 word frame in
+ // seed or copies array depending on total length after padding
+ if (seed[BYTES_OFFSET] < MAX_BYTES) {
+ seed[14] = (int) (bits >>> 32);
+ seed[15] = (int) (bits & 0xFFFFFFFF);
+ } else {
+ copies[EXTRAFRAME_OFFSET + 14] = (int) (bits >>> 32);
+ copies[EXTRAFRAME_OFFSET + 15] = (int) (bits & 0xFFFFFFFF);
+ }
+
+ nextBIndex = HASHBYTES_TO_USE; // skipping remaining random bits
+ }
+ state = NEXT_BYTES;
+
+ if (bytes.length == 0) {
+ return;
+ }
+
+ nextByteToReturn = 0;
+
+ // possibly not all of HASHBYTES_TO_USE bytes were used previous time
+ n = (HASHBYTES_TO_USE - nextBIndex) < (bytes.length - nextByteToReturn) ? HASHBYTES_TO_USE
+ - nextBIndex
+ : bytes.length - nextByteToReturn;
+ if (n > 0) {
+ System.arraycopy(nextBytes, nextBIndex, bytes, nextByteToReturn, n);
+ nextBIndex += n;
+ nextByteToReturn += n;
+ }
+
+ if (nextByteToReturn >= bytes.length) {
+ return; // return because "bytes[]" are filled in
+ }
+
+ n = seed[BYTES_OFFSET] & 0x03;
+ for (;;) {
+ if (n == 0) {
+
+ seed[lastWord] = (int) (counter >>> 32);
+ seed[lastWord + 1] = (int) (counter & 0xFFFFFFFF);
+ seed[lastWord + 2] = END_FLAGS[0];
+
+ } else {
+
+ seed[lastWord] |= (int) ((counter >>> RIGHT1[n]) & MASK[n]);
+ seed[lastWord + 1] = (int) ((counter >>> RIGHT2[n]) & 0xFFFFFFFF);
+ seed[lastWord + 2] = (int) ((counter << LEFT[n]) | END_FLAGS[n]);
+ }
+ if (seed[BYTES_OFFSET] > MAX_BYTES) {
+ copies[EXTRAFRAME_OFFSET] = seed[FRAME_LENGTH];
+ copies[EXTRAFRAME_OFFSET + 1] = seed[FRAME_LENGTH + 1];
+ }
+
+ computeHash(seed);
+
+ if (seed[BYTES_OFFSET] > MAX_BYTES) {
+
+ System.arraycopy(seed, 0, copies, FRAME_OFFSET, FRAME_LENGTH);
+ System.arraycopy(copies, EXTRAFRAME_OFFSET, seed, 0,
+ FRAME_LENGTH);
+
+ computeHash(seed);
+ System.arraycopy(copies, FRAME_OFFSET, seed, 0, FRAME_LENGTH);
+ }
+ counter++;
+
+ int j = 0;
+ for (i = 0; i < EXTRAFRAME_OFFSET; i++) {
+ int k = seed[HASH_OFFSET + i];
+ nextBytes[j] = (byte) (k >>> 24); // getting first byte from left
+ nextBytes[j + 1] = (byte) (k >>> 16); // getting second byte from left
+ nextBytes[j + 2] = (byte) (k >>> 8); // getting third byte from left
+ nextBytes[j + 3] = (byte) (k); // getting fourth byte from left
+ j += 4;
+ }
+
+ nextBIndex = 0;
+ j = HASHBYTES_TO_USE < (bytes.length - nextByteToReturn) ? HASHBYTES_TO_USE
+ : bytes.length - nextByteToReturn;
+
+ if (j > 0) {
+ System.arraycopy(nextBytes, 0, bytes, nextByteToReturn, j);
+ nextByteToReturn += j;
+ nextBIndex += j;
+ }
+
+ if (nextByteToReturn >= bytes.length) {
+ break;
+ }
+ }
+ }
+
+ /**
+ * The method generates a 160 bit hash value using
+ * a 512 bit message stored in first 16 words of int[] array argument and
+ * current hash value stored in five words, beginning OFFSET+1, of the array argument.
+ * Computation is done according to SHA-1 algorithm.
+ *
+ * The resulting hash value replaces the previous hash value in the array;
+ * original bits of the message are not preserved.
+ *
+ * No checks on argument supplied, that is,
+ * a calling method is responsible for such checks.
+ * In case of incorrect array passed to the method
+ * either NPE or IndexOutOfBoundException gets thrown by JVM.
+ *
+ * @params
+ * arrW - integer array; arrW.length >= (BYTES_OFFSET+6);
+ * only first (BYTES_OFFSET+6) words are used
+ */
+ private static void computeHash(int[] arrW) {
+
+ int a = arrW[HASH_OFFSET ];
+ int b = arrW[HASH_OFFSET +1];
+ int c = arrW[HASH_OFFSET +2];
+ int d = arrW[HASH_OFFSET +3];
+ int e = arrW[HASH_OFFSET +4];
+
+ int temp;
+
+ // In this implementation the "d. For t = 0 to 79 do" loop
+ // is split into four loops. The following constants:
+ // K = 5A827999 0 <= t <= 19
+ // K = 6ED9EBA1 20 <= t <= 39
+ // K = 8F1BBCDC 40 <= t <= 59
+ // K = CA62C1D6 60 <= t <= 79
+ // are hex literals in the loops.
+
+ for ( int t = 16; t < 80 ; t++ ) {
+
+ temp = arrW[t-3] ^ arrW[t-8] ^ arrW[t-14] ^ arrW[t-16];
+ arrW[t] = ( temp<<1 ) | ( temp>>>31 );
+ }
+
+ for ( int t = 0 ; t < 20 ; t++ ) {
+
+ temp = ( ( a<<5 ) | ( a>>>27 ) ) +
+ ( ( b & c) | ((~b) & d) ) +
+ ( e + arrW[t] + 0x5A827999 ) ;
+ e = d;
+ d = c;
+ c = ( b<<30 ) | ( b>>>2 ) ;
+ b = a;
+ a = temp;
+ }
+ for ( int t = 20 ; t < 40 ; t++ ) {
+
+ temp = ((( a<<5 ) | ( a>>>27 ))) + (b ^ c ^ d) + (e + arrW[t] + 0x6ED9EBA1) ;
+ e = d;
+ d = c;
+ c = ( b<<30 ) | ( b>>>2 ) ;
+ b = a;
+ a = temp;
+ }
+ for ( int t = 40 ; t < 60 ; t++ ) {
+
+ temp = (( a<<5 ) | ( a>>>27 )) + ((b & c) | (b & d) | (c & d)) +
+ (e + arrW[t] + 0x8F1BBCDC) ;
+ e = d;
+ d = c;
+ c = ( b<<30 ) | ( b>>>2 ) ;
+ b = a;
+ a = temp;
+ }
+ for ( int t = 60 ; t < 80 ; t++ ) {
+
+ temp = ((( a<<5 ) | ( a>>>27 ))) + (b ^ c ^ d) + (e + arrW[t] + 0xCA62C1D6) ;
+ e = d;
+ d = c;
+ c = ( b<<30 ) | ( b>>>2 ) ;
+ b = a;
+ a = temp;
+ }
+
+ arrW[HASH_OFFSET ] += a;
+ arrW[HASH_OFFSET +1] += b;
+ arrW[HASH_OFFSET +2] += c;
+ arrW[HASH_OFFSET +3] += d;
+ arrW[HASH_OFFSET +4] += e;
+ }
+
+ /**
+ * The method appends new bytes to existing ones
+ * within limit of a frame of 64 bytes (16 words).
+ *
+ * Once a length of accumulated bytes reaches the limit
+ * the "computeHash(int[])" method is invoked on the array to compute updated hash,
+ * and the number of bytes in the frame is set to 0.
+ * Thus, after appending all bytes, the array contain only those bytes
+ * that were not used in computing final hash value yet.
+ *
+ * No checks on arguments passed to the method, that is,
+ * a calling method is responsible for such checks.
+ *
+ * @params
+ * intArray - int array containing bytes to which to append;
+ * intArray.length >= (BYTES_OFFSET+6)
+ * @params
+ * byteInput - array of bytes to use for the update
+ * @params
+ * from - the offset to start in the "byteInput" array
+ * @params
+ * to - a number of the last byte in the input array to use,
+ * that is, for first byte "to"==0, for last byte "to"==input.length-1
+ */
+ private static void updateHash(int[] intArray, byte[] byteInput, int fromByte, int toByte) {
+
+ // As intArray contains a packed bytes
+ // the buffer's index is in the intArray[BYTES_OFFSET] element
+
+ int index = intArray[BYTES_OFFSET];
+ int i = fromByte;
+ int maxWord;
+ int nBytes;
+
+ int wordIndex = index >>2;
+ int byteIndex = index & 0x03;
+
+ intArray[BYTES_OFFSET] = ( index + toByte - fromByte + 1 ) & 077 ;
+
+ // In general case there are 3 stages :
+ // - appending bytes to non-full word,
+ // - writing 4 bytes into empty words,
+ // - writing less than 4 bytes in last word
+
+ if ( byteIndex != 0 ) { // appending bytes in non-full word (as if)
+
+ for ( ; ( i <= toByte ) && ( byteIndex < 4 ) ; i++ ) {
+ intArray[wordIndex] |= ( byteInput[i] & 0xFF ) << ((3 - byteIndex)<<3) ;
+ byteIndex++;
+ }
+ if ( byteIndex == 4 ) {
+ wordIndex++;
+ if ( wordIndex == 16 ) { // intArray is full, computing hash
+
+ computeHash(intArray);
+ wordIndex = 0;
+ }
+ }
+ if ( i > toByte ) { // all input bytes appended
+ return ;
+ }
+ }
+
+ // writing full words
+
+ maxWord = (toByte - i + 1) >> 2; // # of remaining full words, may be "0"
+ for ( int k = 0; k < maxWord ; k++ ) {
+
+ intArray[wordIndex] = ( ((int) byteInput[i ] & 0xFF) <<24 ) |
+ ( ((int) byteInput[i +1] & 0xFF) <<16 ) |
+ ( ((int) byteInput[i +2] & 0xFF) <<8 ) |
+ ( ((int) byteInput[i +3] & 0xFF) ) ;
+ i += 4;
+ wordIndex++;
+
+ if ( wordIndex < 16 ) { // buffer is not full yet
+ continue;
+ }
+ computeHash(intArray); // buffer is full, computing hash
+ wordIndex = 0;
+ }
+
+ // writing last incomplete word
+ // after writing free byte positions are set to "0"s
+
+ nBytes = toByte - i +1;
+ if ( nBytes != 0 ) {
+
+ int w = ((int) byteInput[i] & 0xFF) <<24 ;
+
+ if ( nBytes != 1 ) {
+ w |= ((int) byteInput[i +1] & 0xFF) <<16 ;
+ if ( nBytes != 2) {
+ w |= ((int) byteInput[i +2] & 0xFF) <<8 ;
+ }
+ }
+ intArray[wordIndex] = w;
+ }
+
+ return ;
+ }
+}
diff --git a/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Decoder.java b/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Decoder.java
new file mode 100644
index 0000000..49c99c2
--- /dev/null
+++ b/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Decoder.java
@@ -0,0 +1,91 @@
+package com.monke.monkeybook.utils.base64;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PushbackInputStream;
+
+public class BASE64Decoder extends CharacterDecoder{
+ private static final char[] pem_array = new char[]{'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', '+', '/'};
+ private static final byte[] pem_convert_array = new byte[256];
+ byte[] decode_buffer = new byte[4];
+
+ public BASE64Decoder() {
+ }
+
+ protected int bytesPerAtom() {
+ return 4;
+ }
+
+ protected int bytesPerLine() {
+ return 72;
+ }
+
+ protected void decodeAtom(PushbackInputStream var1, OutputStream var2, int var3) throws IOException {
+ byte var5 = -1;
+ byte var6 = -1;
+ byte var7 = -1;
+ byte var8 = -1;
+ if (var3 < 2) {
+ throw new CEFormatException("BASE64Decoder: Not enough bytes for an atom.");
+ } else {
+ int var4;
+ do {
+ var4 = var1.read();
+ if (var4 == -1) {
+ throw new CEStreamExhausted();
+ }
+ } while(var4 == 10 || var4 == 13);
+
+ this.decode_buffer[0] = (byte)var4;
+ var4 = this.readFully(var1, this.decode_buffer, 1, var3 - 1);
+ if (var4 == -1) {
+ throw new CEStreamExhausted();
+ } else {
+ if (var3 > 3 && this.decode_buffer[3] == 61) {
+ var3 = 3;
+ }
+
+ if (var3 > 2 && this.decode_buffer[2] == 61) {
+ var3 = 2;
+ }
+
+ switch(var3) {
+ case 4:
+ var8 = pem_convert_array[this.decode_buffer[3] & 255];
+ case 3:
+ var7 = pem_convert_array[this.decode_buffer[2] & 255];
+ case 2:
+ var6 = pem_convert_array[this.decode_buffer[1] & 255];
+ var5 = pem_convert_array[this.decode_buffer[0] & 255];
+ default:
+ switch(var3) {
+ case 2:
+ var2.write((byte)(var5 << 2 & 252 | var6 >>> 4 & 3));
+ break;
+ case 3:
+ var2.write((byte)(var5 << 2 & 252 | var6 >>> 4 & 3));
+ var2.write((byte)(var6 << 4 & 240 | var7 >>> 2 & 15));
+ break;
+ case 4:
+ var2.write((byte)(var5 << 2 & 252 | var6 >>> 4 & 3));
+ var2.write((byte)(var6 << 4 & 240 | var7 >>> 2 & 15));
+ var2.write((byte)(var7 << 6 & 192 | var8 & 63));
+ }
+
+ }
+ }
+ }
+ }
+
+ static {
+ int var0;
+ for(var0 = 0; var0 < 255; ++var0) {
+ pem_convert_array[var0] = -1;
+ }
+
+ for(var0 = 0; var0 < pem_array.length; ++var0) {
+ pem_convert_array[pem_array[var0]] = (byte)var0;
+ }
+
+ }
+}
diff --git a/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Encoder.java b/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Encoder.java
new file mode 100644
index 0000000..4c5fe1d
--- /dev/null
+++ b/app/src/main/java/com/monke/monkeybook/utils/base64/BASE64Encoder.java
@@ -0,0 +1,52 @@
+package com.monke.monkeybook.utils.base64;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class BASE64Encoder extends CharacterEncoder{
+ private static final char[] pem_array = new char[]{'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', '+', '/'};
+
+ public BASE64Encoder() {
+ }
+
+ protected int bytesPerAtom() {
+ return 3;
+ }
+
+ protected int bytesPerLine() {
+ return 57;
+ }
+
+ protected void encodeAtom(OutputStream var1, byte[] var2, int var3, int var4) throws IOException {
+ byte var5;
+ if (var4 == 1) {
+ var5 = var2[var3];
+ byte var6 = 0;
+ boolean var7 = false;
+ var1.write(pem_array[var5 >>> 2 & 63]);
+ var1.write(pem_array[(var5 << 4 & 48) + (var6 >>> 4 & 15)]);
+ var1.write(61);
+ var1.write(61);
+ } else {
+ byte var8;
+ if (var4 == 2) {
+ var5 = var2[var3];
+ var8 = var2[var3 + 1];
+ byte var9 = 0;
+ var1.write(pem_array[var5 >>> 2 & 63]);
+ var1.write(pem_array[(var5 << 4 & 48) + (var8 >>> 4 & 15)]);
+ var1.write(pem_array[(var8 << 2 & 60) + (var9 >>> 6 & 3)]);
+ var1.write(61);
+ } else {
+ var5 = var2[var3];
+ var8 = var2[var3 + 1];
+ byte var10 = var2[var3 + 2];
+ var1.write(pem_array[var5 >>> 2 & 63]);
+ var1.write(pem_array[(var5 << 4 & 48) + (var8 >>> 4 & 15)]);
+ var1.write(pem_array[(var8 << 2 & 60) + (var10 >>> 6 & 3)]);
+ var1.write(pem_array[var10 & 63]);
+ }
+ }
+
+ }
+}
diff --git a/app/src/main/java/com/monke/monkeybook/utils/base64/CEFormatException.java b/app/src/main/java/com/monke/monkeybook/utils/base64/CEFormatException.java
new file mode 100644
index 0000000..fc6450b
--- /dev/null
+++ b/app/src/main/java/com/monke/monkeybook/utils/base64/CEFormatException.java
@@ -0,0 +1,11 @@
+package com.monke.monkeybook.utils.base64;
+
+import java.io.IOException;
+
+public class CEFormatException extends IOException {
+ static final long serialVersionUID = -7139121221067081482L;
+
+ public CEFormatException(String var1) {
+ super(var1);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/utils/base64/CEStreamExhausted.java b/app/src/main/java/com/monke/monkeybook/utils/base64/CEStreamExhausted.java
new file mode 100644
index 0000000..51e1f26
--- /dev/null
+++ b/app/src/main/java/com/monke/monkeybook/utils/base64/CEStreamExhausted.java
@@ -0,0 +1,10 @@
+package com.monke.monkeybook.utils.base64;
+
+import java.io.IOException;
+
+public class CEStreamExhausted extends IOException {
+ static final long serialVersionUID = -5889118049525891904L;
+
+ public CEStreamExhausted() {
+ }
+}
diff --git a/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterDecoder.java b/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterDecoder.java
new file mode 100644
index 0000000..21f6864
--- /dev/null
+++ b/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterDecoder.java
@@ -0,0 +1,102 @@
+package com.monke.monkeybook.utils.base64;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PushbackInputStream;
+import java.nio.ByteBuffer;
+
+public abstract class CharacterDecoder {
+ public CharacterDecoder() {
+ }
+
+ protected abstract int bytesPerAtom();
+
+ protected abstract int bytesPerLine();
+
+ protected void decodeBufferPrefix(PushbackInputStream var1, OutputStream var2) throws IOException {
+ }
+
+ protected void decodeBufferSuffix(PushbackInputStream var1, OutputStream var2) throws IOException {
+ }
+
+ protected int decodeLinePrefix(PushbackInputStream var1, OutputStream var2) throws IOException {
+ return this.bytesPerLine();
+ }
+
+ protected void decodeLineSuffix(PushbackInputStream var1, OutputStream var2) throws IOException {
+ }
+
+ protected void decodeAtom(PushbackInputStream var1, OutputStream var2, int var3) throws IOException {
+ throw new CEStreamExhausted();
+ }
+
+ protected int readFully(InputStream var1, byte[] var2, int var3, int var4) throws IOException {
+ for(int var5 = 0; var5 < var4; ++var5) {
+ int var6 = var1.read();
+ if (var6 == -1) {
+ return var5 == 0 ? -1 : var5;
+ }
+
+ var2[var5 + var3] = (byte)var6;
+ }
+
+ return var4;
+ }
+
+ public void decodeBuffer(InputStream var1, OutputStream var2) throws IOException {
+ int var4 = 0;
+ PushbackInputStream var5 = new PushbackInputStream(var1);
+ this.decodeBufferPrefix(var5, var2);
+
+ while(true) {
+ try {
+ int var6 = this.decodeLinePrefix(var5, var2);
+
+ int var3;
+ for(var3 = 0; var3 + this.bytesPerAtom() < var6; var3 += this.bytesPerAtom()) {
+ this.decodeAtom(var5, var2, this.bytesPerAtom());
+ var4 += this.bytesPerAtom();
+ }
+
+ if (var3 + this.bytesPerAtom() == var6) {
+ this.decodeAtom(var5, var2, this.bytesPerAtom());
+ var4 += this.bytesPerAtom();
+ } else {
+ this.decodeAtom(var5, var2, var6 - var3);
+ var4 += var6 - var3;
+ }
+
+ this.decodeLineSuffix(var5, var2);
+ } catch (CEStreamExhausted var8) {
+ this.decodeBufferSuffix(var5, var2);
+ return;
+ }
+ }
+ }
+
+ public byte[] decodeBuffer(String var1) throws IOException {
+ byte[] var2 = new byte[var1.length()];
+ var1.getBytes(0, var1.length(), var2, 0);
+ ByteArrayInputStream var3 = new ByteArrayInputStream(var2);
+ ByteArrayOutputStream var4 = new ByteArrayOutputStream();
+ this.decodeBuffer(var3, var4);
+ return var4.toByteArray();
+ }
+
+ public byte[] decodeBuffer(InputStream var1) throws IOException {
+ ByteArrayOutputStream var2 = new ByteArrayOutputStream();
+ this.decodeBuffer(var1, var2);
+ return var2.toByteArray();
+ }
+
+ public ByteBuffer decodeBufferToByteBuffer(String var1) throws IOException {
+ return ByteBuffer.wrap(this.decodeBuffer(var1));
+ }
+
+ public ByteBuffer decodeBufferToByteBuffer(InputStream var1) throws IOException {
+ return ByteBuffer.wrap(this.decodeBuffer(var1));
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterEncoder.java b/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterEncoder.java
new file mode 100644
index 0000000..1184f5b
--- /dev/null
+++ b/app/src/main/java/com/monke/monkeybook/utils/base64/CharacterEncoder.java
@@ -0,0 +1,181 @@
+package com.monke.monkeybook.utils.base64;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.nio.ByteBuffer;
+
+public abstract class CharacterEncoder {
+ protected PrintStream pStream;
+
+ public CharacterEncoder() {
+ }
+
+ protected abstract int bytesPerAtom();
+
+ protected abstract int bytesPerLine();
+
+ protected void encodeBufferPrefix(OutputStream var1) throws IOException {
+ this.pStream = new PrintStream(var1);
+ }
+
+ protected void encodeBufferSuffix(OutputStream var1) throws IOException {
+ }
+
+ protected void encodeLinePrefix(OutputStream var1, int var2) throws IOException {
+ }
+
+ protected void encodeLineSuffix(OutputStream var1) throws IOException {
+ this.pStream.println();
+ }
+
+ protected abstract void encodeAtom(OutputStream var1, byte[] var2, int var3, int var4) throws IOException;
+
+ protected int readFully(InputStream var1, byte[] var2) throws IOException {
+ for(int var3 = 0; var3 < var2.length; ++var3) {
+ int var4 = var1.read();
+ if (var4 == -1) {
+ return var3;
+ }
+
+ var2[var3] = (byte)var4;
+ }
+
+ return var2.length;
+ }
+
+ public void encode(InputStream var1, OutputStream var2) throws IOException {
+ byte[] var5 = new byte[this.bytesPerLine()];
+ this.encodeBufferPrefix(var2);
+
+ while(true) {
+ int var4 = this.readFully(var1, var5);
+ if (var4 == 0) {
+ break;
+ }
+
+ this.encodeLinePrefix(var2, var4);
+
+ for(int var3 = 0; var3 < var4; var3 += this.bytesPerAtom()) {
+ if (var3 + this.bytesPerAtom() <= var4) {
+ this.encodeAtom(var2, var5, var3, this.bytesPerAtom());
+ } else {
+ this.encodeAtom(var2, var5, var3, var4 - var3);
+ }
+ }
+
+ if (var4 < this.bytesPerLine()) {
+ break;
+ }
+
+ this.encodeLineSuffix(var2);
+ }
+
+ this.encodeBufferSuffix(var2);
+ }
+
+ public void encode(byte[] var1, OutputStream var2) throws IOException {
+ ByteArrayInputStream var3 = new ByteArrayInputStream(var1);
+ this.encode((InputStream)var3, var2);
+ }
+
+ public String encode(byte[] var1) {
+ ByteArrayOutputStream var2 = new ByteArrayOutputStream();
+ ByteArrayInputStream var3 = new ByteArrayInputStream(var1);
+ String var4 = null;
+
+ try {
+ this.encode((InputStream)var3, var2);
+ var4 = var2.toString("8859_1");
+ return var4;
+ } catch (Exception var6) {
+ throw new Error("CharacterEncoder.encode internal error");
+ }
+ }
+
+ private byte[] getBytes(ByteBuffer var1) {
+ byte[] var2 = null;
+ if (var1.hasArray()) {
+ byte[] var3 = var1.array();
+ if (var3.length == var1.capacity() && var3.length == var1.remaining()) {
+ var2 = var3;
+ var1.position(var1.limit());
+ }
+ }
+
+ if (var2 == null) {
+ var2 = new byte[var1.remaining()];
+ var1.get(var2);
+ }
+
+ return var2;
+ }
+
+ public void encode(ByteBuffer var1, OutputStream var2) throws IOException {
+ byte[] var3 = this.getBytes(var1);
+ this.encode(var3, var2);
+ }
+
+ public String encode(ByteBuffer var1) {
+ byte[] var2 = this.getBytes(var1);
+ return this.encode(var2);
+ }
+
+ public void encodeBuffer(InputStream var1, OutputStream var2) throws IOException {
+ byte[] var5 = new byte[this.bytesPerLine()];
+ this.encodeBufferPrefix(var2);
+
+ int var4;
+ do {
+ var4 = this.readFully(var1, var5);
+ if (var4 == 0) {
+ break;
+ }
+
+ this.encodeLinePrefix(var2, var4);
+
+ for(int var3 = 0; var3 < var4; var3 += this.bytesPerAtom()) {
+ if (var3 + this.bytesPerAtom() <= var4) {
+ this.encodeAtom(var2, var5, var3, this.bytesPerAtom());
+ } else {
+ this.encodeAtom(var2, var5, var3, var4 - var3);
+ }
+ }
+
+ this.encodeLineSuffix(var2);
+ } while(var4 >= this.bytesPerLine());
+
+ this.encodeBufferSuffix(var2);
+ }
+
+ public void encodeBuffer(byte[] var1, OutputStream var2) throws IOException {
+ ByteArrayInputStream var3 = new ByteArrayInputStream(var1);
+ this.encodeBuffer((InputStream)var3, var2);
+ }
+
+ public String encodeBuffer(byte[] var1) {
+ ByteArrayOutputStream var2 = new ByteArrayOutputStream();
+ ByteArrayInputStream var3 = new ByteArrayInputStream(var1);
+
+ try {
+ this.encodeBuffer((InputStream)var3, var2);
+ } catch (Exception var5) {
+ throw new Error("CharacterEncoder.encodeBuffer internal error");
+ }
+
+ return var2.toString();
+ }
+
+ public void encodeBuffer(ByteBuffer var1, OutputStream var2) throws IOException {
+ byte[] var3 = this.getBytes(var1);
+ this.encodeBuffer(var3, var2);
+ }
+
+ public String encodeBuffer(ByteBuffer var1) {
+ byte[] var2 = this.getBytes(var1);
+ return this.encodeBuffer(var2);
+ }
+}
diff --git a/app/src/main/java/com/monke/monkeybook/view/impl/MainActivity.java b/app/src/main/java/com/monke/monkeybook/view/impl/MainActivity.java
index 423056c..954ed41 100644
--- a/app/src/main/java/com/monke/monkeybook/view/impl/MainActivity.java
+++ b/app/src/main/java/com/monke/monkeybook/view/impl/MainActivity.java
@@ -30,6 +30,7 @@ import java.util.List;
public class MainActivity extends MBaseActivity implements IMainView {
private ImageView ivLogo;
private ImageButton ibMoney;
+ private ImageButton ibSettings;
private ImageButton ibLibrary;
private ImageButton ibAdd;
private ImageButton ibDownload;
@@ -72,6 +73,7 @@ public class MainActivity extends MBaseActivity implements IMain
rfRvShelf = (RefreshRecyclerView) findViewById(R.id.rf_rv_shelf);
ibMoney = (ImageButton) findViewById(R.id.ib_money);
+ ibSettings = findViewById(R.id.ib_settings);
ibLibrary = (ImageButton) findViewById(R.id.ib_library);
ibAdd = (ImageButton) findViewById(R.id.ib_add);
ibDownload = (ImageButton) findViewById(R.id.ib_download);
@@ -85,10 +87,10 @@ public class MainActivity extends MBaseActivity implements IMain
@Override
protected void bindEvent() {
bindRvShelfEvent();
- ivLogo.setOnClickListener(new View.OnClickListener() {
+ ibSettings.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- proxyPop.showAsDropDown(ivLogo);
+ proxyPop.showAsDropDown(ibSettings);
}
});
ibDownload.setOnClickListener(new View.OnClickListener() {
diff --git a/app/src/main/res/drawable-xxhdpi/icon_setting_main_nor.png b/app/src/main/res/drawable-xxhdpi/icon_setting_main_nor.png
new file mode 100644
index 0000000..547b2c0
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_setting_main_nor.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/icon_setting_main_pre.png b/app/src/main/res/drawable-xxhdpi/icon_setting_main_pre.png
new file mode 100644
index 0000000..5763b19
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/icon_setting_main_pre.png differ
diff --git a/app/src/main/res/drawable/selector_icon_setting_main.xml b/app/src/main/res/drawable/selector_icon_setting_main.xml
new file mode 100644
index 0000000..841edca
--- /dev/null
+++ b/app/src/main/res/drawable/selector_icon_setting_main.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 40253e9..e2ea99c 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -35,37 +35,57 @@
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
+ android:paddingTop="10dp"
+ android:paddingBottom="10dp"
android:layout_marginRight="5dp"
android:background="@drawable/bg_ib_pre"
android:src="@drawable/selector_iv_money"
+ android:scaleType="fitCenter"
android:visibility="gone" />
-
-
+ android:scaleType="fitCenter"
+ android:src="@drawable/selector_iv_library"/>
+
+