Austin Huang
4 years ago
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
3 changed files with 104 additions and 220 deletions
-
89app/src/main/java/awais/instagrabber/utils/PasswordUtils.kt
-
161app/src/main/java/awais/instagrabber/utils/TextUtils.kt
-
74app/src/main/java/awais/instagrabber/utils/UrlEncoder.java
@ -1,47 +1,52 @@ |
|||
package awais.instagrabber.utils; |
|||
|
|||
import android.util.Base64; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
|
|||
import java.security.GeneralSecurityException; |
|||
import java.security.InvalidAlgorithmParameterException; |
|||
import java.security.InvalidKeyException; |
|||
import java.security.NoSuchAlgorithmException; |
|||
|
|||
import javax.crypto.BadPaddingException; |
|||
import javax.crypto.Cipher; |
|||
import javax.crypto.IllegalBlockSizeException; |
|||
import javax.crypto.NoSuchPaddingException; |
|||
import javax.crypto.spec.IvParameterSpec; |
|||
import javax.crypto.spec.SecretKeySpec; |
|||
|
|||
public final class PasswordUtils { |
|||
private static final String cipherAlgo = "AES"; |
|||
private static final String cipherTran = "AES/CBC/PKCS5Padding"; |
|||
|
|||
public static byte[] dec(final String encrypted, final byte[] keyValue) throws Exception { |
|||
try { |
|||
final Cipher cipher = Cipher.getInstance(cipherTran); |
|||
final SecretKeySpec secretKey = new SecretKeySpec(keyValue, cipherAlgo); |
|||
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(new byte[16])); |
|||
return cipher.doFinal(Base64.decode(encrypted, Base64.DEFAULT | Base64.NO_PADDING | Base64.NO_WRAP)); |
|||
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidAlgorithmParameterException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) { |
|||
throw new IncorrectPasswordException(e); |
|||
package awais.instagrabber.utils |
|||
|
|||
import android.util.Base64 |
|||
import java.security.GeneralSecurityException |
|||
import java.security.InvalidAlgorithmParameterException |
|||
import java.security.InvalidKeyException |
|||
import java.security.NoSuchAlgorithmException |
|||
import javax.crypto.BadPaddingException |
|||
import javax.crypto.Cipher |
|||
import javax.crypto.IllegalBlockSizeException |
|||
import javax.crypto.NoSuchPaddingException |
|||
import javax.crypto.spec.IvParameterSpec |
|||
import javax.crypto.spec.SecretKeySpec |
|||
|
|||
object PasswordUtils { |
|||
private const val cipherAlgo = "AES" |
|||
private const val cipherTran = "AES/CBC/PKCS5Padding" |
|||
@JvmStatic |
|||
@Throws(Exception::class) |
|||
fun dec(encrypted: String?, keyValue: ByteArray?): ByteArray { |
|||
return try { |
|||
val cipher = Cipher.getInstance(cipherTran) |
|||
val secretKey = SecretKeySpec(keyValue, cipherAlgo) |
|||
cipher.init(Cipher.DECRYPT_MODE, secretKey, IvParameterSpec(ByteArray(16))) |
|||
cipher.doFinal(Base64.decode(encrypted, Base64.DEFAULT or Base64.NO_PADDING or Base64.NO_WRAP)) |
|||
} catch (e: NoSuchAlgorithmException) { |
|||
throw IncorrectPasswordException(e) |
|||
} catch (e: NoSuchPaddingException) { |
|||
throw IncorrectPasswordException(e) |
|||
} catch (e: InvalidAlgorithmParameterException) { |
|||
throw IncorrectPasswordException(e) |
|||
} catch (e: InvalidKeyException) { |
|||
throw IncorrectPasswordException(e) |
|||
} catch (e: BadPaddingException) { |
|||
throw IncorrectPasswordException(e) |
|||
} catch (e: IllegalBlockSizeException) { |
|||
throw IncorrectPasswordException(e) |
|||
} |
|||
} |
|||
|
|||
public static byte[] enc(@NonNull final String str, final byte[] keyValue) throws Exception { |
|||
final Cipher cipher = Cipher.getInstance(cipherTran); |
|||
final SecretKeySpec secretKey = new SecretKeySpec(keyValue, cipherAlgo); |
|||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(new byte[16])); |
|||
final byte[] bytes = cipher.doFinal(str.getBytes()); |
|||
return Base64.encode(bytes, Base64.DEFAULT | Base64.NO_PADDING | Base64.NO_WRAP); |
|||
@JvmStatic |
|||
@Throws(Exception::class) |
|||
fun enc(str: String, keyValue: ByteArray?): ByteArray { |
|||
val cipher = Cipher.getInstance(cipherTran) |
|||
val secretKey = SecretKeySpec(keyValue, cipherAlgo) |
|||
cipher.init(Cipher.ENCRYPT_MODE, secretKey, IvParameterSpec(ByteArray(16))) |
|||
val bytes = cipher.doFinal(str.toByteArray()) |
|||
return Base64.encode(bytes, Base64.DEFAULT or Base64.NO_PADDING or Base64.NO_WRAP) |
|||
} |
|||
|
|||
public static class IncorrectPasswordException extends Exception { |
|||
public IncorrectPasswordException(final GeneralSecurityException e) { |
|||
super(e); |
|||
} |
|||
} |
|||
} |
|||
class IncorrectPasswordException(e: GeneralSecurityException?) : Exception(e) |
|||
} |
@ -1,122 +1,75 @@ |
|||
package awais.instagrabber.utils; |
|||
|
|||
import android.content.Context; |
|||
import android.text.SpannableString; |
|||
import android.text.format.DateFormat; |
|||
import android.text.format.DateUtils; |
|||
import android.text.style.URLSpan; |
|||
import android.util.Patterns; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.Arrays; |
|||
import java.util.Collections; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
import java.util.Locale; |
|||
import java.util.regex.Matcher; |
|||
import java.util.stream.Collectors; |
|||
|
|||
public final class TextUtils { |
|||
// extracted from String class |
|||
public static int indexOfChar(@NonNull final CharSequence sequence, final int ch, final int startIndex) { |
|||
final int max = sequence.length(); |
|||
if (startIndex < max) { |
|||
if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { |
|||
for (int i = startIndex; i < max; i++) if (sequence.charAt(i) == ch) return i; |
|||
} else if (Character.isValidCodePoint(ch)) { |
|||
final char hi = (char) ((ch >>> 10) + (Character.MIN_HIGH_SURROGATE - (Character.MIN_SUPPLEMENTARY_CODE_POINT >>> 10))); |
|||
final char lo = (char) ((ch & 0x3ff) + Character.MIN_LOW_SURROGATE); |
|||
for (int i = startIndex; i < max; i++) |
|||
if (sequence.charAt(i) == hi && sequence.charAt(i + 1) == lo) return i; |
|||
} |
|||
package awais.instagrabber.utils |
|||
|
|||
import android.content.Context |
|||
import android.text.format.DateFormat |
|||
import android.text.format.DateUtils |
|||
import android.util.Patterns |
|||
import java.util.* |
|||
|
|||
object TextUtils { |
|||
@JvmStatic |
|||
fun isEmpty(charSequence: CharSequence?): Boolean { |
|||
if (charSequence == null || charSequence.length < 1) return true |
|||
if (charSequence is String) { |
|||
var str = charSequence |
|||
if ("" == str || "null" == str || str.isEmpty()) return true |
|||
str = str.trim { it <= ' ' } |
|||
return "" == str || "null" == str || str.isEmpty() |
|||
} |
|||
return -1; |
|||
return "null".contentEquals(charSequence) || "".contentEquals(charSequence) |
|||
} |
|||
|
|||
public static CharSequence getSpannableUrl(final String url) { |
|||
if (isEmpty(url)) return url; |
|||
final int httpIndex = url.indexOf("http:"); |
|||
final int httpsIndex = url.indexOf("https:"); |
|||
if (httpIndex == -1 && httpsIndex == -1) return url; |
|||
|
|||
final int length = url.length(); |
|||
|
|||
final int startIndex = httpIndex != -1 ? httpIndex : httpsIndex; |
|||
final int spaceIndex = url.indexOf(' ', startIndex + 1); |
|||
|
|||
final int endIndex = (spaceIndex != -1 ? spaceIndex : length); |
|||
|
|||
final String extractUrl = url.substring(startIndex, Math.min(length, endIndex)); |
|||
|
|||
final SpannableString spannableString = new SpannableString(url); |
|||
spannableString.setSpan(new URLSpan(extractUrl), startIndex, endIndex, 0); |
|||
|
|||
return spannableString; |
|||
} |
|||
|
|||
public static boolean isEmpty(final CharSequence charSequence) { |
|||
if (charSequence == null || charSequence.length() < 1) return true; |
|||
if (charSequence instanceof String) { |
|||
String str = (String) charSequence; |
|||
if ("".equals(str) || "null".equals(str) || str.isEmpty()) return true; |
|||
str = str.trim(); |
|||
return "".equals(str) || "null".equals(str) || str.isEmpty(); |
|||
} |
|||
return "null".contentEquals(charSequence) || "".contentEquals(charSequence); |
|||
} |
|||
|
|||
public static String millisToTimeString(final long millis) { |
|||
return millisToTimeString(millis, false); |
|||
} |
|||
|
|||
public static String millisToTimeString(final long millis, final boolean includeHoursAlways) { |
|||
final int sec = (int) (millis / 1000) % 60; |
|||
int min = (int) (millis / (1000 * 60)); |
|||
@JvmStatic |
|||
@JvmOverloads |
|||
fun millisToTimeString(millis: Long, includeHoursAlways: Boolean = false): String { |
|||
val sec = (millis / 1000).toInt() % 60 |
|||
var min = (millis / (1000 * 60)).toInt() |
|||
if (min >= 60) { |
|||
min = (int) ((millis / (1000 * 60)) % 60); |
|||
final int hr = (int) ((millis / (1000 * 60 * 60)) % 24); |
|||
return String.format(Locale.ENGLISH, "%02d:%02d:%02d", hr, min, sec); |
|||
min = (millis / (1000 * 60) % 60).toInt() |
|||
val hr = (millis / (1000 * 60 * 60) % 24).toInt() |
|||
return String.format(Locale.ENGLISH, "%02d:%02d:%02d", hr, min, sec) |
|||
} |
|||
if (includeHoursAlways) { |
|||
return String.format(Locale.ENGLISH, "%02d:%02d:%02d", 0, min, sec); |
|||
} |
|||
return String.format(Locale.ENGLISH, "%02d:%02d", min, sec); |
|||
return if (includeHoursAlways) { |
|||
String.format(Locale.ENGLISH, "%02d:%02d:%02d", 0, min, sec) |
|||
} else String.format(Locale.ENGLISH, "%02d:%02d", min, sec) |
|||
} |
|||
|
|||
public static String getRelativeDateTimeString(final Context context, final long from) { |
|||
final Date now = new Date(); |
|||
final Date then = new Date(from); |
|||
int days = daysBetween(from, now.getTime()); |
|||
if (days == 0) { |
|||
return DateFormat.getTimeFormat(context).format(then); |
|||
} |
|||
return DateFormat.getDateFormat(context).format(then); |
|||
@JvmStatic |
|||
fun getRelativeDateTimeString(context: Context?, from: Long): String { |
|||
val now = Date() |
|||
val then = Date(from) |
|||
val days = daysBetween(from, now.time) |
|||
return if (days == 0) { |
|||
DateFormat.getTimeFormat(context).format(then) |
|||
} else DateFormat.getDateFormat(context).format(then) |
|||
} |
|||
|
|||
private static int daysBetween(long d1, long d2) { |
|||
return (int) ((d2 - d1) / DateUtils.DAY_IN_MILLIS); |
|||
private fun daysBetween(d1: Long, d2: Long): Int { |
|||
return ((d2 - d1) / DateUtils.DAY_IN_MILLIS).toInt() |
|||
} |
|||
|
|||
public static List<String> extractUrls(final String text) { |
|||
if (isEmpty(text)) return Collections.emptyList(); |
|||
final Matcher matcher = Patterns.WEB_URL.matcher(text); |
|||
final List<String> urls = new ArrayList<>(); |
|||
@JvmStatic |
|||
fun extractUrls(text: String?): List<String> { |
|||
if (isEmpty(text)) return emptyList() |
|||
val matcher = Patterns.WEB_URL.matcher(text) |
|||
val urls: MutableList<String> = ArrayList() |
|||
while (matcher.find()) { |
|||
urls.add(matcher.group()); |
|||
urls.add(matcher.group()) |
|||
} |
|||
return urls; |
|||
return urls |
|||
} |
|||
|
|||
// https://github.com/notslang/instagram-id-to-url-segment |
|||
public static long shortcodeToId(final String shortcode) { |
|||
long result = 0L; |
|||
for (int i = 0; i < shortcode.length() && i < 11; i++){ |
|||
final char c = shortcode.charAt(i); |
|||
final int k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".indexOf(c); |
|||
result = result * 64 + k; |
|||
@JvmStatic |
|||
fun shortcodeToId(shortcode: String): Long { |
|||
var result = 0L |
|||
var i = 0 |
|||
while (i < shortcode.length && i < 11) { |
|||
val c = shortcode[i] |
|||
val k = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_".indexOf(c) |
|||
result = result * 64 + k |
|||
i++ |
|||
} |
|||
return result; |
|||
return result |
|||
} |
|||
} |
|||
} |
@ -1,74 +0,0 @@ |
|||
package awais.instagrabber.utils; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
|
|||
import java.io.CharArrayWriter; |
|||
import java.util.BitSet; |
|||
|
|||
// same as java.net.URLEncoder |
|||
public final class UrlEncoder { |
|||
private static final BitSet dontNeedEncoding = new BitSet(256); |
|||
private static final int caseDiff = ('a' - 'A'); |
|||
|
|||
static { |
|||
int i; |
|||
for (i = 'a'; i <= 'z'; i++) dontNeedEncoding.set(i); |
|||
for (i = 'A'; i <= 'Z'; i++) dontNeedEncoding.set(i); |
|||
for (i = '0'; i <= '9'; i++) dontNeedEncoding.set(i); |
|||
dontNeedEncoding.set(' '); |
|||
dontNeedEncoding.set('-'); |
|||
dontNeedEncoding.set('_'); |
|||
dontNeedEncoding.set('.'); |
|||
dontNeedEncoding.set('*'); |
|||
} |
|||
|
|||
@NonNull |
|||
public static String encodeUrl(@NonNull final String s) { |
|||
final StringBuilder out = new StringBuilder(s.length()); |
|||
final CharArrayWriter charArrayWriter = new CharArrayWriter(); |
|||
|
|||
boolean needToChange = false; |
|||
for (int i = 0; i < s.length(); ) { |
|||
int c = s.charAt(i); |
|||
|
|||
if (dontNeedEncoding.get(c)) { |
|||
if (c == ' ') { |
|||
c = '+'; |
|||
needToChange = true; |
|||
} |
|||
|
|||
out.append((char) c); |
|||
i++; |
|||
} else { |
|||
do { |
|||
charArrayWriter.write(c); |
|||
if (c >= 0xD800 && c <= 0xDBFF && i + 1 < s.length()) { |
|||
final int d = s.charAt(i + 1); |
|||
if (d >= 0xDC00 && d <= 0xDFFF) { |
|||
charArrayWriter.write(d); |
|||
i++; |
|||
} |
|||
} |
|||
i++; |
|||
} while (i < s.length() && !dontNeedEncoding.get(c = s.charAt(i))); |
|||
|
|||
charArrayWriter.flush(); |
|||
|
|||
final byte[] ba = charArrayWriter.toString().getBytes(); |
|||
for (final byte b : ba) { |
|||
out.append('%'); |
|||
char ch = Character.forDigit((b >> 4) & 0xF, 16); |
|||
if (Character.isLetter(ch)) ch -= caseDiff; |
|||
out.append(ch); |
|||
ch = Character.forDigit(b & 0xF, 16); |
|||
if (Character.isLetter(ch)) ch -= caseDiff; |
|||
out.append(ch); |
|||
} |
|||
charArrayWriter.reset(); |
|||
needToChange = true; |
|||
} |
|||
} |
|||
|
|||
return (needToChange ? out.toString() : s); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue