soul-browser/sources/java/com/google/api/client/util/DateTime.java
KaKi87 550ddb0413
Decompile and recreate Soul Browser v1.4.85 with APK CI builds (#1)
* Decompile and recreate Soul Browser v1.4.85 with APK CI builds

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Fix CI build: include bundled google.jks and remove PR trigger

The apktool build failed in CI because app/unknown/.../google.jks was
excluded by the *.jks gitignore rule. Whitelist app-bundled JKS files
and commit the missing resource.

Also remove the redundant pull_request workflow trigger.

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Change package ID to com.github.kaki87.soulbrowser

Rename the application ID so the rebuilt APK can be installed
alongside the original Soul Browser from Google Play.

- Update AndroidManifest package, permissions, providers, and actions
- Update R class references in smali (com/github/kaki87/soulbrowser/R)
- Update shortcuts.xml targetPackage
- Rename app label to "Soul Rebuild" for easy identification

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Fix install compatibility: remove split APK metadata and bundle native libs

The rebuilt APK still declared requiredSplitTypes and Play Store split
metadata, causing Android to reject standalone installs as incompatible.

- Remove requiredSplitTypes and split-related manifest meta-data
- Merge native libs from all ABI splits with uncompressed storage
- Page-align before signing for extractNativeLibs=false
- Add .so to apktool doNotCompress list

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Fix install failure: use apksigner v2/v3 and bundle arm64 native libs

Target SDK 36 requires APK Signature Scheme v2+, but jarsigner only
produces v1 signatures, causing Android to reject the install.

- Sign with apksigner (v1+v2+v3) instead of jarsigner
- Add arm64-v8a native libraries from universal Soul Browser 1.4.79
- Set extractNativeLibs=true for reliable sideload installs
- Commit stable debug keystore for consistent signatures across builds

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Add committed debug keystore for consistent APK signatures

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Fix startup crash: use original classes2.dex desugar libraries

Apktool recompiles smali_classes2 into a broken classes2.dex, causing
ClassNotFoundException for j$.com.android.tools.r8.a at ML Kit init.

Inject the original classes2.dex (Java 8+ desugar libs) after apktool
build instead of using the recompiled version.

Co-authored-by: KaKi87 <KaKi87@pm.me>

* Fix missing drawable resources from density split APKs

The base APK is an app bundle module; density-specific drawables like
seek_thumb_nor_b live in config.xhdpi.apk and were missing after rebuild,
causing Resources$NotFoundException at runtime.

- Merge non-9-patch resources from split APKs before apktool build
- Sync public.xml IDs from R smali only when backing files exist
- Add 713 density-specific resource IDs to public.xml

Co-authored-by: KaKi87 <KaKi87@pm.me>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-08-10 16:07:14 +02:00

314 lines
10 KiB
Java

package com.google.api.client.util;
import android.support.v4.media.a;
import j$.util.DesugarTimeZone;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/* loaded from: classes3.dex */
public final class DateTime implements Serializable {
private static final long serialVersionUID = 1;
private final boolean dateOnly;
private final int tzShift;
private final long value;
private static final TimeZone GMT = DesugarTimeZone.getTimeZone("GMT");
private static final String RFC3339_REGEX = "(\\d{4})-(\\d{2})-(\\d{2})([Tt](\\d{2}):(\\d{2}):(\\d{2})(\\.\\d{1,9})?)?([Zz]|([+-])(\\d{2}):(\\d{2}))?";
private static final Pattern RFC3339_PATTERN = Pattern.compile(RFC3339_REGEX);
/* loaded from: classes3.dex */
public static class Rfc3339ParseResult implements Serializable {
private static final long serialVersionUID = 1;
private final int nanos;
private final long seconds;
private final boolean timeGiven;
private final Integer tzShift;
/* JADX INFO: Access modifiers changed from: private */
public DateTime toDateTime() {
return new DateTime(!this.timeGiven, TimeUnit.SECONDS.toMillis(this.seconds) + TimeUnit.NANOSECONDS.toMillis(this.nanos), this.tzShift);
}
/* JADX INFO: Access modifiers changed from: private */
public SecondsAndNanos toSecondsAndNanos() {
return new SecondsAndNanos(this.seconds, this.nanos);
}
private Rfc3339ParseResult(long j, int i, boolean z, Integer num) {
this.seconds = j;
this.nanos = i;
this.timeGiven = z;
this.tzShift = num;
}
}
/* loaded from: classes3.dex */
public static final class SecondsAndNanos implements Serializable {
private static long serialVersionUID = 1;
private final int nanos;
private final long seconds;
public static SecondsAndNanos ofSecondsAndNanos(long j, int i) {
return new SecondsAndNanos(j, i);
}
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj != null && SecondsAndNanos.class == obj.getClass()) {
SecondsAndNanos secondsAndNanos = (SecondsAndNanos) obj;
if (this.seconds == secondsAndNanos.seconds && this.nanos == secondsAndNanos.nanos) {
return true;
}
}
return false;
}
public int getNanos() {
return this.nanos;
}
public long getSeconds() {
return this.seconds;
}
public int hashCode() {
return j$.util.Objects.hash(Long.valueOf(this.seconds), Integer.valueOf(this.nanos));
}
public String toString() {
return String.format("Seconds: %d, Nanos: %d", Long.valueOf(this.seconds), Integer.valueOf(this.nanos));
}
private SecondsAndNanos(long j, int i) {
this.seconds = j;
this.nanos = i;
}
}
public DateTime(Date date, TimeZone timeZone) {
this(false, date.getTime(), timeZone == null ? null : Integer.valueOf(timeZone.getOffset(date.getTime()) / 60000));
}
private static void appendInt(StringBuilder sb, int i, int i2) {
if (i < 0) {
sb.append('-');
i = -i;
}
int i3 = i;
while (i3 > 0) {
i3 /= 10;
i2--;
}
for (int i4 = 0; i4 < i2; i4++) {
sb.append('0');
}
if (i != 0) {
sb.append(i);
}
}
public static DateTime parseRfc3339(String str) {
return parseRfc3339WithNanoSeconds(str).toDateTime();
}
public static SecondsAndNanos parseRfc3339ToSecondsAndNanos(String str) {
return parseRfc3339WithNanoSeconds(str).toSecondsAndNanos();
}
private static Rfc3339ParseResult parseRfc3339WithNanoSeconds(String str) {
boolean z;
boolean z2;
int i;
int i2;
int i3;
int i4;
Integer num;
Matcher matcher = RFC3339_PATTERN.matcher(str);
if (matcher.matches()) {
int parseInt = Integer.parseInt(matcher.group(1));
int parseInt2 = Integer.parseInt(matcher.group(2)) - 1;
int parseInt3 = Integer.parseInt(matcher.group(3));
if (matcher.group(4) != null) {
z = true;
} else {
z = false;
}
String group = matcher.group(9);
if (group != null) {
z2 = true;
} else {
z2 = false;
}
if (z2 && !z) {
throw new NumberFormatException(a.C("Invalid date/time format, cannot specify time zone shift without specifying time: ", str));
}
if (z) {
int parseInt4 = Integer.parseInt(matcher.group(5));
int parseInt5 = Integer.parseInt(matcher.group(6));
int parseInt6 = Integer.parseInt(matcher.group(7));
if (matcher.group(8) != null) {
String substring = matcher.group(8).substring(1);
substring.getClass();
if (substring.length() < 9) {
StringBuilder sb = new StringBuilder(9);
sb.append(substring);
for (int length = substring.length(); length < 9; length++) {
sb.append('0');
}
substring = sb.toString();
}
i4 = Integer.parseInt(substring);
i2 = parseInt5;
i3 = parseInt6;
} else {
i2 = parseInt5;
i3 = parseInt6;
i4 = 0;
}
i = parseInt4;
} else {
i = 0;
i2 = 0;
i3 = 0;
i4 = 0;
}
GregorianCalendar gregorianCalendar = new GregorianCalendar(GMT);
gregorianCalendar.clear();
gregorianCalendar.set(parseInt, parseInt2, parseInt3, i, i2, i3);
long timeInMillis = gregorianCalendar.getTimeInMillis();
if (z && z2) {
if (Character.toUpperCase(group.charAt(0)) != 'Z') {
int parseInt7 = Integer.parseInt(matcher.group(12)) + (Integer.parseInt(matcher.group(11)) * 60);
if (matcher.group(10).charAt(0) == '-') {
parseInt7 = -parseInt7;
}
timeInMillis -= parseInt7 * 60000;
num = Integer.valueOf(parseInt7);
} else {
num = 0;
}
} else {
num = null;
}
return new Rfc3339ParseResult(timeInMillis / 1000, i4, z, num);
}
throw new NumberFormatException(a.C("Invalid date/time format: ", str));
}
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof DateTime)) {
return false;
}
DateTime dateTime = (DateTime) obj;
if (this.dateOnly == dateTime.dateOnly && this.value == dateTime.value && this.tzShift == dateTime.tzShift) {
return true;
}
return false;
}
public int getTimeZoneShift() {
return this.tzShift;
}
public long getValue() {
return this.value;
}
public int hashCode() {
long j;
long j2 = this.value;
if (this.dateOnly) {
j = 1;
} else {
j = 0;
}
return Arrays.hashCode(new long[]{j2, j, this.tzShift});
}
public boolean isDateOnly() {
return this.dateOnly;
}
public String toString() {
return toStringRfc3339();
}
public String toStringRfc3339() {
StringBuilder sb = new StringBuilder();
GregorianCalendar gregorianCalendar = new GregorianCalendar(GMT);
gregorianCalendar.setTimeInMillis((this.tzShift * 60000) + this.value);
appendInt(sb, gregorianCalendar.get(1), 4);
sb.append('-');
appendInt(sb, gregorianCalendar.get(2) + 1, 2);
sb.append('-');
appendInt(sb, gregorianCalendar.get(5), 2);
if (!this.dateOnly) {
sb.append('T');
appendInt(sb, gregorianCalendar.get(11), 2);
sb.append(':');
appendInt(sb, gregorianCalendar.get(12), 2);
sb.append(':');
appendInt(sb, gregorianCalendar.get(13), 2);
if (gregorianCalendar.isSet(14)) {
sb.append('.');
appendInt(sb, gregorianCalendar.get(14), 3);
}
int i = this.tzShift;
if (i == 0) {
sb.append('Z');
} else {
if (i > 0) {
sb.append('+');
} else {
sb.append('-');
i = -i;
}
appendInt(sb, i / 60, 2);
sb.append(':');
appendInt(sb, i % 60, 2);
}
}
return sb.toString();
}
public DateTime(long j) {
this(false, j, null);
}
public DateTime(Date date) {
this(date.getTime());
}
public DateTime(long j, int i) {
this(false, j, Integer.valueOf(i));
}
public DateTime(boolean z, long j, Integer num) {
int offset;
this.dateOnly = z;
this.value = j;
if (z) {
offset = 0;
} else {
offset = num == null ? TimeZone.getDefault().getOffset(j) / 60000 : num.intValue();
}
this.tzShift = offset;
}
public DateTime(String str) {
DateTime parseRfc3339 = parseRfc3339(str);
this.dateOnly = parseRfc3339.dateOnly;
this.value = parseRfc3339.value;
this.tzShift = parseRfc3339.tzShift;
}
}