soul-browser/sources/java/org/jsoup/parser/StreamParser.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

259 lines
7.9 KiB
Java

package org.jsoup.parser;
import j$.util.Spliterators;
import j$.util.stream.Stream;
import j$.util.stream.StreamSupport;
import java.io.Closeable;
import java.io.Reader;
import java.io.StringReader;
import java.io.UncheckedIOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import org.jsoup.helper.Validate;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.select.Evaluator;
import org.jsoup.select.NodeVisitor;
import org.jsoup.select.Selector;
/* loaded from: classes4.dex */
public class StreamParser implements Closeable {
/* renamed from: c, reason: collision with root package name */
public final Parser f22595c;
public final TreeBuilder f;
public final ElementIterator g;
public Document h;
public boolean i;
/* loaded from: classes4.dex */
public final class ElementIterator implements Iterator<Element>, NodeVisitor {
/* renamed from: c, reason: collision with root package name */
public final LinkedList f22596c = new LinkedList();
public Element f;
public Element g;
public Element h;
public ElementIterator() {
}
public final void a() {
StreamParser streamParser = StreamParser.this;
if (!streamParser.i && this.g == null) {
LinkedList linkedList = this.f22596c;
if (!linkedList.isEmpty()) {
this.g = (Element) linkedList.remove();
return;
}
while (streamParser.f.p()) {
if (!linkedList.isEmpty()) {
this.g = (Element) linkedList.remove();
return;
}
}
streamParser.stop();
streamParser.close();
Element element = this.h;
if (element != null) {
this.g = element;
this.h = null;
}
}
}
@Override // java.util.Iterator
public final boolean hasNext() {
a();
if (this.g != null) {
return true;
}
return false;
}
@Override // org.jsoup.select.NodeVisitor
/* renamed from: head */
public final void mo2head(Node node, int i) {
Element previousElementSibling;
if ((node instanceof Element) && (previousElementSibling = node.previousElementSibling()) != null) {
this.f22596c.add(previousElementSibling);
}
}
@Override // java.util.Iterator
public final Element next() {
a();
Element element = this.g;
if (element != null) {
this.f = element;
this.g = null;
return element;
}
throw new NoSuchElementException();
}
@Override // java.util.Iterator
public final void remove() {
Element element = this.f;
if (element != null) {
element.remove();
return;
}
throw new NoSuchElementException();
}
@Override // org.jsoup.select.NodeVisitor
/* renamed from: tail */
public final void mo3tail(Node node, int i) {
if (node instanceof Element) {
Element element = (Element) node;
this.h = element;
Element lastElementChild = element.lastElementChild();
if (lastElementChild != null) {
this.f22596c.add(lastElementChild);
}
}
}
@Override // org.jsoup.select.NodeVisitor, org.jsoup.select.NodeFilter
public final /* synthetic */ void traverse(Node node) {
org.jsoup.select.d.b(this, node);
}
}
public StreamParser(Parser parser) {
ElementIterator elementIterator = new ElementIterator();
this.g = elementIterator;
this.i = false;
this.f22595c = parser;
TreeBuilder treeBuilder = parser.getTreeBuilder();
this.f = treeBuilder;
treeBuilder.j = elementIterator;
}
@Override // java.io.Closeable, java.lang.AutoCloseable
public void close() {
TreeBuilder treeBuilder = this.f;
CharacterReader characterReader = treeBuilder.b;
if (characterReader == null) {
return;
}
characterReader.close();
treeBuilder.b = null;
treeBuilder.f22609c = null;
treeBuilder.e = null;
}
public Document complete() {
TreeBuilder treeBuilder;
Document document = document();
do {
treeBuilder = this.f;
} while (treeBuilder.p());
CharacterReader characterReader = treeBuilder.b;
if (characterReader == null) {
return document;
}
characterReader.close();
treeBuilder.b = null;
treeBuilder.f22609c = null;
treeBuilder.e = null;
return document;
}
public List<Node> completeFragment() {
TreeBuilder treeBuilder;
do {
treeBuilder = this.f;
} while (treeBuilder.p());
CharacterReader characterReader = treeBuilder.b;
if (characterReader != null) {
characterReader.close();
treeBuilder.b = null;
treeBuilder.f22609c = null;
treeBuilder.e = null;
}
return treeBuilder.a();
}
public Document document() {
Document document = this.f.d;
this.h = document;
Validate.notNull(document, "Must run parse() before calling.");
return this.h;
}
public Element expectFirst(String str) {
return (Element) Validate.expectNotNull(selectFirst(str), "No elements matched the query '%s' in the document.", str);
}
public Element expectNext(String str) {
return (Element) Validate.expectNotNull(selectNext(str), "No elements matched the query '%s' in the document.", str);
}
public Iterator<Element> iterator() {
return this.g;
}
public StreamParser parse(Reader reader, String str) {
close();
ElementIterator elementIterator = this.g;
elementIterator.f22596c.clear();
elementIterator.h = null;
elementIterator.g = null;
elementIterator.f = null;
StreamParser.this.i = false;
Parser parser = this.f22595c;
TreeBuilder treeBuilder = this.f;
treeBuilder.f(reader, str, parser);
this.h = treeBuilder.d;
return this;
}
public StreamParser parseFragment(Reader reader, Element element, String str) {
parse(reader, str);
this.f.g(element);
return this;
}
public Element selectFirst(String str) {
return selectFirst(Selector.evaluatorOf(str));
}
public Element selectNext(String str) {
return selectNext(Selector.evaluatorOf(str));
}
public StreamParser stop() {
this.i = true;
return this;
}
public Stream<Element> stream() {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(this.g, 273), false);
}
public Element selectFirst(Evaluator evaluator) {
Element selectFirst = document().selectFirst(evaluator);
return selectFirst != null ? selectFirst : selectNext(evaluator);
}
public Element selectNext(Evaluator evaluator) {
try {
return stream().filter(evaluator.asPredicate(document())).findFirst().orElse(null);
} catch (UncheckedIOException e) {
throw e.getCause();
}
}
public StreamParser parseFragment(String str, Element element, String str2) {
return parseFragment(new StringReader(str), element, str2);
}
public StreamParser parse(String str, String str2) {
return parse(new StringReader(str), str2);
}
}