Private
Public Access
- Fix NoSuchMethodError on Android 2.x: Dalvik before 4.0 can't link Object methods (toString/equals/...) called through an interface. Patch the bundled Bouncy Castle (tools/patch_bc_dalvik.py) and our own CertVerifier, and make build.sh fail if tools/scan_dalvik.py finds any such call - Treat a manually entered private address (10.x, 172.16-31.x, 192.168.x, .local) as home, so LAN servers that allow access without sign-in work - Send Plex client headers on media requests (files and transcodes) - Explain a 503 on a file as the server being unable to open it (drive or folder not available) - Connection log: home/away, token presence, Plex's file check and a direct file request in the streaming test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
43 lines
3.0 KiB
Python
43 lines
3.0 KiB
Python
"""Rewrites Bouncy Castle calls that Android 2.x's Dalvik can't link.
|
|
|
|
Calling an Object method (toString/equals/hashCode/getClass) through an *interface* type compiles
|
|
to invokeinterface, which Dalvik before 4.0 can't resolve: NoSuchMethodError at runtime. Casting
|
|
the receiver to Object makes javac emit invokevirtual instead. tools/scan_dalvik.py checks nothing
|
|
was missed.
|
|
"""
|
|
import sys
|
|
|
|
FIXES = [
|
|
("asn1/ASN1InputStream.java", "asn1Obj.getClass()", "((Object) asn1Obj).getClass()"),
|
|
("asn1/ConstructedBitStream.java", "asn1Obj.getClass()", "((Object) asn1Obj).getClass()"),
|
|
("asn1/ConstructedOctetStream.java", "asn1Obj.getClass()", "((Object) asn1Obj).getClass()"),
|
|
("asn1/x509/AlgorithmIdentifier.java", "return pa.equals(pb);", "return ((Object) pa).equals(pb);"),
|
|
("asn1/x509/GeneralName.java", "buf.append(obj.toString());", "buf.append(((Object) obj).toString());"),
|
|
("crypto/CryptoServicesPermission.java", "return actions.toString();", "return ((Object) actions).toString();"),
|
|
("crypto/digests/SHA256Digest.java", "digest.getClass().getName()", "((Object) digest).getClass().getName()"),
|
|
("crypto/engines/AESEngine.java", "params.getClass().getName()", "((Object) params).getClass().getName()"),
|
|
("crypto/engines/ARIAEngine.java", "params.getClass().getName()", "((Object) params).getClass().getName()"),
|
|
("crypto/engines/DESedeEngine.java", "params.getClass().getName()", "((Object) params).getClass().getName()"),
|
|
("crypto/engines/SM4Engine.java", "params.getClass().getName()", "((Object) params).getClass().getName()"),
|
|
("crypto/modes/CCMBlockCipher.java", "params.getClass().getName()", "((Object) params).getClass().getName()"),
|
|
("math/ec/ECCurve.java", "getField().equals(other.getField())", "((Object) getField()).equals(other.getField())"),
|
|
("math/ec/ECCurve.java", "return getField().hashCode()", "return ((Object) getField()).hashCode()"),
|
|
("math/field/GenericPolynomialExtensionField.java", "return subfield.equals(other.subfield) && minimalPolynomial.equals(other.minimalPolynomial);",
|
|
"return ((Object) subfield).equals(other.subfield) && ((Object) minimalPolynomial).equals(other.minimalPolynomial);"),
|
|
("math/field/GenericPolynomialExtensionField.java", "return subfield.hashCode()", "return ((Object) subfield).hashCode()"),
|
|
("math/field/GenericPolynomialExtensionField.java", "rotateLeft(minimalPolynomial.hashCode(), 16)", "rotateLeft(((Object) minimalPolynomial).hashCode(), 16)"),
|
|
("tls/crypto/impl/AbstractTlsCrypto.java", "secret.getClass().getName()", "((Object) secret).getClass().getName()"),
|
|
("tls/crypto/impl/bc/BcTlsSecret.java", "secret.getClass().getName()", "((Object) secret).getClass().getName()"),
|
|
]
|
|
|
|
root = sys.argv[1].rstrip("/") + "/com/minamp/bc/"
|
|
for rel, old, new in FIXES:
|
|
p = root + rel
|
|
s = open(p).read()
|
|
if new in s:
|
|
continue
|
|
if old not in s:
|
|
raise SystemExit("pattern not found in %s: %s" % (rel, old))
|
|
open(p, "w").write(s.replace(old, new))
|
|
print("patched %d call sites" % len(FIXES))
|