This commit is contained in:
Lorenzo Pichilli 2020-06-22 00:09:35 +02:00
parent f6a6b4a66b
commit 993c6f60f9
17 changed files with 680 additions and 516 deletions

View File

@ -21,7 +21,6 @@ class ASN1DERDecoder {
asn1obj.identifier = ASN1Identifier(nextValue);
if (asn1obj.identifier.isConstructed()) {
var contentData = loadSubContent(iterator: iterator);
if (contentData.isEmpty) {
@ -39,9 +38,7 @@ class ASN1DERDecoder {
item.parent = asn1obj;
}
} else {
if (asn1obj.identifier.typeClass() == ASN1IdentifierClass.UNIVERSAL) {
var contentData = loadSubContent(iterator: iterator);
asn1obj.encoded = Uint8List.fromList(contentData);
@ -52,75 +49,62 @@ class ASN1DERDecoder {
if (tagNumber == ASN1IdentifierTagNumber.END_OF_CONTENT) {
return result;
}
else if (tagNumber == ASN1IdentifierTagNumber.BOOLEAN) {
} else if (tagNumber == ASN1IdentifierTagNumber.BOOLEAN) {
var value = contentData.length > 0 ? contentData.first : null;
if (value != null) {
asn1obj.value = value > 0 ? true : false;
}
}
else if (tagNumber == ASN1IdentifierTagNumber.INTEGER) {
} else if (tagNumber == ASN1IdentifierTagNumber.INTEGER) {
while (contentData.length > 0 && contentData.first == 0) {
contentData.removeAt(0); // remove not significant digit
}
asn1obj.value = contentData;
}
else if (tagNumber == ASN1IdentifierTagNumber.NULL) {
} else if (tagNumber == ASN1IdentifierTagNumber.NULL) {
asn1obj.value = null;
}
else if (tagNumber == ASN1IdentifierTagNumber.OBJECT_IDENTIFIER) {
} else if (tagNumber == ASN1IdentifierTagNumber.OBJECT_IDENTIFIER) {
asn1obj.value = decodeOid(contentData: contentData);
}
else if ([
} else if ([
ASN1IdentifierTagNumber.UTF8_STRING,
ASN1IdentifierTagNumber.PRINTABLE_STRING,
ASN1IdentifierTagNumber.NUMERIC_STRING,
ASN1IdentifierTagNumber.GENERAL_STRING,
ASN1IdentifierTagNumber.UNIVERSAL_STRING,
ASN1IdentifierTagNumber.CHARACTER_STRING,
ASN1IdentifierTagNumber.T61_STRING].contains(tagNumber)) {
ASN1IdentifierTagNumber.T61_STRING
].contains(tagNumber)) {
asn1obj.value = utf8.decode(contentData, allowMalformed: true);
}
else if (tagNumber == ASN1IdentifierTagNumber.BMP_STRING) {
} else if (tagNumber == ASN1IdentifierTagNumber.BMP_STRING) {
asn1obj.value = String.fromCharCodes(contentData);
}
else if ([
} else if ([
ASN1IdentifierTagNumber.VISIBLE_STRING,
ASN1IdentifierTagNumber.IA5_STRING
].contains(tagNumber)) {
asn1obj.value = ascii.decode(contentData, allowInvalid: true);
}
else if (tagNumber == ASN1IdentifierTagNumber.UTC_TIME) {
} else if (tagNumber == ASN1IdentifierTagNumber.UTC_TIME) {
asn1obj.value = utcTimeToDate(contentData: contentData);
}
else if (tagNumber == ASN1IdentifierTagNumber.GENERALIZED_TIME) {
} else if (tagNumber == ASN1IdentifierTagNumber.GENERALIZED_TIME) {
asn1obj.value = generalizedTimeToDate(contentData: contentData);
}
else if (tagNumber == ASN1IdentifierTagNumber.BIT_STRING) {
} else if (tagNumber == ASN1IdentifierTagNumber.BIT_STRING) {
if (contentData.length > 0) {
contentData.removeAt(0); // unused bits
}
asn1obj.value = contentData;
}
else if (tagNumber == ASN1IdentifierTagNumber.OCTET_STRING) {
} else if (tagNumber == ASN1IdentifierTagNumber.OCTET_STRING) {
try {
var subIterator = contentData.iterator;
asn1obj.sub = parse(iterator: subIterator);
} catch (e) {
var str;
try {
str = utf8.decode(contentData);
} catch(e) {}
} catch (e) {}
if (str != null) {
asn1obj.value = str;
} else {
asn1obj.value = contentData;
}
}
}
else {
} else {
// print("unsupported tag: ${asn1obj.identifier.tagNumber()}");
asn1obj.value = contentData;
}
@ -132,7 +116,7 @@ class ASN1DERDecoder {
var str;
try {
str = utf8.decode(contentData);
} catch(e) {}
} catch (e) {}
if (str != null) {
asn1obj.value = str;
} else {
@ -150,8 +134,8 @@ class ASN1DERDecoder {
if (iterator.moveNext()) {
var first = iterator.current;
if (first != null) {
if ((first & 0x80) != 0) { // long
if ((first & 0x80) != 0) {
// long
var octetsToRead = first - 0x80;
var data = <int>[];
@ -165,11 +149,10 @@ class ASN1DERDecoder {
}
return toIntValue(data) ?? BigInt.from(0);
} else { // short
} else {
// short
return BigInt.from(first);
}
}
}
return BigInt.from(0);
@ -251,7 +234,7 @@ class ASN1DERDecoder {
String utc;
try {
utc = utf8.decode(contentData);
} catch(e) {}
} catch (e) {}
if (utc == null) {
return null;
}
@ -268,36 +251,30 @@ class ASN1DERDecoder {
int end;
String c;
// not just YYMMDDhhmmZ
if(utc.length > 11) {
if (utc.length > 11) {
// get character after minutes
c = utc[10];
end = 10;
// see if seconds are present
if(c != '+' && c != '-') {
if (c != '+' && c != '-') {
// get seconds
ss = int.parse(utc.substring(10, 12), radix: 10);
end += 2;
}
}
var date = DateTime.utc(
year,
MM,
DD,
hh,
mm,
ss,
0
);
var date = DateTime.utc(year, MM, DD, hh, mm, ss, 0);
if(end != null) {
if (end != null) {
// get +/- after end of time
c = utc[end];
if(c == '+' || c == '-') {
if (c == '+' || c == '-') {
// get hours+minutes offset
var hhoffset = int.parse(utc.substring(end + 1, end + 1 + 2), radix: 10);
var mmoffset = int.parse(utc.substring(end + 4, end + 4 + 2), radix: 10);
var hhoffset =
int.parse(utc.substring(end + 1, end + 1 + 2), radix: 10);
var mmoffset =
int.parse(utc.substring(end + 4, end + 4 + 2), radix: 10);
// calculate offset in milliseconds
var offset = hhoffset * 60 + mmoffset;
@ -305,7 +282,7 @@ class ASN1DERDecoder {
var offsetDuration = Duration(milliseconds: offset);
// apply offset
if(c == '+') {
if (c == '+') {
date.subtract(offsetDuration);
} else {
date.add(offsetDuration);
@ -345,7 +322,7 @@ class ASN1DERDecoder {
String gentime;
try {
gentime = utf8.decode(contentData);
} catch(e) {}
} catch (e) {}
if (gentime == null) {
return null;
}
@ -362,23 +339,25 @@ class ASN1DERDecoder {
var offset = 0;
var isUTC = false;
if(gentime[gentime.length - 1] == 'Z') {
if (gentime[gentime.length - 1] == 'Z') {
isUTC = true;
}
var end = gentime.length - 5;
var c = gentime[end];
if(c == '+' || c == '-') {
if (c == '+' || c == '-') {
// get hours+minutes offset
var hhoffset = int.parse(gentime.substring(end + 1, end + 1 + 2), radix: 10);
var mmoffset = int.parse(gentime.substring(end + 4, end + 4 + 2), radix: 10);
var hhoffset =
int.parse(gentime.substring(end + 1, end + 1 + 2), radix: 10);
var mmoffset =
int.parse(gentime.substring(end + 4, end + 4 + 2), radix: 10);
// calculate offset in milliseconds
offset = hhoffset * 60 + mmoffset;
offset *= 60000;
// apply offset
if(c == '+') {
if (c == '+') {
offset *= -1;
}
@ -386,26 +365,17 @@ class ASN1DERDecoder {
}
// check for second fraction
if(gentime[14] == '.') {
if (gentime[14] == '.') {
fff = double.parse(gentime.substring(14)) * 1000;
}
var date = DateTime.utc(
YYYY,
MM,
DD,
hh,
mm,
ss,
fff.toInt()
);
var date = DateTime.utc(YYYY, MM, DD, hh, mm, ss, fff.toInt());
if(isUTC) {
if (isUTC) {
var offsetDuration = Duration(milliseconds: offset);
date.add(offsetDuration);
}
return date;
}
}
@ -418,15 +388,11 @@ BigInt toIntValue(List<int> data) {
BigInt value = BigInt.from(0);
for (var index = 0; index < data.length; index++) {
var byte = data[index];
value += BigInt.from(byte << 8*(data.length-index-1));
value += BigInt.from(byte << 8 * (data.length - index - 1));
}
return value;
}
class ASN1OutOfBufferError extends Error {
class ASN1OutOfBufferError extends Error {}
}
class ASN1ParseError extends Error {
}
class ASN1ParseError extends Error {}

View File

@ -21,32 +21,45 @@ class ASN1DistinguishedNames {
static ASN1DistinguishedNames fromValue(String oid) {
if (oid != null)
return ASN1DistinguishedNames.values.firstWhere((element) => element.oid() == oid, orElse: () => null);
return ASN1DistinguishedNames.values
.firstWhere((element) => element.oid() == oid, orElse: () => null);
return null;
}
String oid() => _oid;
String representation() => _representation;
@override
String toString() => "($_oid, $_representation)";
static const COMMON_NAME = const ASN1DistinguishedNames._internal("2.5.4.3", "CN");
static const DN_QUALIFIER = const ASN1DistinguishedNames._internal("2.5.4.46", "DNQ");
static const SERIAL_NUMBER = const ASN1DistinguishedNames._internal("2.5.4.5", "SERIALNUMBER");
static const GIVEN_NAME = const ASN1DistinguishedNames._internal("2.5.4.42", "GIVENNAME");
static const SURNAME = const ASN1DistinguishedNames._internal("2.5.4.4", "SURNAME");
static const ORGANIZATIONAL_UNIT_NAME = const ASN1DistinguishedNames._internal("2.5.4.11", "OU");
static const ORGANIZATION_NAME = const ASN1DistinguishedNames._internal("2.5.4.10", "O");
static const STREET_ADDRESS = const ASN1DistinguishedNames._internal("2.5.4.9", "STREET");
static const LOCALITY_NAME = const ASN1DistinguishedNames._internal("2.5.4.7", "L");
static const STATE_OR_PROVINCE_NAME = const ASN1DistinguishedNames._internal("2.5.4.8", "ST");
static const COUNTRY_NAME = const ASN1DistinguishedNames._internal("2.5.4.6", "C");
static const EMAIL = const ASN1DistinguishedNames._internal("1.2.840.113549.1.9.1", "E");
static const COMMON_NAME =
const ASN1DistinguishedNames._internal("2.5.4.3", "CN");
static const DN_QUALIFIER =
const ASN1DistinguishedNames._internal("2.5.4.46", "DNQ");
static const SERIAL_NUMBER =
const ASN1DistinguishedNames._internal("2.5.4.5", "SERIALNUMBER");
static const GIVEN_NAME =
const ASN1DistinguishedNames._internal("2.5.4.42", "GIVENNAME");
static const SURNAME =
const ASN1DistinguishedNames._internal("2.5.4.4", "SURNAME");
static const ORGANIZATIONAL_UNIT_NAME =
const ASN1DistinguishedNames._internal("2.5.4.11", "OU");
static const ORGANIZATION_NAME =
const ASN1DistinguishedNames._internal("2.5.4.10", "O");
static const STREET_ADDRESS =
const ASN1DistinguishedNames._internal("2.5.4.9", "STREET");
static const LOCALITY_NAME =
const ASN1DistinguishedNames._internal("2.5.4.7", "L");
static const STATE_OR_PROVINCE_NAME =
const ASN1DistinguishedNames._internal("2.5.4.8", "ST");
static const COUNTRY_NAME =
const ASN1DistinguishedNames._internal("2.5.4.6", "C");
static const EMAIL =
const ASN1DistinguishedNames._internal("1.2.840.113549.1.9.1", "E");
bool operator ==(value) => value == _oid;
@override
int get hashCode => _oid.hashCode;
}
}

View File

@ -12,7 +12,9 @@ class ASN1IdentifierClass {
static ASN1IdentifierClass fromValue(int value) {
if (value != null)
return ASN1IdentifierClass.values.firstWhere((element) => element.toValue() == value, orElse: () => null);
return ASN1IdentifierClass.values.firstWhere(
(element) => element.toValue() == value,
orElse: () => null);
return null;
}
@ -81,41 +83,45 @@ class ASN1IdentifierTagNumber {
static ASN1IdentifierTagNumber fromValue(int value) {
if (value != null)
return ASN1IdentifierTagNumber.values.firstWhere((element) => element.toValue() == value, orElse: () => null);
return ASN1IdentifierTagNumber.values.firstWhere(
(element) => element.toValue() == value,
orElse: () => null);
return null;
}
int toValue() => _value;
static const END_OF_CONTENT = const ASN1IdentifierTagNumber._internal(0x00);
static const BOOLEAN = const ASN1IdentifierTagNumber._internal(0x01);
static const INTEGER = const ASN1IdentifierTagNumber._internal(0x02);
static const BIT_STRING = const ASN1IdentifierTagNumber._internal(0x03);
static const OCTET_STRING = const ASN1IdentifierTagNumber._internal(0x04);
static const NULL = const ASN1IdentifierTagNumber._internal(0x05);
static const OBJECT_IDENTIFIER = const ASN1IdentifierTagNumber._internal(0x06);
static const OBJECT_DESCRIPTOR = const ASN1IdentifierTagNumber._internal(0x07);
static const EXTERNAL = const ASN1IdentifierTagNumber._internal(0x08);
static const READ = const ASN1IdentifierTagNumber._internal(0x09);
static const ENUMERATED = const ASN1IdentifierTagNumber._internal(0x0A);
static const EMBEDDED_PDV = const ASN1IdentifierTagNumber._internal(0x0B);
static const UTF8_STRING = const ASN1IdentifierTagNumber._internal(0x0C);
static const RELATIVE_OID = const ASN1IdentifierTagNumber._internal(0x0D);
static const SEQUENCE = const ASN1IdentifierTagNumber._internal(0x10);
static const SET = const ASN1IdentifierTagNumber._internal(0x11);
static const NUMERIC_STRING = const ASN1IdentifierTagNumber._internal(0x12);
static const PRINTABLE_STRING = const ASN1IdentifierTagNumber._internal(0x13);
static const T61_STRING = const ASN1IdentifierTagNumber._internal(0x14);
static const VIDEOTEX_STRING = const ASN1IdentifierTagNumber._internal(0x15);
static const IA5_STRING = const ASN1IdentifierTagNumber._internal(0x16);
static const UTC_TIME = const ASN1IdentifierTagNumber._internal(0x17);
static const GENERALIZED_TIME = const ASN1IdentifierTagNumber._internal(0x18);
static const GRAPHIC_STRING = const ASN1IdentifierTagNumber._internal(0x19);
static const VISIBLE_STRING = const ASN1IdentifierTagNumber._internal(0x1A);
static const GENERAL_STRING = const ASN1IdentifierTagNumber._internal(0x1B);
static const UNIVERSAL_STRING = const ASN1IdentifierTagNumber._internal(0x1C);
static const CHARACTER_STRING = const ASN1IdentifierTagNumber._internal(0x1D);
static const BMP_STRING = const ASN1IdentifierTagNumber._internal(0x1E);
static const END_OF_CONTENT = const ASN1IdentifierTagNumber._internal(0x00);
static const BOOLEAN = const ASN1IdentifierTagNumber._internal(0x01);
static const INTEGER = const ASN1IdentifierTagNumber._internal(0x02);
static const BIT_STRING = const ASN1IdentifierTagNumber._internal(0x03);
static const OCTET_STRING = const ASN1IdentifierTagNumber._internal(0x04);
static const NULL = const ASN1IdentifierTagNumber._internal(0x05);
static const OBJECT_IDENTIFIER =
const ASN1IdentifierTagNumber._internal(0x06);
static const OBJECT_DESCRIPTOR =
const ASN1IdentifierTagNumber._internal(0x07);
static const EXTERNAL = const ASN1IdentifierTagNumber._internal(0x08);
static const READ = const ASN1IdentifierTagNumber._internal(0x09);
static const ENUMERATED = const ASN1IdentifierTagNumber._internal(0x0A);
static const EMBEDDED_PDV = const ASN1IdentifierTagNumber._internal(0x0B);
static const UTF8_STRING = const ASN1IdentifierTagNumber._internal(0x0C);
static const RELATIVE_OID = const ASN1IdentifierTagNumber._internal(0x0D);
static const SEQUENCE = const ASN1IdentifierTagNumber._internal(0x10);
static const SET = const ASN1IdentifierTagNumber._internal(0x11);
static const NUMERIC_STRING = const ASN1IdentifierTagNumber._internal(0x12);
static const PRINTABLE_STRING = const ASN1IdentifierTagNumber._internal(0x13);
static const T61_STRING = const ASN1IdentifierTagNumber._internal(0x14);
static const VIDEOTEX_STRING = const ASN1IdentifierTagNumber._internal(0x15);
static const IA5_STRING = const ASN1IdentifierTagNumber._internal(0x16);
static const UTC_TIME = const ASN1IdentifierTagNumber._internal(0x17);
static const GENERALIZED_TIME = const ASN1IdentifierTagNumber._internal(0x18);
static const GRAPHIC_STRING = const ASN1IdentifierTagNumber._internal(0x19);
static const VISIBLE_STRING = const ASN1IdentifierTagNumber._internal(0x1A);
static const GENERAL_STRING = const ASN1IdentifierTagNumber._internal(0x1B);
static const UNIVERSAL_STRING = const ASN1IdentifierTagNumber._internal(0x1C);
static const CHARACTER_STRING = const ASN1IdentifierTagNumber._internal(0x1D);
static const BMP_STRING = const ASN1IdentifierTagNumber._internal(0x1E);
String toString() {
switch (this.toValue()) {
@ -200,11 +206,16 @@ class ASN1Identifier {
}
ASN1IdentifierTagNumber tagNumber() {
return ASN1IdentifierTagNumber.fromValue(rawValue & 0x1F) ?? ASN1IdentifierTagNumber.END_OF_CONTENT;
return ASN1IdentifierTagNumber.fromValue(rawValue & 0x1F) ??
ASN1IdentifierTagNumber.END_OF_CONTENT;
}
ASN1IdentifierClass typeClass() {
for (var tc in [ASN1IdentifierClass.APPLICATION, ASN1IdentifierClass.CONTEXT_SPECIFIC, ASN1IdentifierClass.PRIVATE]) {
for (var tc in [
ASN1IdentifierClass.APPLICATION,
ASN1IdentifierClass.CONTEXT_SPECIFIC,
ASN1IdentifierClass.PRIVATE
]) {
if ((rawValue & tc.toValue()) == tc.toValue()) {
return tc;
}
@ -226,4 +237,4 @@ class ASN1Identifier {
String toString() {
return description;
}
}
}

View File

@ -46,12 +46,12 @@ class ASN1Object {
ASN1Object findOid({OID oid, String oidValue}) {
oidValue = oid != null ? oid.toValue() : oidValue;
for (var child in (sub ?? <ASN1Object>[])) {
if (child.identifier?.tagNumber() == ASN1IdentifierTagNumber.OBJECT_IDENTIFIER) {
if (child.identifier?.tagNumber() ==
ASN1IdentifierTagNumber.OBJECT_IDENTIFIER) {
if (child.value == oidValue) {
return child;
}
}
else {
} else {
var result = child.findOid(oidValue: oidValue);
if (result != null) {
return result;
@ -66,22 +66,23 @@ class ASN1Object {
}
String printAsn1({insets = ""}) {
var output = insets;
output += identifier?.description?.toUpperCase() ?? "";
output += (value != null ? ": $value" : "");
if (identifier?.typeClass() == ASN1IdentifierClass.UNIVERSAL && identifier?.tagNumber() == ASN1IdentifierTagNumber.OBJECT_IDENTIFIER) {
var descr = OID.fromValue(value?.toString() ?? "")?.name();
if (descr != null) {
output += " ($descr)";
}
var output = insets;
output += identifier?.description?.toUpperCase() ?? "";
output += (value != null ? ": $value" : "");
if (identifier?.typeClass() == ASN1IdentifierClass.UNIVERSAL &&
identifier?.tagNumber() == ASN1IdentifierTagNumber.OBJECT_IDENTIFIER) {
var descr = OID.fromValue(value?.toString() ?? "")?.name();
if (descr != null) {
output += " ($descr)";
}
output += sub != null && sub.length > 0 ? " {" : "";
output += "\n";
for (var item in (sub ?? <ASN1Object>[])) {
output += item.printAsn1(insets: insets + " ");
}
output += sub != null && sub.length > 0 ? "}\n" : "";
return output;
}
output += sub != null && sub.length > 0 ? " {" : "";
output += "\n";
for (var item in (sub ?? <ASN1Object>[])) {
output += item.printAsn1(insets: insets + " ");
}
output += sub != null && sub.length > 0 ? "}\n" : "";
return output;
}
@override
@ -95,4 +96,4 @@ class ASN1Object {
}
return null;
}
}
}

View File

@ -16,7 +16,8 @@ class KeyUsage {
].toSet();
static KeyUsage fromIndex(int value) {
return KeyUsage.values.firstWhere((element) => element.toValue() == value, orElse: () => null);
return KeyUsage.values.firstWhere((element) => element.toValue() == value,
orElse: () => null);
}
int toValue() => _value;

View File

@ -103,7 +103,8 @@ class OID {
].toSet();
static OID fromValue(String value) {
return OID.values.firstWhere((element) => element.toValue() == value, orElse: () => null);
return OID.values.firstWhere((element) => element.toValue() == value,
orElse: () => null);
}
String toValue() => _value;
@ -122,29 +123,40 @@ class OID {
static const ecdsaWithSHA256 = const OID._internal("1.2.840.10045.4.3.2");
static const ecdsaWithSHA512 = const OID._internal("1.2.840.10045.4.3.4");
static const rsaEncryption = const OID._internal("1.2.840.113549.1.1.1");
static const md2WithRSAEncryption = const OID._internal("1.2.840.113549.1.1.2");
static const md4WithRSAEncryption = const OID._internal("1.2.840.113549.1.1.3");
static const md5WithRSAEncryption = const OID._internal("1.2.840.113549.1.1.4");
static const sha1WithRSAEncryption = const OID._internal("1.2.840.113549.1.1.5");
static const md2WithRSAEncryption =
const OID._internal("1.2.840.113549.1.1.2");
static const md4WithRSAEncryption =
const OID._internal("1.2.840.113549.1.1.3");
static const md5WithRSAEncryption =
const OID._internal("1.2.840.113549.1.1.4");
static const sha1WithRSAEncryption =
const OID._internal("1.2.840.113549.1.1.5");
static const RSAES_OAEP = const OID._internal("1.2.840.113549.1.1.7");
static const mgf1 = const OID._internal(".2.840.113549.1.1.8");
static const pSpecified = const OID._internal(".2.840.113549.1.1.9");
static const RSASSA_PSS = const OID._internal(".2.840.113549.1.1.10");
static const sha256WithRSAEncryption = const OID._internal("1.2.840.113549.1.1.11");
static const sha384WithRSAEncryption = const OID._internal("1.2.840.113549.1.1.12");
static const sha512WithRSAEncryption = const OID._internal("1.2.840.113549.1.1.13");
static const sha256WithRSAEncryption =
const OID._internal("1.2.840.113549.1.1.11");
static const sha384WithRSAEncryption =
const OID._internal("1.2.840.113549.1.1.12");
static const sha512WithRSAEncryption =
const OID._internal("1.2.840.113549.1.1.13");
static const pkcs7data = const OID._internal("1.2.840.113549.1.7.1");
static const pkcs7signedData = const OID._internal("1.2.840.113549.1.7.2");
static const pkcs7envelopedData = const OID._internal("1.2.840.113549.1.7.3");
static const emailAddress = const OID._internal("1.2.840.113549.1.9.1");
static const signingCertificateV2 = const OID._internal("1.2.840.113549.1.9.16.2.47");
static const signingCertificateV2 =
const OID._internal("1.2.840.113549.1.9.16.2.47");
static const contentType = const OID._internal("1.2.840.113549.1.9.3");
static const messageDigest = const OID._internal("1.2.840.113549.1.9.4");
static const signingTime = const OID._internal("1.2.840.113549.1.9.5");
static const dsaWithSha1 = const OID._internal("1.2.840.10040.4.3");
static const certificateExtension = const OID._internal("1.3.6.1.4.1.11129.2.4.2");
static const jurisdictionOfIncorporationSP = const OID._internal("1.3.6.1.4.1.311.60.2.1.2");
static const jurisdictionOfIncorporationC = const OID._internal("1.3.6.1.4.1.311.60.2.1.3");
static const certificateExtension =
const OID._internal("1.3.6.1.4.1.11129.2.4.2");
static const jurisdictionOfIncorporationSP =
const OID._internal("1.3.6.1.4.1.311.60.2.1.2");
static const jurisdictionOfIncorporationC =
const OID._internal("1.3.6.1.4.1.311.60.2.1.3");
static const authorityInfoAccess = const OID._internal("1.3.6.1.5.5.7.1.1");
static const qcStatements = const OID._internal("1.3.6.1.5.5.7.1.3");
static const cps = const OID._internal("1.3.6.1.5.5.7.2.1");
@ -160,7 +172,8 @@ class OID {
static const sha384 = const OID._internal("2.16.840.1.101.3.4.2.2");
static const sha512 = const OID._internal("2.16.840.1.101.3.4.2.3");
static const md5 = const OID._internal("1.2.840.113549.2.5");
static const VeriSignEVpolicy = const OID._internal("2.16.840.1.113733.1.7.23.6");
static const VeriSignEVpolicy =
const OID._internal("2.16.840.1.113733.1.7.23.6");
static const extendedValidation = const OID._internal("2.23.140.1.1");
static const organizationValidated = const OID._internal("2.23.140.1.2.2");
static const subjectKeyIdentifier = const OID._internal("2.5.29.14");

View File

@ -322,7 +322,11 @@ class X509Certificate {
///Gets the certificate constraints path length from the
///critical BasicConstraints extension, (OID = 2.5.29.19).
int get basicConstraints {
var sub = extensionObject(oid: OID.basicConstraints)?.block?.lastSub()?.lastSub()?.lastSub();
var sub = extensionObject(oid: OID.basicConstraints)
?.block
?.lastSub()
?.lastSub()
?.lastSub();
if (sub != null) {
if (sub.value is List<int>) {
return (sub.value as List<int>).length;
@ -333,31 +337,60 @@ class X509Certificate {
///Gets the raw bits from the Subject Key Identifier (SKID) extension, (OID = 2.5.29.14).
List<int> get subjectKeyIdentifier =>
extensionObject(oid: OID.subjectKeyIdentifier)?.block?.lastSub()?.lastSub()?.value ?? <int>[];
extensionObject(oid: OID.subjectKeyIdentifier)
?.block
?.lastSub()
?.lastSub()
?.value ??
<int>[];
///Gets the raw bits from the Authority Key Identifier extension, (OID = 2.5.29.35).
List<int> get authorityKeyIdentifier =>
extensionObject(oid: OID.authorityKeyIdentifier)?.block?.lastSub()?.lastSub()?.firstSub()?.value ?? <int>[];
extensionObject(oid: OID.authorityKeyIdentifier)
?.block
?.lastSub()
?.lastSub()
?.firstSub()
?.value ??
<int>[];
///Gets the list of certificate policies from the CertificatePolicies extension, (OID = 2.5.29.32).
List<String> get certificatePolicies =>
extensionObject(oid: OID.certificatePolicies)?.block?.lastSub()?.firstSub()?.sub?.map((e) => e.firstSub()?.value as String)?.toList() ?? <String>[];
extensionObject(oid: OID.certificatePolicies)
?.block
?.lastSub()
?.firstSub()
?.sub
?.map((e) => e.firstSub()?.value as String)
?.toList() ??
<String>[];
///Gets the list of CRL distribution points from the CRLDistributionPoints extension, (OID = 2.5.29.31).
List<String> get cRLDistributionPoints =>
extensionObject(oid: OID.cRLDistributionPoints)?.block?.lastSub()?.firstSub()?.sub?.map((e) => e.firstSub()?.firstSub()?.firstSub()?.value as String)?.toList() ?? <String>[];
extensionObject(oid: OID.cRLDistributionPoints)
?.block
?.lastSub()
?.firstSub()
?.sub
?.map((e) => e.firstSub()?.firstSub()?.firstSub()?.value as String)
?.toList() ??
<String>[];
///Gets the map of the format (as a key) and location (as a value) of additional information
///about the CA who issued the certificate in which this extension appears
///from the AuthorityInfoAccess extension, (OID = 1.3.6.1.5.5.5.7.1.1).
Map<String, String> get authorityInfoAccess {
var result = <String, String>{};
var sub = extensionObject(oid: OID.authorityInfoAccess)?.block?.lastSub()?.firstSub()?.sub;
var sub = extensionObject(oid: OID.authorityInfoAccess)
?.block
?.lastSub()
?.firstSub()
?.sub;
if (sub != null) {
sub.forEach((element) {
if (element.subCount() > 1) {
result.putIfAbsent(element.subAtIndex(0).value,
() => element.subAtIndex(1).value);
result.putIfAbsent(
element.subAtIndex(0).value, () => element.subAtIndex(1).value);
}
});
}
@ -413,8 +446,6 @@ class X509Certificate {
result += quote;
}
}
}
}
return result;

View File

@ -52,4 +52,4 @@ class X509Extension {
}
return result;
}
}
}

View File

@ -25,11 +25,13 @@ class X509PublicKey {
} else if (oid == OID.rsaEncryption) {
List<ASN1Object> publicKeyAsn1Objects;
try {
publicKeyAsn1Objects = ASN1DERDecoder.decode(data: keyData.toList(growable: true));
} catch(e) {}
publicKeyAsn1Objects =
ASN1DERDecoder.decode(data: keyData.toList(growable: true));
} catch (e) {}
if (publicKeyAsn1Objects != null && publicKeyAsn1Objects.length > 0) {
var publicKeyModulus = publicKeyAsn1Objects.first?.subAtIndex(0)?.value;
var publicKeyModulus =
publicKeyAsn1Objects.first?.subAtIndex(0)?.value;
if (publicKeyModulus != null) {
return Uint8List.fromList(publicKeyModulus);
}
@ -51,4 +53,4 @@ class X509PublicKey {
Map<String, dynamic> toJson() {
return toMap();
}
}
}

View File

@ -84,7 +84,8 @@ class CookieManager {
expiresDate: cookieListMap[i]["expiresDate"],
isSessionOnly: cookieListMap[i]["isSessionOnly"],
domain: cookieListMap[i]["domain"],
sameSite: HTTPCookieSameSitePolicy.fromValue(cookieListMap[i]["sameSite"]),
sameSite:
HTTPCookieSameSitePolicy.fromValue(cookieListMap[i]["sameSite"]),
isSecure: cookieListMap[i]["isSecure"],
isHttpOnly: cookieListMap[i]["isHttpOnly"],
path: cookieListMap[i]["path"]));
@ -111,7 +112,8 @@ class CookieManager {
expiresDate: cookies[i]["expiresDate"],
isSessionOnly: cookies[i]["isSessionOnly"],
domain: cookies[i]["domain"],
sameSite: HTTPCookieSameSitePolicy.fromValue(cookies[i]["sameSite"]),
sameSite:
HTTPCookieSameSitePolicy.fromValue(cookies[i]["sameSite"]),
isSecure: cookies[i]["isSecure"],
isHttpOnly: cookies[i]["isHttpOnly"],
path: cookies[i]["path"]);

View File

@ -31,7 +31,8 @@ class HttpAuthCredentialDatabase {
///Gets a map list of all HTTP auth credentials saved.
///Each map contains the key `protectionSpace` of type [ProtectionSpace]
///and the key `credentials` of type `List<HttpAuthCredential>` that contains all the HTTP auth credentials saved for that `protectionSpace`.
Future<List<ProtectionSpaceHttpAuthCredentials>> getAllAuthCredentials() async {
Future<List<ProtectionSpaceHttpAuthCredentials>>
getAllAuthCredentials() async {
Map<String, dynamic> args = <String, dynamic>{};
List<dynamic> allCredentials =
await _channel.invokeMethod('getAllAuthCredentials', args);
@ -41,20 +42,17 @@ class HttpAuthCredentialDatabase {
for (Map<dynamic, dynamic> map in allCredentials) {
Map<dynamic, dynamic> protectionSpace = map["protectionSpace"];
List<dynamic> credentials = map["credentials"];
result.add(
ProtectionSpaceHttpAuthCredentials(
protectionSpace: ProtectionSpace(
host: protectionSpace["host"],
protocol: protectionSpace["protocol"],
realm: protectionSpace["realm"],
port: protectionSpace["port"]),
credentials: credentials
.map((credential) => HttpAuthCredential(
result.add(ProtectionSpaceHttpAuthCredentials(
protectionSpace: ProtectionSpace(
host: protectionSpace["host"],
protocol: protectionSpace["protocol"],
realm: protectionSpace["realm"],
port: protectionSpace["port"]),
credentials: credentials
.map((credential) => HttpAuthCredential(
username: credential["username"],
password: credential["password"]))
.toList()
)
);
.toList()));
}
return result;
}

View File

@ -291,7 +291,7 @@ class _InAppWebViewState extends State<InAppWebView> {
if (gestureRecognizers == null) {
gestureRecognizers = <Factory<OneSequenceGestureRecognizer>>[
Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer(),
() => EagerGestureRecognizer(),
),
].toSet();
}

View File

@ -69,7 +69,8 @@ class InAppWebViewController {
this._webview = webview;
this.android = AndroidInAppWebViewController(this);
this.ios = IOSInAppWebViewController(this);
this.webStorage = WebStorage(localStorage: LocalStorage(this), sessionStorage: SessionStorage(this));
this.webStorage = WebStorage(
localStorage: LocalStorage(this), sessionStorage: SessionStorage(this));
}
InAppWebViewController.fromInAppBrowser(
@ -369,29 +370,45 @@ class InAppWebViewController {
int androidError = call.arguments["androidError"];
int iosError = call.arguments["iosError"];
String message = call.arguments["message"];
Map<String, dynamic> sslCertificateMap = call.arguments["sslCertificate"]?.cast<String, dynamic>();
Map<String, dynamic> sslCertificateMap =
call.arguments["sslCertificate"]?.cast<String, dynamic>();
SslCertificate sslCertificate;
if (sslCertificateMap != null) {
if (Platform.isIOS) {
try {
X509Certificate x509certificate = X509Certificate.fromData(data: sslCertificateMap["x509Certificate"]);
X509Certificate x509certificate = X509Certificate.fromData(
data: sslCertificateMap["x509Certificate"]);
sslCertificate = SslCertificate(
issuedBy: SslCertificateDName(
CName: x509certificate.issuer(dn: ASN1DistinguishedNames.COMMON_NAME) ?? "",
CName: x509certificate.issuer(
dn: ASN1DistinguishedNames.COMMON_NAME) ??
"",
DName: x509certificate.issuerDistinguishedName ?? "",
OName: x509certificate.issuer(dn: ASN1DistinguishedNames.ORGANIZATION_NAME) ?? "",
UName: x509certificate.issuer(dn: ASN1DistinguishedNames.ORGANIZATIONAL_UNIT_NAME) ?? ""),
OName: x509certificate.issuer(
dn: ASN1DistinguishedNames.ORGANIZATION_NAME) ??
"",
UName: x509certificate.issuer(
dn: ASN1DistinguishedNames
.ORGANIZATIONAL_UNIT_NAME) ??
""),
issuedTo: SslCertificateDName(
CName: x509certificate.subject(dn: ASN1DistinguishedNames.COMMON_NAME) ?? "",
CName: x509certificate.subject(
dn: ASN1DistinguishedNames.COMMON_NAME) ??
"",
DName: x509certificate.subjectDistinguishedName ?? "",
OName: x509certificate.subject(dn: ASN1DistinguishedNames.ORGANIZATION_NAME) ?? "",
UName: x509certificate.subject(dn: ASN1DistinguishedNames.ORGANIZATIONAL_UNIT_NAME) ?? ""),
OName: x509certificate.subject(
dn: ASN1DistinguishedNames.ORGANIZATION_NAME) ??
"",
UName: x509certificate.subject(
dn: ASN1DistinguishedNames
.ORGANIZATIONAL_UNIT_NAME) ??
""),
validNotAfterDate: x509certificate.notAfter,
validNotBeforeDate: x509certificate.notBefore,
x509Certificate: x509certificate,
);
} catch(e, stacktrace) {
} catch (e, stacktrace) {
print(e);
print(stacktrace);
return null;
@ -401,8 +418,11 @@ class InAppWebViewController {
}
}
AndroidSslError androidSslError = androidError != null ? AndroidSslError.fromValue(androidError) : null;
IOSSslError iosSslError = iosError != null ? IOSSslError.fromValue(iosError) : null;
AndroidSslError androidSslError = androidError != null
? AndroidSslError.fromValue(androidError)
: null;
IOSSslError iosSslError =
iosError != null ? IOSSslError.fromValue(iosError) : null;
var protectionSpace = ProtectionSpace(
host: host, protocol: protocol, realm: realm, port: port);
@ -884,8 +904,7 @@ class InAppWebViewController {
InAppWebViewGroupOptions options = await getOptions();
if (options != null && options.crossPlatform.javaScriptEnabled == true) {
List<Map<dynamic, dynamic>> links = (await evaluateJavascript(
source: """
List<Map<dynamic, dynamic>> links = (await evaluateJavascript(source: """
(function() {
var linkNodes = document.head.getElementsByTagName("link");
var links = [];
@ -920,8 +939,8 @@ class InAppWebViewController {
manifestUrl = manifestUrl.substring(1);
}
manifestUrl = ((assetPathBase == null)
? url.scheme + "://" + url.host + "/"
: assetPathBase) +
? url.scheme + "://" + url.host + "/"
: assetPathBase) +
manifestUrl;
}
continue;
@ -1466,7 +1485,8 @@ class InAppWebViewController {
///
///**Official Android API**: https://developer.android.com/reference/android/view/View#scrollTo(int,%20int)
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619400-setcontentoffset
Future<void> scrollTo({@required int x, @required int y, bool animated = false}) async {
Future<void> scrollTo(
{@required int x, @required int y, bool animated = false}) async {
assert(x != null && y != null);
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('x', () => x);
@ -1485,7 +1505,8 @@ class InAppWebViewController {
///
///**Official Android API**: https://developer.android.com/reference/android/view/View#scrollBy(int,%20int)
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619400-setcontentoffset
Future<void> scrollBy({@required int x, @required int y, bool animated = false}) async {
Future<void> scrollBy(
{@required int x, @required int y, bool animated = false}) async {
assert(x != null && y != null);
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('x', () => x);
@ -1544,7 +1565,8 @@ class InAppWebViewController {
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#zoomBy(float)
///**Official iOS API**: https://developer.apple.com/documentation/uikit/uiscrollview/1619412-setzoomscale
Future<void> zoomBy(double zoomFactor) async {
assert(!Platform.isAndroid || (Platform.isAndroid && zoomFactor > 0.01 && zoomFactor <= 100.0));
assert(!Platform.isAndroid ||
(Platform.isAndroid && zoomFactor > 0.01 && zoomFactor <= 100.0));
Map<String, dynamic> args = <String, dynamic>{};
args.putIfAbsent('zoomFactor', () => zoomFactor);
@ -1611,12 +1633,15 @@ class InAppWebViewController {
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#requestFocusNodeHref(android.os.Message)
Future<RequestFocusNodeHrefResult> requestFocusNodeHref() async {
Map<String, dynamic> args = <String, dynamic>{};
Map<dynamic, dynamic> result = await _channel.invokeMethod('requestFocusNodeHref', args);
return result != null ? RequestFocusNodeHrefResult(
url: result['url'],
title: result['title'],
src: result['src'],
) : null;
Map<dynamic, dynamic> result =
await _channel.invokeMethod('requestFocusNodeHref', args);
return result != null
? RequestFocusNodeHrefResult(
url: result['url'],
title: result['title'],
src: result['src'],
)
: null;
}
///Requests the URL of the image last touched by the user.
@ -1626,10 +1651,13 @@ class InAppWebViewController {
///**Official Android API**: https://developer.android.com/reference/android/webkit/WebView#requestImageRef(android.os.Message)
Future<RequestImageRefResult> requestImageRef() async {
Map<String, dynamic> args = <String, dynamic>{};
Map<dynamic, dynamic> result = await _channel.invokeMethod('requestImageRef', args);
return result != null ? RequestImageRefResult(
url: result['url'],
) : null;
Map<dynamic, dynamic> result =
await _channel.invokeMethod('requestImageRef', args);
return result != null
? RequestImageRefResult(
url: result['url'],
)
: null;
}
///Returns the list of `<meta>` tags of the current WebView.
@ -1638,7 +1666,8 @@ class InAppWebViewController {
Future<List<MetaTag>> getMetaTags() async {
List<MetaTag> metaTags = [];
List<Map<dynamic, dynamic>> metaTagList = (await evaluateJavascript(source: """
List<Map<dynamic, dynamic>> metaTagList =
(await evaluateJavascript(source: """
(function() {
var metaTags = [];
var metaTagNodes = document.head.getElementsByTagName('meta');
@ -1682,14 +1711,12 @@ class InAppWebViewController {
var attrs = <MetaTagAttribute>[];
for (var metaTagAttr in metaTag["attrs"]) {
attrs.add(
MetaTagAttribute(name: metaTagAttr["name"], value: metaTagAttr["value"])
);
attrs.add(MetaTagAttribute(
name: metaTagAttr["name"], value: metaTagAttr["value"]));
}
metaTags.add(
MetaTag(name: metaTag["name"], content: metaTag["content"], attrs: attrs)
);
metaTags.add(MetaTag(
name: metaTag["name"], content: metaTag["content"], attrs: attrs));
}
return metaTags;
@ -1743,28 +1770,43 @@ class InAppWebViewController {
Future<SslCertificate> getCertificate() async {
Map<String, dynamic> args = <String, dynamic>{};
Map<String, dynamic> sslCertificateMap = (await _channel.invokeMethod('getCertificate', args))?.cast<String, dynamic>();
Map<String, dynamic> sslCertificateMap =
(await _channel.invokeMethod('getCertificate', args))
?.cast<String, dynamic>();
if (sslCertificateMap != null) {
if (Platform.isIOS) {
try {
X509Certificate x509certificate = X509Certificate.fromData(data: sslCertificateMap["x509Certificate"]);
X509Certificate x509certificate = X509Certificate.fromData(
data: sslCertificateMap["x509Certificate"]);
return SslCertificate(
issuedBy: SslCertificateDName(
CName: x509certificate.issuer(dn: ASN1DistinguishedNames.COMMON_NAME) ?? "",
CName: x509certificate.issuer(
dn: ASN1DistinguishedNames.COMMON_NAME) ??
"",
DName: x509certificate.issuerDistinguishedName ?? "",
OName: x509certificate.issuer(dn: ASN1DistinguishedNames.ORGANIZATION_NAME) ?? "",
UName: x509certificate.issuer(dn: ASN1DistinguishedNames.ORGANIZATIONAL_UNIT_NAME) ?? ""),
OName: x509certificate.issuer(
dn: ASN1DistinguishedNames.ORGANIZATION_NAME) ??
"",
UName: x509certificate.issuer(
dn: ASN1DistinguishedNames.ORGANIZATIONAL_UNIT_NAME) ??
""),
issuedTo: SslCertificateDName(
CName: x509certificate.subject(dn: ASN1DistinguishedNames.COMMON_NAME) ?? "",
CName: x509certificate.subject(
dn: ASN1DistinguishedNames.COMMON_NAME) ??
"",
DName: x509certificate.subjectDistinguishedName ?? "",
OName: x509certificate.subject(dn: ASN1DistinguishedNames.ORGANIZATION_NAME) ?? "",
UName: x509certificate.subject(dn: ASN1DistinguishedNames.ORGANIZATIONAL_UNIT_NAME) ?? ""),
OName: x509certificate.subject(
dn: ASN1DistinguishedNames.ORGANIZATION_NAME) ??
"",
UName: x509certificate.subject(
dn: ASN1DistinguishedNames.ORGANIZATIONAL_UNIT_NAME) ??
""),
validNotAfterDate: x509certificate.notAfter,
validNotBeforeDate: x509certificate.notBefore,
x509Certificate: x509certificate,
);
} catch(e, stacktrace) {
} catch (e, stacktrace) {
print(e);
print(stacktrace);
return null;

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,6 @@ class Util {
} else if (colorValue.startsWith("hlsa(")) {
return Util.getColorFromHlsaString(colorValue);
} else {
/**
This part of the code is generated using the JavaScript code below on this link: https://drafts.csswg.org/css-color/#typedef-color
@ -33,7 +32,7 @@ class Util {
code += '}';
*/
switch(colorValue) {
switch (colorValue) {
case "aliceblue":
return Util.getColorFromHex("#f0f8ff");
case "antiquewhite":
@ -337,8 +336,10 @@ class Util {
static Color getColorFromHex(String hexString) {
hexString = hexString.trim();
if (hexString.length == 4) { // convert for example #f00 to #ff0000
hexString = "#" + (hexString[1] * 2) + (hexString[2] * 2) + (hexString[3] * 2);
if (hexString.length == 4) {
// convert for example #f00 to #ff0000
hexString =
"#" + (hexString[1] * 2) + (hexString[2] * 2) + (hexString[3] * 2);
}
final buffer = StringBuffer();
if (hexString.length == 6 || hexString.length == 7) buffer.write('ff');
@ -363,7 +364,8 @@ class Util {
.split(",")
.map((rbgValue) => rbgValue.trim())
.toList();
return Color.fromRGBO(int.parse(rgbaValues[0]), int.parse(rgbaValues[1]), int.parse(rgbaValues[2]), double.parse(rgbaValues[3]));
return Color.fromRGBO(int.parse(rgbaValues[0]), int.parse(rgbaValues[1]),
int.parse(rgbaValues[2]), double.parse(rgbaValues[3]));
}
static Color getColorFromHlsString(String hlsString) {
@ -385,10 +387,11 @@ class Util {
.map((rbgValue) => double.parse(rbgValue.trim()))
.toList();
var rgbaValues = hslToRgb(hlsaValues[0], hlsaValues[1], hlsaValues[2]);
return Color.fromRGBO(rgbaValues[0], rgbaValues[1], rgbaValues[2], hlsaValues[3]);
return Color.fromRGBO(
rgbaValues[0], rgbaValues[1], rgbaValues[2], hlsaValues[3]);
}
static List<num> hslToRgb(double h, double s, double l){
static List<num> hslToRgb(double h, double s, double l) {
double r, g, b;
if (s == 0) {
@ -396,30 +399,25 @@ class Util {
} else {
double q = l < 0.5 ? l * (1 + s) : l + s - l * s;
double p = 2 * l - q;
r = hueToRgb(p, q, h + 1/3);
r = hueToRgb(p, q, h + 1 / 3);
g = hueToRgb(p, q, h);
b = hueToRgb(p, q, h - 1/3);
b = hueToRgb(p, q, h - 1 / 3);
}
var rgb = [to255(r), to255(g), to255(b)];
return rgb;
}
static num to255(double v) {
return min(255, 256*v);
return min(255, 256 * v);
}
/// Helper method that converts hue to rgb
static double hueToRgb(double p, double q, double t) {
if (t < 0)
t += 1;
if (t > 1)
t -= 1;
if (t < 1/6)
return p + (q - p) * 6 * t;
if (t < 1/2)
return q;
if (t < 2/3)
return p + (q - p) * (2/3 - t) * 6;
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
}
}

View File

@ -54,7 +54,7 @@ class Storage {
Future<void> setItem({@required String key, @required dynamic value}) async {
var encodedValue = json.encode(value);
await _controller.evaluateJavascript(source: """
window.$webStorageType.setItem("$key", ${ value is String ? encodedValue : "JSON.stringify($encodedValue)" });
window.$webStorageType.setItem("$key", ${value is String ? encodedValue : "JSON.stringify($encodedValue)"});
""");
}
@ -81,10 +81,10 @@ class Storage {
}
Future<List<WebStorageItem>> getItems() async {
var webStorageItems = <WebStorageItem>[];
List<Map<dynamic, dynamic>> items = (await _controller.evaluateJavascript(source: """
List<Map<dynamic, dynamic>> items =
(await _controller.evaluateJavascript(source: """
(function() {
var webStorageItems = [];
for(var i = 0; i < window.$webStorageType.length; i++){
@ -105,9 +105,8 @@ class Storage {
}
for (var item in items) {
webStorageItems.add(
WebStorageItem(key: item["key"], value: item["value"])
);
webStorageItems
.add(WebStorageItem(key: item["key"], value: item["value"]));
}
return webStorageItems;
@ -128,9 +127,11 @@ class Storage {
}
class LocalStorage extends Storage {
LocalStorage(InAppWebViewController controller) : super(controller, WebStorageType.LOCAL_STORAGE);
LocalStorage(InAppWebViewController controller)
: super(controller, WebStorageType.LOCAL_STORAGE);
}
class SessionStorage extends Storage {
SessionStorage(InAppWebViewController controller) : super(controller, WebStorageType.SESSION_STORAGE);
SessionStorage(InAppWebViewController controller)
: super(controller, WebStorageType.SESSION_STORAGE);
}

View File

@ -838,7 +838,8 @@ class IOSInAppWebViewOptions
this.isPagingEnabled = false,
this.maximumZoomScale = 1.0,
this.minimumZoomScale = 1.0,
this.contentInsetAdjustmentBehavior = IOSUIScrollViewContentInsetAdjustmentBehavior.NEVER});
this.contentInsetAdjustmentBehavior =
IOSUIScrollViewContentInsetAdjustmentBehavior.NEVER});
@override
Map<String, dynamic> toMap() {