├── .github ├── FUNDING.yml └── workflows │ └── dart.yml ├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── analysis_options.yaml ├── example ├── elliptic_curve.dart └── main.dart ├── lib ├── basic_utils.dart └── src │ ├── Asn1Utils.dart │ ├── BooleanUtils.dart │ ├── ColorUtils.dart │ ├── CryptoUtils.dart │ ├── DateUtils.dart │ ├── DnsUtils.dart │ ├── DomainUtils.dart │ ├── EmailUtils.dart │ ├── EnumUtils.dart │ ├── FunctionDefs.dart │ ├── HttpUtils.dart │ ├── IterableUtils.dart │ ├── MathUtils.dart │ ├── SortUtils.dart │ ├── StringUtils.dart │ ├── X509Utils.dart │ ├── hex_utils.dart │ ├── library │ ├── IDNAConverter.dart │ └── crypto │ │ ├── pss_signer.dart │ │ └── ufixnum.dart │ ├── model │ ├── CountryCodeList.dart │ ├── DnsApiProvider.dart │ ├── Domain.dart │ ├── EmailAddress.dart │ ├── GtldList.dart │ ├── HttpRequestReturnType.dart │ ├── IdnCountryCodeList.dart │ ├── LengthUnits.dart │ ├── PublicSuffix.dart │ ├── Question.dart │ ├── Question.g.dart │ ├── RRecord.dart │ ├── RRecord.g.dart │ ├── RRecordType.dart │ ├── ResolveResponse.dart │ ├── ResolveResponse.g.dart │ ├── asn1 │ │ ├── ASN1DumpLine.dart │ │ ├── ASN1DumpWrapper.dart │ │ ├── ASN1ObjectType.dart │ │ └── pkcs5s1_parameter_generator.dart │ ├── crl │ │ ├── CertificateListData.dart │ │ ├── CertificateRevokeListData.dart │ │ ├── CrlEntryExtensionsData.dart │ │ ├── CrlExtensions.dart │ │ ├── CrlReason.dart │ │ └── RevokedCertificate.dart │ ├── csr │ │ ├── CertificateSigningRequestData.dart │ │ ├── CertificateSigningRequestData.g.dart │ │ ├── CertificateSigningRequestExtensions.dart │ │ ├── CertificateSigningRequestExtensions.g.dart │ │ ├── CertificationRequestInfo.dart │ │ ├── CertificationRequestInfo.g.dart │ │ ├── SubjectPublicKeyInfo.dart │ │ └── SubjectPublicKeyInfo.g.dart │ ├── exception │ │ └── HttpResponseException.dart │ ├── ocsp │ │ ├── BasicOCSPResponse.dart │ │ ├── OCSPCertStatus.dart │ │ ├── OCSPCertStatusValues.dart │ │ ├── OCSPResponse.dart │ │ ├── OCSPResponseData.dart │ │ ├── OCSPResponseStatus.dart │ │ └── OCSPSingleResponse.dart │ ├── pkcs7 │ │ ├── Pkcs7CertificateData.dart │ │ └── Pkcs7CertificateData.g.dart │ └── x509 │ │ ├── CertificateChainCheckData.dart │ │ ├── CertificateChainPairCheckResult.dart │ │ ├── ExtendedKeyUsage.dart │ │ ├── KeyUsage.dart │ │ ├── TbsCertificate.dart │ │ ├── TbsCertificate.g.dart │ │ ├── VmcData.dart │ │ ├── VmcData.g.dart │ │ ├── X509CertificateData.dart │ │ ├── X509CertificateData.g.dart │ │ ├── X509CertificateDataExtensions.dart │ │ ├── X509CertificateDataExtensions.g.dart │ │ ├── X509CertificateObject.dart │ │ ├── X509CertificateObject.g.dart │ │ ├── X509CertificatePublicKeyData.dart │ │ ├── X509CertificatePublicKeyData.g.dart │ │ ├── X509CertificateValidity.dart │ │ └── X509CertificateValidity.g.dart │ └── pkcs12_utils.dart ├── main_test.dart ├── object_identifiers.csv ├── pubspec.lock ├── pubspec.yaml ├── test ├── asn1_utils_test.dart ├── boolean_utils_test.dart ├── color_utils_test.dart ├── crypto_utils_test.dart ├── date_utils_test.dart ├── dns_utils_test.dart ├── domain_utils_test.dart ├── email_utils_test.dart ├── enum_utils_test.dart ├── hex_utils_test.dart ├── http_utils_test.dart ├── iterable_utils_test.dart ├── math_utils_test.dart ├── pkcs12_utils_test.dart ├── sort_utils_test.dart ├── string_utils_test.dart └── x509_utils_test.dart └── test_resources ├── RapidSSLTLSRSACAG1.crl ├── RapidSSLTLSRSACAG1.pem ├── github_com_cert_chain.pem ├── rapid_ssl_broken_chain.pem └── test_dump.txt /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ['https://www.paypal.me/ephenodrom'] 13 | -------------------------------------------------------------------------------- /.github/workflows/dart.yml: -------------------------------------------------------------------------------- 1 | name: Dart CI 2 | 3 | on: [push] 4 | 5 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 6 | jobs: 7 | # This workflow contains a single job called "build" 8 | build: 9 | # The type of runner that the job will run on 10 | runs-on: ubuntu-latest 11 | 12 | # Steps represent a sequence of tasks that will be executed as part of the job 13 | steps: 14 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 15 | - uses: actions/checkout@v3 16 | - uses: dart-lang/setup-dart@v1 17 | 18 | - name: Install dependencies 19 | run: dart pub get 20 | 21 | - name: Test dartvm 22 | run: dart run test 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_Store 3 | .dart_tool/ 4 | 5 | .packages 6 | .pub/ 7 | 8 | build/ 9 | ios/.generated/ 10 | ios/Flutter/Generated.xcconfig 11 | ios/Runner/GeneratedPluginRegistrant.* 12 | 13 | res 14 | lib/generated 15 | node_modules 16 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: beta 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Ephenodrom 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:pedantic/analysis_options.yaml -------------------------------------------------------------------------------- /example/elliptic_curve.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:typed_data'; 3 | 4 | import 'package:basic_utils/src/CryptoUtils.dart'; 5 | import 'package:pointycastle/ecc/api.dart'; 6 | 7 | void main() { 8 | // generate key pairs 9 | var ec = CryptoUtils.generateEcKeyPair(curve: 'secp256k1'); 10 | var privKey = ec.privateKey as ECPrivateKey; 11 | var pubKey = ec.publicKey as ECPublicKey; 12 | 13 | // convert to pem 14 | var privKeyPem = CryptoUtils.encodeEcPrivateKeyToPem(privKey); 15 | var pubKeyPem = CryptoUtils.encodeEcPublicKeyToPem(pubKey); 16 | 17 | print('PrivKey PEM:\n$privKeyPem'); 18 | print('PubKey PEM:\n$pubKeyPem'); 19 | 20 | // convert pem to base64 21 | var pubKeyBase64 = base64Encode(pubKeyPem.codeUnits); 22 | print('PubKey base64: $pubKeyBase64'); 23 | 24 | // decode keys from pem 25 | var decodedPrivKey = CryptoUtils.ecPrivateKeyFromPem(privKeyPem); 26 | var decodedPubKey = CryptoUtils.ecPublicKeyFromPem(pubKeyPem); 27 | 28 | // sign message 29 | var message = Uint8List.fromList('Hello world!'.codeUnits); 30 | var signature = CryptoUtils.ecSign(decodedPrivKey, message, 31 | algorithmName: 'SHA-256/ECDSA'); // can be SHA-256/ECDSA or other 32 | var encodedSignature = CryptoUtils.ecSignatureToBase64(signature); 33 | print('Signature in base64: $encodedSignature'); 34 | 35 | // verify message using ECSignature 36 | var isVerifiedByECSignature = CryptoUtils.ecVerify( 37 | decodedPubKey, message, signature, 38 | algorithm: 'SHA-256/ECDSA'); 39 | print('ECSignature verification result: $isVerifiedByECSignature'); 40 | 41 | // verify message using signature in base64 42 | var isVerifiedByBase64Signature = CryptoUtils.ecVerifyBase64( 43 | decodedPubKey, message, encodedSignature, 44 | algorithm: 'SHA-256/ECDSA'); 45 | print('Base64Signature verification result: $isVerifiedByBase64Signature'); 46 | } 47 | -------------------------------------------------------------------------------- /example/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/basic_utils.dart'; 2 | 3 | void main() async { 4 | // StringUtils 5 | // print('Convert to lowercase underscore: ' + 6 | // StringUtils.camelCaseToLowerUnderscore('camelCase')); 7 | // print('Is lowercase: ' + StringUtils.isLowerCase('lowercase').toString()); 8 | // print('Is uppercase: ' + StringUtils.isUpperCase('UPPERCASE').toString()); 9 | // print('Is ascii: ' + StringUtils.isAscii('Hello').toString()); 10 | // print( 11 | // 'Is null or empty: ' + StringUtils.isNullOrEmpty('notempty').toString()); 12 | 13 | // // DomainUtils 14 | // print('Is dartlang.org a domain name? ' + 15 | // DomainUtils.isDomainName('dartlang.org').toString()); 16 | // var domain = DomainUtils.parseDomain('dartlang.org')!; 17 | // print('Sld = ' + domain.sld! + ' & tld = ' + domain.tld!); 18 | 19 | // // EmailUtils 20 | // print('Is hello@world.com an email ? ' + 21 | // EmailUtils.isEmail('hello@world.com').toString()); 22 | 23 | // // MathUtils 24 | // print('1 km is ' + 25 | // MathUtils.convertUnit(1, LengthUnits.kilometer, LengthUnits.meter) 26 | // .toString() + 27 | // ' meter.'); 28 | // 29 | print(StringUtils.removeCharAtPosition('flutterr', 8)); 30 | print(StringUtils.pickOnly('123456789', from: 3, to: 7)); 31 | 32 | print(StringUtils.removeExp('Hello This World', 'This')); 33 | print(StringUtils.truncate('This is a Dart Utility Library', 26)); 34 | 35 | print(StringUtils.generateRandomString(15)); 36 | print(MathUtils.getRandomNumber().toString()); 37 | } 38 | -------------------------------------------------------------------------------- /lib/basic_utils.dart: -------------------------------------------------------------------------------- 1 | library basic_utils; 2 | 3 | /// Export model and other stuff 4 | export 'src/model/CountryCodeList.dart'; 5 | export 'src/model/Domain.dart'; 6 | export 'src/model/EmailAddress.dart'; 7 | export 'src/model/GtldList.dart'; 8 | export 'src/model/IdnCountryCodeList.dart'; 9 | export 'src/model/PublicSuffix.dart'; 10 | export 'src/model/LengthUnits.dart'; 11 | export 'src/model/exception/HttpResponseException.dart'; 12 | export 'src/model/RRecordType.dart'; 13 | export 'src/model/RRecord.dart'; 14 | export 'src/model/ResolveResponse.dart'; 15 | export 'src/model/HttpRequestReturnType.dart'; 16 | export 'src/model/pkcs7/Pkcs7CertificateData.dart'; 17 | export 'src/model/x509/X509CertificateData.dart'; 18 | export 'src/model/x509/X509CertificateObject.dart'; 19 | export 'src/model/x509/VmcData.dart'; 20 | export 'src/model/x509/X509CertificateDataExtensions.dart'; 21 | export 'src/model/x509/X509CertificateValidity.dart'; 22 | export 'src/model/x509/ExtendedKeyUsage.dart'; 23 | export 'src/model/x509/KeyUsage.dart'; 24 | export 'src/model/csr/CertificateSigningRequestData.dart'; 25 | export 'src/model/csr/CertificateSigningRequestExtensions.dart'; 26 | export 'src/model/x509/X509CertificatePublicKeyData.dart'; 27 | export 'src/model/DnsApiProvider.dart'; 28 | export 'src/model/x509/CertificateChainCheckData.dart'; 29 | export 'src/model/x509/CertificateChainPairCheckResult.dart'; 30 | export 'src/model/x509/TbsCertificate.dart'; 31 | export 'src/model/csr/CertificationRequestInfo.dart'; 32 | export 'src/model/csr/SubjectPublicKeyInfo.dart'; 33 | 34 | /// ASN1 35 | export 'src/model/asn1/ASN1DumpLine.dart'; 36 | export 'src/model/asn1/ASN1DumpWrapper.dart'; 37 | export 'src/model/asn1/ASN1ObjectType.dart'; 38 | 39 | /// OCSP 40 | export 'src/model/ocsp/BasicOCSPResponse.dart'; 41 | export 'src/model/ocsp/OCSPCertStatus.dart'; 42 | export 'src/model/ocsp/OCSPCertStatusValues.dart'; 43 | export 'src/model/ocsp/OCSPResponse.dart'; 44 | export 'src/model/ocsp/OCSPResponseData.dart'; 45 | export 'src/model/ocsp/OCSPResponseStatus.dart'; 46 | export 'src/model/ocsp/OCSPSingleResponse.dart'; 47 | 48 | /// CRL 49 | export 'src/model/crl/CertificateListData.dart'; 50 | export 'src/model/crl/CertificateRevokeListData.dart'; 51 | export 'src/model/crl/CrlEntryExtensionsData.dart'; 52 | export 'src/model/crl/CrlExtensions.dart'; 53 | export 'src/model/crl/CrlReason.dart'; 54 | export 'src/model/crl/RevokedCertificate.dart'; 55 | 56 | /// Export util classes 57 | export 'src/DomainUtils.dart'; 58 | export 'src/EmailUtils.dart'; 59 | export 'src/StringUtils.dart'; 60 | export 'src/MathUtils.dart'; 61 | export 'src/HttpUtils.dart'; 62 | export 'src/DnsUtils.dart'; 63 | export 'src/SortUtils.dart'; 64 | export 'src/ColorUtils.dart'; 65 | export 'src/DateUtils.dart'; 66 | export 'src/X509Utils.dart'; 67 | export 'src/IterableUtils.dart'; 68 | export 'src/CryptoUtils.dart'; 69 | export 'src/Asn1Utils.dart'; 70 | export 'src/FunctionDefs.dart'; 71 | export 'src/EnumUtils.dart'; 72 | export 'src/pkcs12_utils.dart'; 73 | export 'src/hex_utils.dart'; 74 | export 'src/BooleanUtils.dart'; 75 | 76 | // Export other libraries 77 | export 'package:pointycastle/ecc/api.dart'; 78 | export 'package:pointycastle/asymmetric/api.dart'; 79 | export 'package:pointycastle/api.dart' hide Padding; 80 | -------------------------------------------------------------------------------- /lib/src/BooleanUtils.dart: -------------------------------------------------------------------------------- 1 | /// 2 | /// Utility library to provide helper methods for Dart boolean. 3 | /// 4 | class BooleanUtils { 5 | /// The false String "false" 6 | static final String FALSE = 'false'; 7 | 8 | /// The true String "true" 9 | static final String TRUE = 'true'; 10 | 11 | /// Performs an 'and' operation on a set of booleans. 12 | /// 13 | /// Example 14 | /// BooleanUtils.and([true, true]) = true 15 | /// BooleanUtils.and([false, false]) = false 16 | /// BooleanUtils.and([true, false]) = false 17 | /// BooleanUtils.and([true, true, false]) = false 18 | /// BooleanUtils.and([true, true, true]) = true 19 | static bool and(final List array) { 20 | for (final element in array) { 21 | if (!element) { 22 | return false; 23 | } 24 | } 25 | return true; 26 | } 27 | 28 | /// Performs an 'or' operation on a set of booleans. 29 | /// 30 | /// BooleanUtils.or(true, true) = true 31 | /// BooleanUtils.or(false, false) = false 32 | /// BooleanUtils.or(true, false) = true 33 | /// BooleanUtils.or(true, true, false) = true 34 | /// BooleanUtils.or(true, true, true) = true 35 | /// BooleanUtils.or(false, false, false) = false 36 | static bool or(final List array) { 37 | for (final element in array) { 38 | if (element) { 39 | return true; 40 | } 41 | } 42 | return false; 43 | } 44 | 45 | /// Performs an xor on a set of booleans. 46 | /// 47 | /// BooleanUtils.xor([true, true]) = false 48 | /// BooleanUtils.xor([false, false]) = false 49 | /// BooleanUtils.xor([true, false]) = true 50 | static bool xor(final List array) { 51 | // false if the neutral element of the xor operator 52 | var result = false; 53 | for (final element in array) { 54 | result ^= element; 55 | } 56 | 57 | return result; 58 | } 59 | 60 | /// Returns a new list of possible values (like an enum would). 61 | static List booleanValues() { 62 | return [false, true]; 63 | } 64 | 65 | /// Compares two boolean values 66 | static int compare(final bool x, final bool y) { 67 | if (x == y) { 68 | return 0; 69 | } 70 | return x ? 1 : -1; 71 | } 72 | 73 | /// Converts an int to a boolean using the convention that zero 74 | /// is false, everything else is true. 75 | /// 76 | /// BooleanUtils.toBoolean(0) = false 77 | /// BooleanUtils.toBoolean(1) = true 78 | /// BooleanUtils.toBoolean(2) = true 79 | static bool toBoolean(final int value) { 80 | return value != 0; 81 | } 82 | 83 | /// Converts a String to a Boolean. 84 | /// 85 | /// 'true', 'on', 'y', 't', 'yes' 86 | /// or '1' (case insensitive) will return true. 87 | /// 'false', 'off', 'n', 'f', 'no' 88 | /// or '0' (case insensitive) will return false. 89 | /// Otherwise, null is returned. 90 | /// 91 | /// NOTE: This method may return null and may throw a NullPointerException 92 | /// if unboxed to a boolean 93 | /// 94 | /// // N.B. case is not significant 95 | /// BooleanUtils.toBooleanObject(null) = null 96 | /// BooleanUtils.toBooleanObject("true") = true 97 | /// BooleanUtils.toBooleanObject("T") = true 98 | /// BooleanUtils.toBooleanObject("false") = false 99 | /// BooleanUtils.toBooleanObject("f") = false 100 | /// BooleanUtils.toBooleanObject("No") = false 101 | /// BooleanUtils.toBooleanObject("n") = false 102 | /// BooleanUtils.toBooleanObject("on") = true 103 | /// BooleanUtils.toBooleanObject("ON") = true 104 | /// BooleanUtils.toBooleanObject("off") = false 105 | /// BooleanUtils.toBooleanObject("oFf") = false 106 | /// BooleanUtils.toBooleanObject("yes") = true 107 | /// BooleanUtils.toBooleanObject("Y") = true 108 | /// BooleanUtils.toBooleanObject("1") = true 109 | /// BooleanUtils.toBooleanObject("0") = false 110 | /// BooleanUtils.toBooleanObject("blue") = null 111 | /// BooleanUtils.toBooleanObject("true ") = null // trailing space (too long) 112 | /// BooleanUtils.toBooleanObject("ono") = null // does not match on or no 113 | static bool toBooleanObject(final String? str) { 114 | if (str == TRUE) { 115 | return true; 116 | } 117 | if (str == FALSE) { 118 | return false; 119 | } 120 | if (str == null) { 121 | return false; 122 | } 123 | switch (str.length) { 124 | case 1: 125 | { 126 | final ch0 = str[0]; 127 | if (ch0 == 'y' || 128 | ch0 == 'Y' || 129 | ch0 == 't' || 130 | ch0 == 'T' || 131 | ch0 == '1') { 132 | return true; 133 | } 134 | if (ch0 == 'n' || 135 | ch0 == 'N' || 136 | ch0 == 'f' || 137 | ch0 == 'F' || 138 | ch0 == '0') { 139 | return false; 140 | } 141 | break; 142 | } 143 | case 2: 144 | { 145 | final ch0 = str[0]; 146 | final ch1 = str[1]; 147 | if ((ch0 == 'o' || ch0 == 'O') && (ch1 == 'n' || ch1 == 'N')) { 148 | return true; 149 | } 150 | if ((ch0 == 'n' || ch0 == 'N') && (ch1 == 'o' || ch1 == 'O')) { 151 | return false; 152 | } 153 | break; 154 | } 155 | case 3: 156 | { 157 | final ch0 = str[0]; 158 | final ch1 = str[1]; 159 | final ch2 = str[2]; 160 | if ((ch0 == 'y' || ch0 == 'Y') && 161 | (ch1 == 'e' || ch1 == 'E') && 162 | (ch2 == 's' || ch2 == 'S')) { 163 | return true; 164 | } 165 | if ((ch0 == 'o' || ch0 == 'O') && 166 | (ch1 == 'f' || ch1 == 'F') && 167 | (ch2 == 'f' || ch2 == 'F')) { 168 | return false; 169 | } 170 | break; 171 | } 172 | case 4: 173 | { 174 | final ch0 = str[0]; 175 | final ch1 = str[1]; 176 | final ch2 = str[2]; 177 | final ch3 = str[3]; 178 | if ((ch0 == 't' || ch0 == 'T') && 179 | (ch1 == 'r' || ch1 == 'R') && 180 | (ch2 == 'u' || ch2 == 'U') && 181 | (ch3 == 'e' || ch3 == 'E')) { 182 | return true; 183 | } 184 | break; 185 | } 186 | case 5: 187 | { 188 | final ch0 = str[0]; 189 | final ch1 = str[1]; 190 | final ch2 = str[2]; 191 | final ch3 = str[3]; 192 | final ch4 = str[4]; 193 | if ((ch0 == 'f' || ch0 == 'F') && 194 | (ch1 == 'a' || ch1 == 'A') && 195 | (ch2 == 'l' || ch2 == 'L') && 196 | (ch3 == 's' || ch3 == 'S') && 197 | (ch4 == 'e' || ch4 == 'E')) { 198 | return false; 199 | } 200 | break; 201 | } 202 | default: 203 | break; 204 | } 205 | 206 | return false; 207 | } 208 | 209 | /// Converts a Boolean to a boolean handling null. 210 | /// 211 | /// BooleanUtils.toBooleanDefaultIfNull(true, false) = true 212 | /// BooleanUtils.toBooleanDefaultIfNull(true, true) = true 213 | /// BooleanUtils.toBooleanDefaultIfNull(false, true) = false 214 | /// BooleanUtils.toBooleanDefaultIfNull(false, false) = false 215 | /// BooleanUtils.toBooleanDefaultIfNull(null, true) = true 216 | /// BooleanUtils.toBooleanDefaultIfNull(null, false) = false 217 | static bool toBooleanDefaultIfNull( 218 | final bool? value, final bool valueIfNull) { 219 | if (value == null) { 220 | return valueIfNull; 221 | } 222 | return value; 223 | } 224 | 225 | /// Converts a boolean to an int using the convention that 226 | /// true is 1 and false is 0 227 | /// 228 | /// BooleanUtils.toInteger(true) = 1 229 | /// BooleanUtils.toInteger(false) = 0 230 | static int toInteger(final bool bool) { 231 | return bool ? 1 : 0; 232 | } 233 | 234 | /// Converts a boolean to a String returning one of the input Strings. 235 | /// 236 | /// BooleanUtils.toBooleanString(true) = "true" 237 | /// BooleanUtils.toBooleanString(false) = "false" 238 | static String toBooleanString(final bool value) { 239 | return value ? TRUE : FALSE; 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /lib/src/ColorUtils.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/basic_utils.dart'; 2 | 3 | /// 4 | /// Helper class for color operations. 5 | /// 6 | class ColorUtils { 7 | static const String BASIC_COLOR_RED = 'red'; 8 | static const String BASIC_COLOR_GREEN = 'green'; 9 | static const String BASIC_COLOR_BLUE = 'blue'; 10 | static const String HEX_BLACK = '#000000'; 11 | static const String HEX_WHITE = '#FFFFFF'; 12 | 13 | /// 14 | /// Converts the given [hex] color string to the corresponding int. 15 | /// 16 | /// Note that when no alpha/opacity is specified, 0xFF is assumed. 17 | /// 18 | static int hexToInt(String hex) { 19 | final hexDigits = hex.startsWith('#') ? hex.substring(1) : hex; 20 | final hexMask = hexDigits.length <= 6 ? 0xFF000000 : 0; 21 | final hexValue = int.parse(hexDigits, radix: 16); 22 | assert(hexValue >= 0 && hexValue <= 0xFFFFFFFF); 23 | return hexValue | hexMask; 24 | } 25 | 26 | /// 27 | /// Converts the given integer [i] to a hex string with a leading #. 28 | /// 29 | /// Note that only the RGB values will be returned (like #RRGGBB), so 30 | /// and alpha/opacity value will be stripped. 31 | /// 32 | static String intToHex(int i) { 33 | assert(i >= 0 && i <= 0xFFFFFFFF); 34 | return '#${(i & 0xFFFFFF | 0x1000000).toRadixString(16).substring(1).toUpperCase()}'; 35 | } 36 | 37 | /// 38 | /// Lightens or darkens the given [hex] color by the given [percent]. 39 | /// 40 | /// To lighten a color, set the [percent] value to > 0. 41 | /// To darken a color, set the [percent] value to < 0. 42 | /// Will add a # to the [hex] string if it is missing. 43 | /// 44 | /// 45 | static String shadeColor(String hex, double percent) { 46 | var bC = basicColorsFromHex(hex); 47 | 48 | var R = (bC[BASIC_COLOR_RED]! * (100 + percent) / 100).round(); 49 | var G = (bC[BASIC_COLOR_GREEN]! * (100 + percent) / 100).round(); 50 | var B = (bC[BASIC_COLOR_BLUE]! * (100 + percent) / 100).round(); 51 | 52 | if (R > 255) { 53 | R = 255; 54 | } else if (R < 0) { 55 | R = 0; 56 | } 57 | 58 | if (G > 255) { 59 | G = 255; 60 | } else if (G < 0) { 61 | G = 0; 62 | } 63 | 64 | if (B > 255) { 65 | B = 255; 66 | } else if (B < 0) { 67 | B = 0; 68 | } 69 | 70 | var RR = ((R.toRadixString(16).length == 1) 71 | ? '0' + R.toRadixString(16) 72 | : R.toRadixString(16)); 73 | var GG = ((G.toRadixString(16).length == 1) 74 | ? '0' + G.toRadixString(16) 75 | : G.toRadixString(16)); 76 | var BB = ((B.toRadixString(16).length == 1) 77 | ? '0' + B.toRadixString(16) 78 | : B.toRadixString(16)); 79 | 80 | return '#' + RR + GG + BB; 81 | } 82 | 83 | /// 84 | /// Fills up the given 3 char [hex] string to 6 char hex string. 85 | /// 86 | /// Will add a # to the [hex] string if it is missing. 87 | /// 88 | static String fillUpHex(String hex) { 89 | if (!hex.startsWith('#')) { 90 | hex = '#' + hex; 91 | } 92 | 93 | if (hex.length == 7) { 94 | return hex; 95 | } 96 | 97 | var filledUp = ''; 98 | hex.runes.forEach((r) { 99 | var char = String.fromCharCode(r); 100 | if (char == '#') { 101 | filledUp = filledUp + char; 102 | } else { 103 | filledUp = filledUp + char + char; 104 | } 105 | }); 106 | return filledUp; 107 | } 108 | 109 | /// 110 | /// Returns true or false if the calculated relative luminance from the given [hex] is less than 0.5. 111 | /// 112 | static bool isDark(String hex) { 113 | var bC = basicColorsFromHex(hex); 114 | 115 | return calculateRelativeLuminance( 116 | bC[BASIC_COLOR_RED]!, bC[BASIC_COLOR_GREEN]!, bC[BASIC_COLOR_BLUE]!) < 117 | 0.5; 118 | } 119 | 120 | /// 121 | /// Calculates the limunance for the given [hex] color and returns black as hex for bright colors, white as hex for dark colors. 122 | /// 123 | static String contrastColor(String hex) { 124 | var bC = basicColorsFromHex(hex); 125 | 126 | var luminance = calculateRelativeLuminance( 127 | bC[BASIC_COLOR_RED]!, bC[BASIC_COLOR_GREEN]!, bC[BASIC_COLOR_BLUE]!); 128 | return luminance > 0.5 ? HEX_BLACK : HEX_WHITE; 129 | } 130 | 131 | /// 132 | /// Fetches the basic color int values for red, green, blue from the given [hex] string. 133 | /// 134 | /// The values are returned inside a map with the following keys : 135 | /// * red 136 | /// * green 137 | /// * blue 138 | /// 139 | static Map basicColorsFromHex(String hex) { 140 | hex = fillUpHex(hex); 141 | 142 | if (!hex.startsWith('#')) { 143 | hex = '#' + hex; 144 | } 145 | 146 | var R = int.parse(hex.substring(1, 3), radix: 16); 147 | var G = int.parse(hex.substring(3, 5), radix: 16); 148 | var B = int.parse(hex.substring(5, 7), radix: 16); 149 | return {BASIC_COLOR_RED: R, BASIC_COLOR_GREEN: G, BASIC_COLOR_BLUE: B}; 150 | } 151 | 152 | /// 153 | /// Calculates the relative luminance for the given [red], [green], [blue] values. 154 | /// 155 | /// The returned value is between 0 and 1 with the given [decimals]. 156 | /// 157 | static double calculateRelativeLuminance(int red, int green, int blue, 158 | {int decimals = 2}) { 159 | return MathUtils.round( 160 | (0.299 * red + 0.587 * green + 0.114 * blue) / 255, decimals); 161 | } 162 | 163 | /// 164 | /// Swatch the given [hex] color. 165 | /// 166 | /// It creates lighter and darker colors from the given [hex] returned in a list with the given [hex]. 167 | /// 168 | /// The [amount] defines how much lighter or darker colors a generated. 169 | /// The specified [percentage] value defines the color spacing of the individual colors. As a default, 170 | /// each color is 15 percent lighter or darker than the previous one. 171 | /// 172 | static List swatchColor(String hex, 173 | {double percentage = 15, int amount = 5}) { 174 | hex = fillUpHex(hex); 175 | 176 | var colors = []; 177 | for (var i = 1; i <= amount; i++) { 178 | colors.add(shadeColor(hex, (6 - i) * percentage)); 179 | } 180 | colors.add(hex); 181 | for (var i = 1; i <= amount; i++) { 182 | colors.add(shadeColor(hex, (0 - i) * percentage)); 183 | } 184 | return colors; 185 | } 186 | 187 | /// 188 | /// Inverts Color Hex code 189 | /// Convert string to (4-bit int) and apply bitwise-NOT operation then convert back to Hex String 190 | /// e.g: convert white (FFFFFF) to Dark (000000). 191 | /// Returns Inverted String Color. 192 | /// 193 | static String invertColor(String color) { 194 | var invertedColor = []; 195 | for (var i = 0; i < color.length; i++) { 196 | if (color[i].startsWith('#')) { 197 | invertedColor.add('#'); 198 | } else { 199 | invertedColor.add( 200 | ((~int.parse('0x${color[i]}')).toUnsigned(4)).toRadixString(16)); 201 | } 202 | } 203 | return invertedColor.join(); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /lib/src/DnsUtils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:basic_utils/basic_utils.dart'; 4 | 5 | /// 6 | /// Helper class for dns record lookups 7 | /// 8 | class DnsUtils { 9 | /// 10 | /// Base url for each dns resolver 11 | /// 12 | static const _dnsApiProviderUrl = { 13 | DnsApiProvider.GOOGLE: 'https://dns.google.com/resolve', 14 | DnsApiProvider.CLOUDFLARE: 'https://cloudflare-dns.com/dns-query', 15 | }; 16 | 17 | /// 18 | /// Lookup for records of the given [type] and [name]. It also supports [dnssec] 19 | /// 20 | static Future?> lookupRecord(String name, RRecordType type, 21 | {bool dnssec = false, 22 | DnsApiProvider provider = DnsApiProvider.GOOGLE}) async { 23 | var queryParameters = {}; 24 | queryParameters.putIfAbsent('name', () => name); 25 | queryParameters.putIfAbsent('type', () => _getTypeFromType(type)); 26 | queryParameters.putIfAbsent('dnssec', () => dnssec.toString()); 27 | 28 | assert(_dnsApiProviderUrl.length == DnsApiProvider.values.length); 29 | var _baseUrl = _dnsApiProviderUrl[provider]; 30 | 31 | var headers = {'Accept': 'application/dns-json'}; 32 | 33 | var body = await HttpUtils.getForJson(_baseUrl!, 34 | queryParameters: queryParameters, headers: headers); 35 | var response = ResolveResponse.fromJson(body); 36 | return response.answer; 37 | } 38 | 39 | static String _getTypeFromType(RRecordType type) { 40 | return rRecordTypeToInt(type).toString(); 41 | } 42 | 43 | /// 44 | /// Converts the given number [type] to a [RRecordType] enum. 45 | /// 46 | static RRecordType intToRRecordType(int type) { 47 | return _intToRRecordType[type] ?? RRecordType.A; 48 | } 49 | 50 | /// 51 | /// Converts the given type to a decimal number 52 | /// 53 | static int rRecordTypeToInt(RRecordType type) { 54 | return _rRecordTypeToInt[type] ?? 1; 55 | } 56 | 57 | /// 58 | /// Map from [RRecordType] enum to number 59 | /// 60 | static const _rRecordTypeToInt = { 61 | RRecordType.A: 1, 62 | RRecordType.AAAA: 28, 63 | RRecordType.ANY: 255, 64 | RRecordType.CAA: 257, 65 | RRecordType.CDS: 59, 66 | RRecordType.CERT: 37, 67 | RRecordType.CNAME: 5, 68 | RRecordType.DNAME: 39, 69 | RRecordType.DNSKEY: 48, 70 | RRecordType.DS: 43, 71 | RRecordType.HINFO: 13, 72 | RRecordType.IPSECKEY: 45, 73 | RRecordType.MX: 15, 74 | RRecordType.NAPTR: 35, 75 | RRecordType.NS: 2, 76 | RRecordType.NSEC: 47, 77 | RRecordType.NSEC3PARAM: 51, 78 | RRecordType.PTR: 12, 79 | RRecordType.RP: 17, 80 | RRecordType.RRSIG: 46, 81 | RRecordType.SOA: 6, 82 | RRecordType.SPF: 99, 83 | RRecordType.SRV: 33, 84 | RRecordType.SSHFP: 44, 85 | RRecordType.TLSA: 52, 86 | RRecordType.TXT: 16, 87 | RRecordType.WKS: 11, 88 | }; 89 | 90 | /// 91 | /// Map from number to [RRecordType] enum 92 | /// 93 | static final _intToRRecordType = 94 | _rRecordTypeToInt.map((k, v) => MapEntry(v, k)); 95 | 96 | /// 97 | /// Reverse lookup for the given [ip] to determine a hostname. 98 | /// 99 | /// Thise reserses the given [ip], adds ".in-addr.arpa" / ".ip6.arpa" and 100 | /// tries to fetch a PTR record for the generated name. 101 | /// 102 | /// Will return null, if no IP address is given or no PTR is found. 103 | /// 104 | static Future?> reverseDns(String ip, 105 | {DnsApiProvider provider = DnsApiProvider.GOOGLE}) async { 106 | var queryParameters = {}; 107 | 108 | var reverse = getReverseAddr(ip); 109 | if (reverse == null) { 110 | return null; 111 | } 112 | queryParameters.putIfAbsent('name', () => reverse); 113 | queryParameters.putIfAbsent( 114 | 'type', () => _getTypeFromType(RRecordType.PTR)); 115 | //queryParameters.putIfAbsent('dnssec', () => dnssec.toString()); 116 | 117 | assert(_dnsApiProviderUrl.length == DnsApiProvider.values.length); 118 | var _baseUrl = _dnsApiProviderUrl[provider]; 119 | 120 | var headers = {'Accept': 'application/dns-json'}; 121 | 122 | var body = await HttpUtils.getForJson(_baseUrl!, 123 | queryParameters: queryParameters, headers: headers); 124 | var response = ResolveResponse.fromJson(body); 125 | return response.answer; 126 | } 127 | 128 | /// 129 | /// Reverses the given [ip] address. Will return null if the given [ip] is not 130 | /// an IP address. 131 | /// 132 | /// Example : 133 | /// 172.217.22.14 => 14.22.217.172.in-addr.arpa 134 | /// 2a00:1450:4001:81a::200e => e.0.0.2.a.1.8.1.0.0.4.0.5.4.1.0.0.a.2.ip6.arpa 135 | /// 136 | static String? getReverseAddr(String ip) { 137 | if (ip.contains('.')) { 138 | return ip.split('.').reversed.join('.') + '.in-addr.arpa'; 139 | } else if (ip.contains(':')) { 140 | return ip.split(':').join().split('').reversed.join('.') + '.ip6.arpa'; 141 | } else { 142 | return null; 143 | } 144 | } 145 | 146 | /// 147 | /// Converts the record to the BIND representation. 148 | /// 149 | static String toBind(RRecord record) { 150 | var sb = StringBuffer(); 151 | sb.write(record.name); 152 | if (sb.length < 8) { 153 | sb.write('\t'); 154 | } 155 | if (sb.length < 16) { 156 | sb.write('\t'); 157 | } 158 | sb.write('\t'); 159 | sb.write(record.ttl); 160 | sb.write('\tIN\t'); 161 | sb.write(intToRRecordType(record.rType) 162 | .toString() 163 | .substring('RRecordType.'.length)); 164 | 165 | sb.write('\t'); 166 | sb.write('\"'); 167 | sb.write(record.data); 168 | sb.write('\"'); 169 | 170 | return sb.toString(); 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /lib/src/DomainUtils.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/StringUtils.dart'; 2 | import 'package:basic_utils/src/library/IDNAConverter.dart'; 3 | import 'package:basic_utils/src/model/CountryCodeList.dart'; 4 | import 'package:basic_utils/src/model/Domain.dart'; 5 | import 'package:basic_utils/src/model/GtldList.dart'; 6 | import 'package:basic_utils/src/model/IdnCountryCodeList.dart'; 7 | import 'package:basic_utils/src/model/PublicSuffix.dart'; 8 | 9 | /// 10 | /// Helper class for domain names 11 | /// 12 | class DomainUtils { 13 | /// 14 | /// Checks if the given string [s] is a domain name. 15 | /// 16 | /// Will return false if the given string [s] starts with www. or *. 17 | /// 18 | static bool isDomainName(String s) { 19 | if (s.startsWith('*.') || isSubDomain(s)) { 20 | return false; 21 | } 22 | return parseDomain(s) != null; 23 | } 24 | 25 | /// 26 | /// Checks if the given string [subTld] is a subTld 27 | /// 28 | static bool isSubTld(String tld, String? subTld) { 29 | var subTLDs = suffixList[tld]; 30 | if (subTLDs == null) { 31 | return false; 32 | } 33 | if (subTLDs.contains(subTld)) { 34 | return true; 35 | } 36 | return false; 37 | } 38 | 39 | /// 40 | /// Check if the given string [s] is a subdomain 41 | /// Example: api.domain.com => true 42 | /// domain.de.com => false 43 | /// 44 | static bool isSubDomain(String? s) { 45 | if (StringUtils.isNotNullOrEmpty(s)) { 46 | var labels = splitDomainName(s!); 47 | if (labels.length == 2) { 48 | // Only 2 labels, so it has to be a normal domain name 49 | return false; 50 | } 51 | if (labels.length == 3) { 52 | // 3 labels, check for www and if the second label is a subtld 53 | if (labels.elementAt(0) == 'www') { 54 | // Found www at the first label, it is a subdomain 55 | return true; 56 | } 57 | // If the domain name has a subtld, return false otherwise return true 58 | return !isSubTld(labels.elementAt(2), labels.elementAt(1)); 59 | } 60 | if (labels.length > 3) { 61 | // More than 3 labels, so it is a sub domain name 62 | return true; 63 | } 64 | return false; 65 | } else { 66 | return false; 67 | } 68 | } 69 | 70 | /// 71 | /// Checks if the given [sub] is a subdomain of the given [domain]. 72 | /// Example : 73 | /// sub1.domain.com & domain.com => true 74 | /// sub1.domain2.com & domain.com => false 75 | /// 76 | static bool isSubDomainOf(String sub, String domain) { 77 | var rightPart = sub.substring(sub.indexOf('.') + 1); 78 | return rightPart == domain; 79 | } 80 | 81 | /// 82 | /// Checks if the given string [s] is a cctld. 83 | /// Example : 84 | /// de => true 85 | /// com => false 86 | /// 87 | static bool isCCTLD(String s) { 88 | return idnCountryCodeList.containsKey(s) || 89 | countryCodeList.contains(s.toUpperCase()); 90 | } 91 | 92 | /// 93 | /// Checks if the given string [s] is a ngtld. 94 | /// Example : 95 | /// car => true 96 | /// com => false 97 | /// de => false 98 | /// 99 | static bool isNGTLD(String s) { 100 | return (!isCCTLD(s) && !isGTLD(s) && isTld(s)); 101 | } 102 | 103 | /// 104 | /// Checks if the given string [s] is a tld. 105 | /// Example : 106 | /// car => true 107 | /// com => true 108 | /// de => true 109 | /// qwertzu => false 110 | /// 111 | static bool isTld(String s) { 112 | return suffixList.containsKey(s); 113 | } 114 | 115 | /// 116 | /// Checks if the given string [s] is a gtld. 117 | /// Example : 118 | /// de => false 119 | /// com => true 120 | /// 121 | static bool isGTLD(String s) { 122 | return gtldList.contains(s); 123 | } 124 | 125 | /// 126 | /// Splits the given [domainName]. 127 | /// Examples : 128 | /// example.com => ['example','com'] 129 | /// subdomain.example.com => ['subdomain','example','com'] 130 | /// 131 | static List splitDomainName(String domainName) { 132 | return domainName.split('.'); 133 | } 134 | 135 | /// 136 | /// Fetches the domain from the given [url] 137 | /// Returns null if the given [url] is not parsable. 138 | /// 139 | static Domain? getDomainFromUrl(String url) { 140 | url = url.replaceFirst('https://', ''); 141 | url = url.replaceFirst('http://', ''); 142 | if (url.contains('/')) { 143 | url = url.substring(0, url.indexOf('/')); 144 | } 145 | return parseDomain(url); 146 | } 147 | 148 | /// 149 | /// Parse the given [domainName] to a [Domain] object. 150 | /// Returns null if the given [domainName] is not parsable. 151 | /// 152 | static Domain? parseDomain(String domainName) { 153 | domainName = domainName.trim(); 154 | if (domainName.endsWith('.')) { 155 | domainName = domainName.substring(0, domainName.length - 1); 156 | } 157 | if (domainName.startsWith('.')) { 158 | domainName = domainName.substring(1, domainName.length); 159 | } 160 | if (!domainName.contains('.')) { 161 | return null; 162 | } 163 | var tld = domainName.substring( 164 | domainName.lastIndexOf('.') + 1, domainName.length); 165 | var leftPart = _getLeftPart(domainName, tld); 166 | // Check if we have a left part 167 | if (StringUtils.isNullOrEmpty(leftPart)) { 168 | return null; 169 | } 170 | 171 | // Check if suffix list contains tld 172 | if (!suffixList.containsKey(tld)) { 173 | return null; 174 | } 175 | 176 | // Fetch subTLDs from the suffix list 177 | var subTLDs = suffixList[tld]; 178 | if (subTLDs == null || subTLDs.isEmpty) { 179 | // No subTLDs for the given tld, build the domain 180 | return Domain(sld: _trimToLastLabel(leftPart), tld: tld); 181 | } else { 182 | // Iterate over each subTLD 183 | for (var subTldEntry in subTLDs) { 184 | // Remove uncommon chars 185 | subTldEntry = _removeUncommonChars(subTldEntry); 186 | if (domainName.endsWith('.' + subTldEntry + '.' + tld)) { 187 | var labelCount = 0; 188 | // Calculate the allowedLabels 189 | if (subTldEntry == '*') { 190 | // *.de means that label1.label2.de is allowed 191 | labelCount = 3; 192 | } else { 193 | labelCount = subTldEntry.split('.').length + 2; 194 | } 195 | var leftPt = ''; 196 | if (domainName.length > (subTldEntry + '.' + tld).length) { 197 | leftPt = _getLeftPart(domainName, subTldEntry + '.' + tld); 198 | // Calculate the amount of labels in the right part: 1 (tld) + subTld length 199 | var rightPartLabels = 1 + subTldEntry.split('.').length; 200 | // Calculate the allowed amount of labels in the left part 201 | var leftPartLabelsAllowed = labelCount - rightPartLabels; 202 | var cuttingIndex = leftPt.indexOf('.', leftPartLabelsAllowed - 1); 203 | String sld; 204 | if (cuttingIndex >= 0) { 205 | sld = leftPt.substring(cuttingIndex + 1); 206 | } else { 207 | sld = leftPt; 208 | } 209 | return Domain(sld: sld, subTld: subTldEntry, tld: tld); 210 | } 211 | return Domain(sld: subTldEntry, tld: tld); 212 | } else if (subTldEntry.contains('*')) { 213 | var left = _getLeftPart(domainName, tld); 214 | var count = left.split('.').length; 215 | if (count > 2) { 216 | left = left.substring(left.indexOf('.', (count - 2) - 1) + 1); 217 | if (left.split('.').length > 1) { 218 | var sld = left.split('.')[0]; 219 | var subTld = left.substring(sld.length + 1); 220 | return Domain(sld: sld, subTld: subTld, tld: tld); 221 | } else { 222 | return Domain(sld: left, tld: tld); 223 | } 224 | } else { 225 | return Domain(sld: left, tld: tld); 226 | } 227 | } 228 | } 229 | // No subTld from the suffix list matches 230 | return Domain(sld: _trimToLastLabel(leftPart), tld: tld); 231 | } 232 | } 233 | 234 | static String _removeUncommonChars(String subTldEntry) { 235 | if (subTldEntry.startsWith('!')) { 236 | return subTldEntry.substring(1); 237 | } 238 | if (subTldEntry.startsWith('*.')) { 239 | return subTldEntry.substring(2); 240 | } 241 | return subTldEntry; 242 | } 243 | 244 | static String _getLeftPart(String domainName, String rightPart) { 245 | return domainName.substring(0, domainName.lastIndexOf('.' + rightPart)); 246 | } 247 | 248 | static String _trimToLastLabel(String value) { 249 | if (!value.contains('.')) return value; 250 | return value.substring(value.lastIndexOf('.') + 1); 251 | } 252 | 253 | /// 254 | /// Splits the given [domain] in seperate domain names for each subdomain. 255 | /// 256 | /// Example: 257 | /// sub2.sub1.domain.com => ['sub2.sub1.domain.com', 'sub1.domain.com', 'domain.com'] 258 | /// 259 | static List splitSubdomainInDomains(String name) { 260 | var domains = []; 261 | var ar = name.split('\.'); 262 | 263 | for (var i = 0; i < ar.length; i++) { 264 | var sb = StringBuffer(); 265 | for (var j = i; j < ar.length; j++) { 266 | sb.write(ar[j]); 267 | sb.write('.'); 268 | } 269 | var domain = sb.toString(); 270 | domain = domain.substring(0, domain.length - 1); 271 | if (ar.length - i == 3) { 272 | var splitted = splitDomainName(domain); 273 | if (isSubTld(splitted.elementAt(2), splitted.elementAt(1))) { 274 | domains.add(domain); 275 | break; 276 | } 277 | } 278 | if (ar.length - i == 2) { 279 | domains.add(domain); 280 | break; 281 | } 282 | domains.add(domain); 283 | } 284 | return domains; 285 | } 286 | 287 | /// 288 | /// Converts the given [domain] to IDN. 289 | /// 290 | /// Example : domän.com => xn--domn-noa.com 291 | /// 292 | /// This method uses an IDNA converter arcoding to 293 | /// 294 | static String toIDN(String domain) { 295 | return IDNAConverter.urlEncode(domain); 296 | } 297 | 298 | /// 299 | /// Converts the given [domain] from IDN to UTF8. 300 | /// 301 | /// Example : xn--domn-noa.com => domän.com 302 | /// 303 | /// This method uses an IDNA converter arcoding to 304 | /// 305 | static String fromIDN(String domain) { 306 | return IDNAConverter.urlDecode(domain); 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /lib/src/EmailUtils.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/basic_utils.dart'; 2 | 3 | /// 4 | /// Helper class for emails 5 | /// 6 | class EmailUtils { 7 | static final emailRegex = 8 | '^([\\w\\d\\-\\+]+)(\\.+[\\w\\d\\-\\+%]+)*@([\\w\\-]+\\.){1,5}(([A-Za-z]){2,30}|xn--[A-Za-z0-9]{1,26})\$'; 9 | 10 | /// 11 | /// Checks whether the given string [s] is a email address 12 | /// 13 | static bool isEmail(String s) { 14 | var regExp = RegExp(emailRegex); 15 | return regExp.hasMatch(s); 16 | } 17 | 18 | /// 19 | /// Parse the given email address string [s] to a [EmailAddress] object. 20 | /// Returns null if [s] is not parsable. 21 | /// 22 | static EmailAddress? parseEmailAddress(String s) { 23 | if (isEmail(s)) { 24 | var parts = s.split('@'); 25 | var domain = DomainUtils.parseDomain(parts.elementAt(1)); 26 | if (domain == null) { 27 | return null; 28 | } 29 | return EmailAddress(parts.elementAt(0), domain); 30 | } else { 31 | return null; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /lib/src/EnumUtils.dart: -------------------------------------------------------------------------------- 1 | /// 2 | /// Helper class for Enum operations 3 | /// 4 | class EnumUtils { 5 | /// 6 | /// Gets the enum for the enum list, returning defaultEnum if not found. 7 | /// 8 | /// Example : 9 | /// ```dart 10 | /// stringToEnum('Wednesday', Day.values, Day.Monday); // will receive Day.Wednesday from Day.values 11 | /// stringToEnum('wednesday', Day.values, Day.Monday, ignoreCase: true); // will receive wednesday from the given Day.values. 12 | /// ``` 13 | static T getEnum( 14 | final String enumName, final List enumList, final T defaultEnum, 15 | {bool ignoreCase = false}) { 16 | return enumList.firstWhere( 17 | (element) => ignoreCase 18 | ? element.name.toUpperCase() == enumName.toUpperCase() 19 | : element.name == enumName, 20 | orElse: () => defaultEnum, 21 | ); 22 | } 23 | 24 | /// 25 | /// Checks if the specified name is a valid enum for the enum list. 26 | /// 27 | /// Example : 28 | /// ```dart 29 | /// isValidEnum('Wednesday', Day.values); // will receive Day.Wednesday from Day.values 30 | /// isValidEnum('wednesday', Day.values, ignoreCase: true); // will receive wednesday from the given Day.values. 31 | /// ``` 32 | static bool isValidEnum(final String enumName, final List enumList, 33 | {bool ignoreCase = false}) { 34 | try { 35 | enumList.firstWhere( 36 | (element) => ignoreCase 37 | ? element.name.toUpperCase() == enumName.toUpperCase() 38 | : element.name == enumName, 39 | ); 40 | return true; 41 | } catch (ex) { 42 | return false; 43 | } 44 | } 45 | 46 | /// 47 | /// Gets the Map of enums by name. 48 | /// 49 | /// This method is useful when you need a map of enums by name. 50 | /// 51 | static Map getEnumMap(final List enumList) { 52 | final map = {}; 53 | enumList.forEach((element) { 54 | map[element.name] = element; 55 | }); 56 | return map; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lib/src/FunctionDefs.dart: -------------------------------------------------------------------------------- 1 | 2 | /// Represents a function that accepts two arguments and produces a result. 3 | typedef BiFunction = R Function(T first, U second); 4 | 5 | /// Represents an operation that accepts two input arguments and returns no 6 | /// result 7 | typedef BiConsumer = BiFunction; 8 | 9 | /// Represents an operation upon two operands of the same type, producing a 10 | /// result of the same type as the operands. 11 | typedef BinaryOperator = BiFunction; 12 | 13 | /// Represents a predicate (boolean-valued function) of two arguments. 14 | typedef BiPredicate = BiFunction; 15 | 16 | /// Represents a supplier of results. 17 | typedef Supplier = T Function(); 18 | 19 | /// Represents a supplier of boolean-valued results. 20 | typedef BooleanSupplier = Supplier; 21 | 22 | /// Represents a function that accepts one argument and produces a result. 23 | typedef SingleFunction = R Function(T arg); 24 | 25 | /// Represents an operation that accepts a single input argument and returns no 26 | /// result. 27 | typedef Consumer = SingleFunction; 28 | 29 | /// Represents a predicate (boolean-valued function) of one argument. 30 | typedef Predicate = SingleFunction; 31 | 32 | /// Represents an operation on a single operand that produces a result of the 33 | /// same type as its operand. 34 | typedef UnaryOperator = SingleFunction; 35 | -------------------------------------------------------------------------------- /lib/src/IterableUtils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:math'; 2 | 3 | /// 4 | /// Helper class for operations on iterables 5 | /// 6 | class IterableUtils { 7 | /// 8 | /// An empty unmodifiable collection. 9 | /// 10 | static final Iterable _emptyIterable = List.unmodifiable([]); 11 | 12 | /// 13 | /// Returns a random element in [iterable]. Throws [RangeError] if [iterable] is null or empty. 14 | /// 15 | static T randomItem(Iterable iterable) { 16 | if (iterable.isEmpty) { 17 | throw RangeError('iterable must not be empty'); 18 | } 19 | return iterable.elementAt(Random().nextInt(iterable.length)); 20 | } 21 | 22 | /// 23 | /// Checks if the given Iterable [iterable] is null or empty 24 | /// 25 | static bool isNullOrEmpty(Iterable? iterable) => 26 | (iterable == null || iterable.isEmpty) ? true : false; 27 | 28 | /// 29 | /// Checks if the given Iterable [iterable] is not null or empty 30 | /// 31 | static bool isNotNullOrEmpty(Iterable? iterable) => !isNullOrEmpty(iterable); 32 | 33 | /// 34 | /// Splits the given [list] into sublist of the given [size]. 35 | /// 36 | static List> chunk(List list, int size) { 37 | if (size <= 1) { 38 | throw ArgumentError('size must be >1'); 39 | } 40 | var parts = >[]; 41 | final baseListSize = list.length; 42 | for (var i = 0; i < baseListSize; i += size) { 43 | var subList = list.sublist(i, min(baseListSize, i + size)); 44 | parts.add(subList); 45 | } 46 | return parts; 47 | } 48 | 49 | /// 50 | /// Make an [Iterable] that aggregates elements from each of the iterables. 51 | /// 52 | /// IterableUtils.zip([1, 3, 5], [2, 4, 6]) = [1, 2, 3, 4, 5, 6] 53 | /// IterableUtils.zip([1, 3, 5], ['a', 'b', 'c']) = [1, 'a', 3, 'b', 5, 'c'] 54 | /// 55 | static Iterable zip(Iterable a, Iterable b) sync* { 56 | final ita = a.iterator; 57 | final itb = b.iterator; 58 | bool hasA, hasB; 59 | while ((hasA = ita.moveNext()) | (hasB = itb.moveNext())) { 60 | if (hasA) yield ita.current; 61 | if (hasB) yield itb.current; 62 | } 63 | } 64 | 65 | /// 66 | /// Returns the immutable [_emptyIterable]. 67 | /// 68 | static Iterable emptyIterable() { 69 | return _emptyIterable; 70 | } 71 | 72 | /// 73 | /// Returns an immutable empty collection if the argument is null, 74 | /// or the argument itself otherwise. 75 | /// 76 | static Iterable emptyIfNull(final Iterable? collection) { 77 | return collection ?? _emptyIterable; 78 | } 79 | 80 | /// 81 | /// Returns an [Iterable] containing the union of the given [Iterable]. 82 | /// The cardinality of each element in the returned [Iterable] will 83 | /// be equal to the maximum of the cardinality of that element in the two 84 | /// given [Iterable]. 85 | /// 86 | static Iterable union( 87 | final Iterable iterable1, final Iterable iterable2) { 88 | final a = Set.of(iterable1); 89 | final b = Set.of(iterable2); 90 | return a.union(b); 91 | } 92 | 93 | /// 94 | /// Returns a [Iterable] containing the intersection of the given [Iterable]. 95 | /// 96 | static Iterable intersection( 97 | final Iterable iterable1, final Iterable iterable2) { 98 | final a = Set.of(iterable1); 99 | final b = Set.of(iterable2); 100 | return a.intersection(b); 101 | } 102 | 103 | /// 104 | /// Returns a new [Iterable] containing a minus a subset of b. 105 | /// Only the elements of b that satisfy the predicate condition, 106 | /// p are subtracted from a. 107 | /// 108 | static Iterable subtract(final Iterable iterable1, final Iterable iterable2) { 109 | final a = Set.of(iterable1); 110 | final b = Set.of(iterable2); 111 | return a.difference(b); 112 | } 113 | 114 | /// 115 | /// Returns true if all elements of [iterable2] are also contained in [iterable1]. 116 | /// 117 | static bool containsAll(final Iterable iterable1, final Iterable iterable2) { 118 | if (iterable2.isEmpty) { 119 | return true; 120 | } 121 | 122 | return iterable2.every((element) => iterable1.contains(element)); 123 | } 124 | 125 | /// 126 | /// Returns true if at least one element is in both collections. 127 | /// 128 | static bool containsAny(final Iterable iterable1, final Iterable iterable2) { 129 | if (iterable1.length < iterable2.length) { 130 | return iterable1.any((element) => iterable2.contains(element)); 131 | } else { 132 | return iterable2.any((element) => iterable1.contains(element)); 133 | } 134 | } 135 | 136 | /// 137 | /// Gets the size of the [Iterator], [Map] or specified. 138 | /// 139 | static int size(final dynamic iterable) { 140 | if (iterable == null) { 141 | return 0; 142 | } 143 | if (iterable is Iterable) { 144 | return iterable.length; 145 | } else if (iterable is Map) { 146 | return iterable.length; 147 | } else { 148 | try { 149 | return iterable.length; 150 | } catch (ex) { 151 | throw ArgumentError('Unsupported object type $iterable'); 152 | } 153 | } 154 | } 155 | 156 | /// 157 | /// Gets the size of the [Iterator], [Map] or specified. 158 | /// 159 | static bool sizeIsEmpty(final dynamic iterable) { 160 | final result = size(iterable); 161 | return result == 0; 162 | } 163 | 164 | static void _permutate( 165 | int n, List elements, List> store) { 166 | if (n == 1) { 167 | var t = []; 168 | t.addAll(elements); 169 | store.add(t); 170 | } else { 171 | for (var i = 0; i < n - 1; i++) { 172 | _permutate(n - 1, elements, store); 173 | if (n % 2 == 0) { 174 | swap(elements, i, n - 1); 175 | } else { 176 | swap(elements, 0, n - 1); 177 | } 178 | } 179 | _permutate(n - 1, elements, store); 180 | } 181 | } 182 | 183 | /// 184 | /// Swaps the given index [a] and [b] in the given [input] 185 | /// 186 | static void swap(List input, int a, int b) { 187 | var tmp = input[a]; 188 | input[a] = input[b]; 189 | input[b] = tmp; 190 | } 191 | 192 | /// 193 | /// Creates a permutation if the given list [data] by swapping each items to get the amount of [data.length]!. 194 | /// 195 | /// If the data consists of 4 items, the permutation will create 24 possible combinations (4*3*2*1=24). 196 | /// 197 | /// Example 198 | /// 199 | /// data = ["A", "B", "C"] 200 | /// 201 | /// result = [[A, B, C], [B, A, C], [C, A, B], [A, C, B], [B, C, A], [C, B, A]] 202 | /// 203 | static List> permutate(List data) { 204 | var store = >[]; 205 | var tmp = []; 206 | tmp.addAll(data); 207 | _permutate(data.length, tmp, store); 208 | return store; 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /lib/src/SortUtils.dart: -------------------------------------------------------------------------------- 1 | /// 2 | /// Helper class for dns record lookups 3 | /// 4 | class SortUtils { 5 | /// 6 | /// Implementation of the quick sort algorithm 7 | /// 8 | static List quickSort(List list) { 9 | if (list.length <= 1) { 10 | return list; 11 | } 12 | 13 | var pivot = list[0]; 14 | var less = []; 15 | var more = []; 16 | var pivotList = []; 17 | 18 | list.forEach((var element) { 19 | if (element.compareTo(pivot) < 0) { 20 | less.add(element); 21 | } else if (element.compareTo(pivot) > 0) { 22 | more.add(element); 23 | } else { 24 | pivotList.add(element); 25 | } 26 | }); 27 | 28 | less = quickSort(less); 29 | more = quickSort(more); 30 | 31 | less.addAll(pivotList); 32 | less.addAll(more); 33 | return less; 34 | } 35 | 36 | /// 37 | /// Implementation of the bubble sort algorithm 38 | /// 39 | static List bubbleSort(List list) { 40 | var retList = List.from(list); 41 | var tmp; 42 | var swapped = false; 43 | do { 44 | swapped = false; 45 | for (var i = 1; i < retList.length; i++) { 46 | if (retList[i - 1].compareTo(retList[i]) > 0) { 47 | tmp = retList[i - 1]; 48 | retList[i - 1] = retList[i]; 49 | retList[i] = tmp; 50 | swapped = true; 51 | } 52 | } 53 | } while (swapped); 54 | 55 | return retList; 56 | } 57 | 58 | /// 59 | /// Implementation of the heap sort algorithm 60 | /// 61 | static List heapSort(List a) { 62 | var count = a.length; 63 | 64 | var start = (count - 2) ~/ 2; 65 | 66 | while (start >= 0) { 67 | _sink(a, start, count - 1); 68 | start--; 69 | } 70 | 71 | var end = count - 1; 72 | while (end > 0) { 73 | var tmp = a[end]; 74 | a[end] = a[0]; 75 | a[0] = tmp; 76 | 77 | _sink(a, 0, end - 1); 78 | 79 | end--; 80 | } 81 | return a; 82 | } 83 | 84 | /// 85 | /// Sink a element in the tree 86 | /// 87 | static void _sink(List a, int start, int end) { 88 | var root = start; 89 | 90 | while ((root * 2 + 1) <= end) { 91 | var child = root * 2 + 1; 92 | if (child + 1 <= end && a[child].compareTo(a[child + 1]) == -1) { 93 | child = child + 1; 94 | } 95 | 96 | if (a[root].compareTo(a[child]) == -1) { 97 | var tmp = a[root]; 98 | a[root] = a[child]; 99 | a[child] = tmp; 100 | root = child; 101 | } else { 102 | return; 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /lib/src/hex_utils.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | class HexUtils { 4 | /// 5 | /// Converts the given [hex] to [Uint8List] 6 | /// 7 | static Uint8List decode(String hex) { 8 | var str = hex.replaceAll(" ", ""); 9 | str = str.toLowerCase(); 10 | if (str.length % 2 != 0) { 11 | str = "0" + str; 12 | } 13 | var l = str.length ~/ 2; 14 | var result = new Uint8List(l); 15 | for (var i = 0; i < l; ++i) { 16 | var x = int.parse(str.substring(i * 2, (2 * (i + 1))), radix: 16); 17 | if (x.isNaN) { 18 | throw ArgumentError('Expected hex string'); 19 | } 20 | result[i] = x; 21 | } 22 | return result; 23 | } 24 | 25 | /// 26 | /// Converts the given [bytes] to hex string 27 | /// 28 | static String encode(Uint8List bytes) { 29 | var sb = StringBuffer(); 30 | for (var b in bytes) { 31 | var s = b.toRadixString(16).toUpperCase(); 32 | if (s.length == 1) { 33 | s = '0$s'; 34 | } 35 | sb.write(s); 36 | } 37 | return sb.toString(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/library/IDNAConverter.dart: -------------------------------------------------------------------------------- 1 | /// 2 | /// Implementation of IDNA - RFC 3490 standard converter according to 3 | /// 4 | class IDNAConverter { 5 | static const INVALID_INPUT = 'Invalid input'; 6 | static const OVERFLOW = 'Overflow: input needs wider integers to process'; 7 | static const NOT_BASIC = 'Illegal input >= 0x80 (not a basic code point)'; 8 | 9 | static const int base = 36; 10 | static const int tMin = 1; 11 | static const int tMax = 26; 12 | 13 | static const int skew = 38; 14 | static const int damp = 700; 15 | 16 | static const int initialBias = 72; 17 | static const int initialN = 128; // 0x80 18 | static const delimiter = '-'; // '\x2D' 19 | 20 | /// Highest positive signed 32-bit float value 21 | static const maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1 22 | 23 | static RegExp regexPunycode = RegExp(r'^xn--'); 24 | static RegExp regexNonASCII = RegExp(r'[^\0-\x7E]'); // non-ASCII chars 25 | static RegExp regexSeparators = 26 | RegExp(r'[\u002E\u3002\uFF0E\uFF61]'); // RFC 3490 separators 27 | static RegExp regexUrlprefix = RegExp(r'^http://|^https://'); 28 | 29 | /// 30 | /// Converts a string that contains unicode symbols to a string with only ASCII symbols. 31 | /// 32 | static String encode(String input) { 33 | var n = initialN; 34 | var delta = 0; 35 | var bias = initialBias; 36 | var output = []; 37 | 38 | // Copy all basic code points to the output 39 | var b = 0; 40 | for (var i = 0; i < input.length; i++) { 41 | var c = input.codeUnitAt(i); 42 | if (isBasic(c)) { 43 | output.add(c); 44 | b++; 45 | } 46 | } 47 | 48 | // Append delimiter 49 | if (b > 0) { 50 | output.add(delimiter.codeUnitAt(0)); 51 | } 52 | 53 | var h = b; 54 | while (h < input.length) { 55 | var m = maxInt; 56 | 57 | // Find the minimum code point >= n 58 | for (var i = 0; i < input.length; i++) { 59 | var c = input.codeUnitAt(i); 60 | if (c >= n && c < m) { 61 | m = c; 62 | } 63 | } 64 | 65 | if (m - n > (maxInt - delta) / (h + 1)) { 66 | throw ArgumentError(OVERFLOW); 67 | } 68 | delta = delta + (m - n) * (h + 1); 69 | n = m; 70 | 71 | for (var j = 0; j < input.length; j++) { 72 | var c = input.codeUnitAt(j); 73 | if (c < n) { 74 | delta++; 75 | if (0 == delta) { 76 | throw ArgumentError(OVERFLOW); 77 | } 78 | } 79 | if (c == n) { 80 | var q = delta; 81 | 82 | for (var k = base;; k += base) { 83 | int t; 84 | if (k <= bias) { 85 | t = tMin; 86 | } else if (k >= bias + tMax) { 87 | t = tMax; 88 | } else { 89 | t = k - bias; 90 | } 91 | if (q < t) { 92 | break; 93 | } 94 | output.add((digitToBasic(t + (q - t) % (base - t)))); 95 | q = ((q - t) / (base - t)).floor(); 96 | } 97 | 98 | output.add(digitToBasic(q)); 99 | bias = adapt(delta, h + 1, h == b); 100 | delta = 0; 101 | h++; 102 | } 103 | } 104 | 105 | delta++; 106 | n++; 107 | } 108 | 109 | return String.fromCharCodes(output); 110 | } 111 | 112 | /// 113 | /// Decode a ASCII string to the corresponding unicode string. 114 | /// 115 | static String decode(String input) { 116 | var n = initialN; 117 | var i = 0; 118 | var bias = initialBias; 119 | var output = []; 120 | 121 | var d = input.lastIndexOf(delimiter); 122 | if (d > 0) { 123 | for (var j = 0; j < d; j++) { 124 | var c = input.codeUnitAt(j); 125 | if (!isBasic(c)) { 126 | throw ArgumentError(INVALID_INPUT); 127 | } 128 | output.add(c); 129 | } 130 | d++; 131 | } else { 132 | d = 0; 133 | } 134 | 135 | while (d < input.length) { 136 | var oldi = i; 137 | var w = 1; 138 | 139 | for (var k = base;; k += base) { 140 | if (d == input.length) { 141 | throw ArgumentError(INVALID_INPUT); 142 | } 143 | var c = input.codeUnitAt(d++); 144 | var digit = basicToDigit(c); 145 | if (digit > (maxInt - i) / w) { 146 | throw ArgumentError(OVERFLOW); 147 | } 148 | 149 | i = i + digit * w; 150 | 151 | int t; 152 | if (k <= bias) { 153 | t = tMin; 154 | } else if (k >= bias + tMax) { 155 | t = tMax; 156 | } else { 157 | t = k - bias; 158 | } 159 | if (digit < t) { 160 | break; 161 | } 162 | w = w * (base - t); 163 | } 164 | 165 | bias = adapt(i - oldi, output.length + 1, oldi == 0); 166 | 167 | if (i / (output.length + 1) > maxInt - n) { 168 | throw ArgumentError(OVERFLOW); 169 | } 170 | 171 | n = (n + i / (output.length + 1)).floor(); 172 | i = i % (output.length + 1); 173 | output.insert(i, n); 174 | i++; 175 | } 176 | 177 | return String.fromCharCodes(output); 178 | } 179 | 180 | static int adapt(int delta, int numpoints, bool first) { 181 | if (first) { 182 | delta = (delta / damp).floor(); 183 | } else { 184 | delta = (delta / 2).floor(); 185 | } 186 | 187 | delta = delta + (delta / numpoints).floor(); 188 | 189 | var k = 0; 190 | while (delta > ((base - tMin) * tMax) / 2) { 191 | delta = (delta / (base - tMin)).floor(); 192 | k = k + base; 193 | } 194 | 195 | return (k + ((base - tMin + 1) * delta) / (delta + skew)).floor(); 196 | } 197 | 198 | /// 199 | /// Checks if the given [value] is within the ASCII set 200 | /// 201 | static bool isBasic(int value) { 202 | return value < 0x80; 203 | } 204 | 205 | /// Converts a digit/integer into a basic code point. 206 | /// @see `basicToDigit()` 207 | /// @private 208 | /// @param {Number} digit The numeric value of a basic code point. 209 | /// @returns {Number} The basic code point whose value 210 | static int digitToBasic(int digit) { 211 | if (digit < 26) { 212 | // 0..25 : 'a'..'z' 213 | return digit + 'a'.codeUnitAt(0); 214 | } else if (digit < 36) { 215 | // 26..35 : '0'..'9'; 216 | return digit - 26 + '0'.codeUnitAt(0); 217 | } else { 218 | throw ArgumentError(INVALID_INPUT); 219 | } 220 | } 221 | 222 | /// Converts a basic code point into a digit/integer. 223 | /// @see `digitToBasic()` 224 | /// @private 225 | /// @param {Number} codePoint The basic numeric code point value. 226 | /// @returns {Number} The numeric value of a basic code point (for use in 227 | /// representing integers) in the range `0` to `base - 1`, or `base` if 228 | /// the code point does not represent a value. 229 | static int basicToDigit(int codePoint) { 230 | if (codePoint - '0'.codeUnitAt(0) < 10) { 231 | // '0'..'9' : 26..35 232 | return codePoint - '0'.codeUnitAt(0) + 26; 233 | } else if (codePoint - 'a'.codeUnitAt(0) < 26) { 234 | // 'a'..'z' : 0..25 235 | return codePoint - 'a'.codeUnitAt(0); 236 | } else { 237 | throw ArgumentError(INVALID_INPUT); 238 | } 239 | } 240 | 241 | /// 242 | /// Converts a domain name or url that contains unicode symbols to a string with only ASCII symbols. 243 | /// 244 | static String urlDecode(String value) { 245 | return _urlConvert(value, false); 246 | } 247 | 248 | /// 249 | /// Decode a ASCII domain name or url to the corresponding unicode string. 250 | /// 251 | static String urlEncode(String value) { 252 | return _urlConvert(value, true); 253 | } 254 | 255 | static String _urlConvert(String url, bool shouldencode) { 256 | var _url = []; 257 | var _result = []; 258 | if (regexUrlprefix.hasMatch(url)) { 259 | _url = url.split('/'); 260 | } else { 261 | _url.add(url); 262 | } 263 | _url.forEach((String _suburl) { 264 | _suburl = _suburl.replaceAll(regexSeparators, '\x2E'); 265 | 266 | var _split = _suburl.split('.'); 267 | 268 | var _join = []; 269 | 270 | _split.forEach((elem) { 271 | // do decode and encode 272 | if (shouldencode) { 273 | if (regexPunycode.hasMatch(elem) || 274 | regexNonASCII.hasMatch(elem) == false) { 275 | _join.add(elem); 276 | } else { 277 | _join.add('xn--' + encode(elem)); 278 | } 279 | } else { 280 | if (regexNonASCII.hasMatch(elem)) { 281 | throw ArgumentError(NOT_BASIC); 282 | } else { 283 | _join.add(regexPunycode.hasMatch(elem) 284 | ? decode(elem.replaceFirst(regexPunycode, '')) 285 | : elem); 286 | } 287 | } 288 | }); 289 | _result.add(_join.isNotEmpty ? _join.join('.') : _suburl); 290 | }); 291 | 292 | return _result.length > 1 293 | ? _result.join('/') 294 | : _result.elementAt(0); 295 | } 296 | } 297 | -------------------------------------------------------------------------------- /lib/src/library/crypto/pss_signer.dart: -------------------------------------------------------------------------------- 1 | // See file LICENSE for more information. 2 | 3 | library impl.signer.pss_signer; 4 | 5 | import 'dart:typed_data'; 6 | 7 | import 'package:pointycastle/api.dart'; 8 | import 'package:pointycastle/asymmetric/api.dart'; 9 | import 'package:pointycastle/asymmetric/rsa.dart'; 10 | import 'package:pointycastle/src/registry/registry.dart'; 11 | 12 | class LocalPSSSigner implements Signer { 13 | /// Intended for internal use. 14 | static final FactoryConfig factoryConfig = 15 | DynamicFactoryConfig.suffix(Signer, '/PSS', (_, Match match) { 16 | final digestName = match.group(1); 17 | return () => LocalPSSSigner( 18 | RSAEngine(), 19 | Digest(digestName!), 20 | Digest(digestName), 21 | ); 22 | }); 23 | 24 | static const int TRAILER_IMPLICIT = 0xBC; 25 | 26 | final Digest _contentDigest; 27 | final Digest _mgfDigest; 28 | final AsymmetricBlockCipher _cipher; 29 | final int _hLen; 30 | final int _mgfhLen; 31 | final int _trailer; 32 | 33 | late bool _sSet; 34 | late int _sLen; 35 | late Uint8List _salt; 36 | late SecureRandom _random; 37 | 38 | late int _emBits; 39 | late Uint8List _block; 40 | late Uint8List _mDash; 41 | 42 | late bool _forSigning; 43 | 44 | LocalPSSSigner(this._cipher, this._contentDigest, this._mgfDigest, 45 | {int trailer = TRAILER_IMPLICIT}) 46 | : _hLen = _contentDigest.digestSize, 47 | _mgfhLen = _mgfDigest.digestSize, 48 | _trailer = trailer; 49 | 50 | @override 51 | String get algorithmName => '${_mgfDigest.algorithmName}/PSS'; 52 | 53 | @override 54 | void init(bool forSigning, CipherParameters params) { 55 | _forSigning = forSigning; 56 | 57 | AsymmetricKeyParameter akparams; 58 | if (params is ParametersWithSaltConfiguration) { 59 | akparams = params.parameters as AsymmetricKeyParameter; 60 | _random = params.random; 61 | _sSet = false; 62 | _sLen = params.saltLength; 63 | _salt = Uint8List(_sLen); 64 | } else if (params is ParametersWithSalt) { 65 | akparams = params.parameters as AsymmetricKeyParameter; 66 | _sSet = true; 67 | _salt = params.salt; 68 | _sLen = _salt.length; 69 | } else { 70 | throw ArgumentError( 71 | 'Unsupported parameters type ${params.runtimeType}: should be ParametersWithSaltConfiguration or ParametersWithSalt'); 72 | } 73 | 74 | var k = akparams.key as RSAAsymmetricKey; 75 | 76 | if (forSigning && (k is! RSAPrivateKey)) { 77 | throw ArgumentError('Signing requires private key'); 78 | } 79 | 80 | if (!forSigning && (k is! RSAPublicKey)) { 81 | throw ArgumentError('Verification requires public key'); 82 | } 83 | 84 | _emBits = k.modulus!.bitLength - 1; 85 | 86 | if (_emBits < (8 * _hLen + 8 * _sLen + 9)) { 87 | throw ArgumentError('Key too small for specified hash and salt lengths'); 88 | } 89 | 90 | _mDash = Uint8List(8 + _sLen + _contentDigest.digestSize); 91 | 92 | _cipher.init(forSigning, akparams); 93 | 94 | _block = Uint8List((_emBits + 7) ~/ 8); 95 | 96 | reset(); 97 | } 98 | 99 | /// Clear possibly sensitive data. 100 | void _clearBlock(Uint8List block) { 101 | for (var i = 0; i != block.length; i++) { 102 | block[i] = 0; 103 | } 104 | } 105 | 106 | @override 107 | void reset() { 108 | _contentDigest.reset(); 109 | } 110 | 111 | @override 112 | PSSSignature generateSignature(Uint8List message) { 113 | if (!_forSigning) { 114 | throw StateError('Signer was not initialised for signature generation'); 115 | } 116 | 117 | _contentDigest.reset(); 118 | _contentDigest.update(message, 0, message.length); 119 | _contentDigest.doFinal(_mDash, _mDash.length - _hLen - _sLen); 120 | 121 | if (_sLen != 0) { 122 | if (!_sSet) { 123 | _salt = _random.nextBytes(_sLen); 124 | } 125 | 126 | _arrayCopy(_salt, 0, _mDash, _mDash.length - _sLen, _sLen); 127 | } 128 | 129 | var h = Uint8List(_hLen); 130 | 131 | _contentDigest.update(_mDash, 0, _mDash.length); 132 | 133 | _contentDigest.doFinal(h, 0); 134 | 135 | _block[_block.length - _sLen - 1 - _hLen - 1] = 0x01; 136 | _arrayCopy(_salt, 0, _block, _block.length - _sLen - _hLen - 1, _sLen); 137 | 138 | var dbMask = 139 | _maskGeneratorFunction1(h, 0, h.length, _block.length - _hLen - 1); 140 | for (var i = 0; i != dbMask.length; i++) { 141 | _block[i] ^= dbMask[i]; 142 | } 143 | 144 | _arrayCopy(h, 0, _block, _block.length - _hLen - 1, _hLen); 145 | 146 | var firstByteMask = 0xff >> ((_block.length * 8) - _emBits); 147 | 148 | _block[0] &= firstByteMask; 149 | _block[_block.length - 1] = _trailer; 150 | 151 | var b = _cipher.process(_block); 152 | 153 | _clearBlock(_block); 154 | 155 | return PSSSignature(b); 156 | } 157 | 158 | @override 159 | bool verifySignature(Uint8List message, covariant PSSSignature signature) { 160 | if (_forSigning) { 161 | throw StateError('Signer was not initialised for signature verification'); 162 | } 163 | 164 | _contentDigest.reset(); 165 | _contentDigest.update(message, 0, message.length); 166 | _contentDigest.doFinal(_mDash, _mDash.length - _hLen - _sLen); 167 | 168 | var b = _cipher.process(signature.bytes); 169 | _block.fillRange(0, _block.length - b.length, 0); 170 | _arrayCopy(b, 0, _block, _block.length - b.length, b.length); 171 | 172 | var firstByteMask = 0xFF >> ((_block.length * 8) - _emBits); 173 | 174 | if (_block[0] != (_block[0] & firstByteMask) || 175 | _block[_block.length - 1] != _trailer) { 176 | _clearBlock(_block); 177 | return false; 178 | } 179 | 180 | var dbMask = _maskGeneratorFunction1( 181 | _block, _block.length - _hLen - 1, _hLen, _block.length - _hLen - 1); 182 | 183 | for (var i = 0; i != dbMask.length; i++) { 184 | _block[i] ^= dbMask[i]; 185 | } 186 | 187 | _block[0] &= firstByteMask; 188 | 189 | for (var i = 0; i != _block.length - _hLen - _sLen - 2; i++) { 190 | if (_block[i] != 0) { 191 | _clearBlock(_block); 192 | return false; 193 | } 194 | } 195 | 196 | if (_block[_block.length - _hLen - _sLen - 2] != 0x01) { 197 | _clearBlock(_block); 198 | return false; 199 | } 200 | 201 | if (_sSet) { 202 | _arrayCopy(_salt, 0, _mDash, _mDash.length - _sLen, _sLen); 203 | } else { 204 | _arrayCopy(_block, _block.length - _sLen - _hLen - 1, _mDash, 205 | _mDash.length - _sLen, _sLen); 206 | } 207 | 208 | _contentDigest.update(_mDash, 0, _mDash.length); 209 | _contentDigest.doFinal(_mDash, _mDash.length - _hLen); 210 | 211 | for (var i = _block.length - _hLen - 1, j = _mDash.length - _hLen; 212 | j != _mDash.length; 213 | i++, j++) { 214 | if ((_block[i] ^ _mDash[j]) != 0) { 215 | _clearBlock(_mDash); 216 | _clearBlock(_block); 217 | return false; 218 | } 219 | } 220 | 221 | _clearBlock(_mDash); 222 | _clearBlock(_block); 223 | return true; 224 | } 225 | 226 | /// Convert int to octet string. 227 | void _intToOSP(int i, Uint8List sp) { 228 | sp[0] = i >> 24; 229 | sp[1] = i >> 16; 230 | sp[2] = i >> 8; 231 | sp[3] = i >> 0; 232 | } 233 | 234 | Uint8List _maskGeneratorFunction1( 235 | Uint8List Z, int zOff, int zLen, int length) { 236 | var mask = Uint8List(length); 237 | var hashBuf = Uint8List(_mgfhLen); 238 | var C = Uint8List(4); 239 | var counter = 0; 240 | 241 | _mgfDigest.reset(); 242 | 243 | while (counter < (length ~/ _mgfhLen)) { 244 | _intToOSP(counter, C); 245 | 246 | _mgfDigest.update(Z, zOff, zLen); 247 | _mgfDigest.update(C, 0, C.length); 248 | _mgfDigest.doFinal(hashBuf, 0); 249 | 250 | _arrayCopy(hashBuf, 0, mask, counter * _mgfhLen, _mgfhLen); 251 | counter++; 252 | } 253 | 254 | if ((counter * _mgfhLen) < length) { 255 | _intToOSP(counter, C); 256 | 257 | _mgfDigest.update(Z, zOff, zLen); 258 | _mgfDigest.update(C, 0, C.length); 259 | _mgfDigest.doFinal(hashBuf, 0); 260 | 261 | _arrayCopy(hashBuf, 0, mask, counter * _mgfhLen, 262 | mask.length - (counter * _mgfhLen)); 263 | } 264 | 265 | return mask; 266 | } 267 | 268 | void _arrayCopy(Uint8List? sourceArr, int sourcePos, Uint8List? outArr, 269 | int outPos, int len) { 270 | for (var i = 0; i < len; i++) { 271 | outArr![outPos + i] = sourceArr![sourcePos + i]; 272 | } 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /lib/src/model/CountryCodeList.dart: -------------------------------------------------------------------------------- 1 | final List countryCodeList = [ 2 | 'AF', 3 | 'EG', 4 | 'AL', 5 | 'DZ', 6 | 'VI', 7 | 'UM', 8 | 'AS', 9 | 'AD', 10 | 'AO', 11 | 'AI', 12 | 'AG', 13 | 'GQ', 14 | 'AR', 15 | 'AM', 16 | 'AW', 17 | 'AZ', 18 | 'ET', 19 | 'AU', 20 | 'BS', 21 | 'BH', 22 | 'BD', 23 | 'BB', 24 | 'BY', 25 | 'BE', 26 | 'BZ', 27 | 'BJ', 28 | 'BM', 29 | 'BT', 30 | 'BO', 31 | 'BA', 32 | 'BW', 33 | 'BV', 34 | 'BR', 35 | 'VG', 36 | 'IO', 37 | 'BN', 38 | 'BG', 39 | 'BF', 40 | 'BI', 41 | 'CL', 42 | 'CN', 43 | 'CK', 44 | 'CR', 45 | 'CI', 46 | 'DK', 47 | 'DE', 48 | 'DM', 49 | 'DO', 50 | 'DJ', 51 | 'EC', 52 | 'SV', 53 | 'ER', 54 | 'EE', 55 | 'FK', 56 | 'FO', 57 | 'FJ', 58 | 'FI', 59 | 'FR', 60 | 'TF', 61 | 'GF', 62 | 'PF', 63 | 'GA', 64 | 'GM', 65 | 'GE', 66 | 'GH', 67 | 'GI', 68 | 'GD', 69 | 'GR', 70 | 'GL', 71 | 'GB', 72 | 'GP', 73 | 'GU', 74 | 'GT', 75 | 'GY', 76 | 'HT', 77 | 'HM', 78 | 'HN', 79 | 'HK', 80 | 'IN', 81 | 'ID', 82 | 'IQ', 83 | 'IR', 84 | 'IE', 85 | 'IS', 86 | 'IL', 87 | 'IT', 88 | 'JM', 89 | 'JP', 90 | 'YE', 91 | 'JO', 92 | 'KY', 93 | 'KH', 94 | 'CM', 95 | 'CA', 96 | 'CV', 97 | 'KZ', 98 | 'QA', 99 | 'KE', 100 | 'KG', 101 | 'KI', 102 | 'CC', 103 | 'CO', 104 | 'KM', 105 | 'CD', 106 | 'HR', 107 | 'CU', 108 | 'KW', 109 | 'LA', 110 | 'LS', 111 | 'LV', 112 | 'LB', 113 | 'LR', 114 | 'LY', 115 | 'LI', 116 | 'LT', 117 | 'LU', 118 | 'MO', 119 | 'MG', 120 | 'MW', 121 | 'MY', 122 | 'MV', 123 | 'ML', 124 | 'MT', 125 | 'MA', 126 | 'MH', 127 | 'MQ', 128 | 'MR', 129 | 'MU', 130 | 'YT', 131 | 'MK', 132 | 'MX', 133 | 'FM', 134 | 'MD', 135 | 'MC', 136 | 'MN', 137 | 'MS', 138 | 'MZ', 139 | 'MM', 140 | 'NA', 141 | 'NR', 142 | 'NP', 143 | 'NC', 144 | 'NZ', 145 | 'NI', 146 | 'NL', 147 | 'AN', 148 | 'NE', 149 | 'NG', 150 | 'NU', 151 | 'KP', 152 | 'MP', 153 | 'NF', 154 | 'NO', 155 | 'OM', 156 | 'AT', 157 | 'TL', 158 | 'PK', 159 | 'PW', 160 | 'PA', 161 | 'PG', 162 | 'PY', 163 | 'PE', 164 | 'PH', 165 | 'PN', 166 | 'PL', 167 | 'PT', 168 | 'PR', 169 | 'CG', 170 | 'RE', 171 | 'RW', 172 | 'RU', 173 | 'SB', 174 | 'ZM', 175 | 'WS', 176 | 'SM', 177 | 'ST', 178 | 'SA', 179 | 'SE', 180 | 'CH', 181 | 'SN', 182 | 'SC', 183 | 'SL', 184 | 'ZW', 185 | 'SG', 186 | 'SK', 187 | 'SI', 188 | 'SO', 189 | 'ES', 190 | 'LK', 191 | 'SH', 192 | 'KN', 193 | 'LC', 194 | 'PM', 195 | 'VC', 196 | 'ZA', 197 | 'SD', 198 | 'KR', 199 | 'SR', 200 | 'SJ', 201 | 'SZ', 202 | 'SY', 203 | 'TJ', 204 | 'TW', 205 | 'TZ', 206 | 'TH', 207 | 'TG', 208 | 'TK', 209 | 'TO', 210 | 'TT', 211 | 'TD', 212 | 'CZ', 213 | 'TN', 214 | 'TR', 215 | 'TM', 216 | 'TC', 217 | 'TV', 218 | 'UG', 219 | 'UA', 220 | 'HU', 221 | 'UY', 222 | 'UZ', 223 | 'VU', 224 | 'VA', 225 | 'VE', 226 | 'AE', 227 | 'US', 228 | 'VN', 229 | 'WF', 230 | 'CX', 231 | 'EH', 232 | 'CF', 233 | 'CY', 234 | 'ME', 235 | 'RS', 236 | 'GN', 237 | 'RO', 238 | 'AC', 239 | 'AQ', 240 | 'AX', 241 | 'EU', 242 | 'GG', 243 | 'GS', 244 | 'GW', 245 | 'IM', 246 | 'JE', 247 | 'PS', 248 | 'YU', 249 | 'BQ', 250 | 'CW', 251 | 'SX', 252 | 'BL', 253 | 'SU' 254 | ]; 255 | -------------------------------------------------------------------------------- /lib/src/model/DnsApiProvider.dart: -------------------------------------------------------------------------------- 1 | enum DnsApiProvider { GOOGLE, CLOUDFLARE } 2 | -------------------------------------------------------------------------------- /lib/src/model/Domain.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/basic_utils.dart'; 2 | 3 | /// 4 | /// Model that represents a domain name 5 | /// 6 | class Domain { 7 | /// The second level domain name 8 | String? sld; 9 | 10 | /// The sub top level domain name 11 | String? subTld; 12 | 13 | /// The top level domain name 14 | String? tld; 15 | 16 | /// The ascii encoded top level domain. NOT YET IMPLEMENTED 17 | String? asciiTld; 18 | 19 | /// The ascii encoded sub top level domain. NOT YET IMPLEMENTED 20 | String? asciiSubTld; 21 | 22 | /// The ascii encoded second level domain. NOT YET IMPLEMENTED 23 | String? asciiSld; 24 | 25 | /// The ascii version of the domain. NOT YET IMPLEMENTED 26 | String? asciiName; 27 | 28 | Domain({this.sld, this.tld, this.subTld}) { 29 | _setTld(tld); 30 | _setSld(sld); 31 | _setSubTld(subTld); 32 | } 33 | 34 | void _setTld(String? tld) { 35 | if (tld != null) { 36 | tld = tld; 37 | //asciiTld = DomainUtils.toASCII(tld, isNamePrep2008()); 38 | } 39 | } 40 | 41 | void _setSubTld(String? subTld) { 42 | if (subTld != null) { 43 | subTld = subTld; 44 | // asciiSubTld = DomainUtils.toASCII(subTld, isNamePrep2008()); 45 | } 46 | } 47 | 48 | void _setSld(String? sld) { 49 | if (sld != null) { 50 | sld = sld; 51 | //asciiSld = DomainUtils.toASCII(sld, isNamePrep2008()); 52 | } 53 | } 54 | 55 | @override 56 | String toString() { 57 | var parts = []; 58 | parts.add(sld); 59 | if (StringUtils.isNotNullOrEmpty(subTld)) { 60 | parts.add(subTld); 61 | } 62 | parts.add(tld); 63 | return parts.join('.'); 64 | } 65 | 66 | String toAsciiString() { 67 | var parts = []; 68 | parts.add(asciiSld); 69 | if (StringUtils.isNotNullOrEmpty(asciiSubTld)) { 70 | parts.add(asciiSubTld); 71 | } 72 | parts.add(asciiTld); 73 | return parts.join('.'); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /lib/src/model/EmailAddress.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/Domain.dart'; 2 | 3 | /// 4 | /// Model that represents a email address 5 | /// 6 | class EmailAddress { 7 | /// The local part of the email address 8 | String local; 9 | 10 | /// The domain of the email address 11 | Domain domain; 12 | 13 | EmailAddress(this.local, this.domain); 14 | 15 | @override 16 | String toString() { 17 | return local + '@' + domain.toString(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/model/GtldList.dart: -------------------------------------------------------------------------------- 1 | final List gtldList = [ 2 | 'com', 3 | 'net', 4 | 'org', 5 | 'info', 6 | 'biz', 7 | 'mobi', 8 | 'name', 9 | 'travel', 10 | 'jobs', 11 | 'aero', 12 | '9.4.e164.arpa', 13 | 'pro', 14 | 'coop', 15 | 'museum', 16 | 'tel', 17 | 'xxx', 18 | 'asia', 19 | 'cat' 20 | ]; 21 | -------------------------------------------------------------------------------- /lib/src/model/HttpRequestReturnType.dart: -------------------------------------------------------------------------------- 1 | enum HttpRequestReturnType { JSON, STRING, FULLRESPONSE } 2 | -------------------------------------------------------------------------------- /lib/src/model/IdnCountryCodeList.dart: -------------------------------------------------------------------------------- 1 | final Map idnCountryCodeList = { 2 | 'xn--fiqs8s': 'cn', 3 | 'xn--fiqz9s': 'cn', 4 | 'xn--wgbh1c': 'eg', 5 | 'xn--j6w193g': 'hk', 6 | 'xn--h2brj9c': 'in', 7 | 'xn--mgbbh1a71e': 'in', 8 | 'xn--fpcrj9c3d': 'in', 9 | 'xn--gecrj9c': 'in', 10 | 'xn--s9brj9c': 'in', 11 | 'xn--xkc2dl3a5ee0h': 'in', 12 | 'xn--45brj9c': 'in', 13 | 'xn--mgba3a4f16a': 'ir', 14 | 'xn--mgbayh7gpa': 'jo', 15 | 'xn--ygbi2ammx': 'ps', 16 | 'xn--wgbl6a': 'qa', 17 | 'xn--p1ai': 'ru', 18 | 'xn--mgberp4a5d4ar': 'sa', 19 | 'xn--yfro4i67o': 'sg', 20 | 'xn--clchc0ea0b2g2a9gcd': 'sg', 21 | 'xn--3e0b707e': 'kr', 22 | 'xn--fzc2c9e2c': 'lk', 23 | 'xn--xkc2al3hye2a': 'lk', 24 | 'xn--mgbtf8fl': 'sy', 25 | 'xn--kprw13d': 'tw', 26 | 'xn--kpry57d': 'tw', 27 | 'xn--o3cw4h': 'th', 28 | 'xn--pgbs0dh': 'tn', 29 | 'xn--mgbaam7a8h': 'ae', 30 | 'xn--lgbbat1ad8j': 'dz', 31 | 'xn--54b7fta0cc': 'bd', 32 | 'xn--90ae': 'bg ', 33 | 'xn--node': 'ge', 34 | 'xn--4dbrk0ce': 'il', 35 | 'xn--mgbc0a9azcg': 'ma', 36 | 'xn--mgb9awbf': 'om', 37 | 'xn--mgbai9azgqp6j': 'pk', 38 | 'xn--90a3ac': 'rs', 39 | 'xn--j1amh': 'ua', 40 | 'xn--90ais': 'by' 41 | }; 42 | -------------------------------------------------------------------------------- /lib/src/model/LengthUnits.dart: -------------------------------------------------------------------------------- 1 | enum LengthUnits { 2 | attometer, 3 | femtometer, 4 | picometer, 5 | nanometer, 6 | micrometers, 7 | millimeter, 8 | centimeter, 9 | decimeter, 10 | meter, 11 | kilometer 12 | } 13 | -------------------------------------------------------------------------------- /lib/src/model/Question.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'Question.g.dart'; 4 | 5 | @JsonSerializable(includeIfNull: false) 6 | class Question { 7 | String name; 8 | 9 | int type; 10 | 11 | Question({required this.name,required this.type}); 12 | 13 | /* 14 | * Json to Question object 15 | */ 16 | factory Question.fromJson(Map json) => 17 | _$QuestionFromJson(json); 18 | 19 | /* 20 | * Question object to json 21 | */ 22 | Map toJson() => _$QuestionToJson(this); 23 | } 24 | -------------------------------------------------------------------------------- /lib/src/model/Question.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'Question.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Question _$QuestionFromJson(Map json) => Question( 10 | name: json['name'] as String, 11 | type: json['type'] as int, 12 | ); 13 | 14 | Map _$QuestionToJson(Question instance) => { 15 | 'name': instance.name, 16 | 'type': instance.type, 17 | }; 18 | -------------------------------------------------------------------------------- /lib/src/model/RRecord.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'RRecord.g.dart'; 4 | 5 | @JsonSerializable(includeIfNull: false) 6 | class RRecord { 7 | /// The name of the record 8 | String name; 9 | 10 | /// The type of the record 11 | @JsonKey(name: 'type') 12 | int rType; 13 | 14 | /// The time to live of the record 15 | @JsonKey(name: 'TTL') 16 | int ttl; 17 | 18 | /// The data of the record 19 | String data; 20 | 21 | RRecord( 22 | {required this.name, 23 | required this.rType, 24 | required this.ttl, 25 | required this.data}); 26 | 27 | /* 28 | * Json to RRecord object 29 | */ 30 | factory RRecord.fromJson(Map json) => 31 | _$RRecordFromJson(json); 32 | 33 | /* 34 | * RRecord object to json 35 | */ 36 | Map toJson() => _$RRecordToJson(this); 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/model/RRecord.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'RRecord.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | RRecord _$RRecordFromJson(Map json) => RRecord( 10 | name: json['name'] as String, 11 | rType: json['type'] as int, 12 | ttl: json['TTL'] as int, 13 | data: json['data'] as String, 14 | ); 15 | 16 | Map _$RRecordToJson(RRecord instance) => { 17 | 'name': instance.name, 18 | 'type': instance.rType, 19 | 'TTL': instance.ttl, 20 | 'data': instance.data, 21 | }; 22 | -------------------------------------------------------------------------------- /lib/src/model/RRecordType.dart: -------------------------------------------------------------------------------- 1 | enum RRecordType { 2 | A, 3 | AAAA, 4 | ANY, 5 | CAA, 6 | CDS, 7 | CERT, 8 | DNAME, 9 | DNSKEY, 10 | DS, 11 | HINFO, 12 | IPSECKEY, 13 | NSEC, 14 | NSEC3PARAM, 15 | NAPTR, 16 | PTR, 17 | RP, 18 | RRSIG, 19 | SOA, 20 | SPF, 21 | SRV, 22 | SSHFP, 23 | TLSA, 24 | WKS, 25 | TXT, 26 | NS, 27 | MX, 28 | CNAME 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/model/ResolveResponse.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/Question.dart'; 2 | import 'package:basic_utils/src/model/RRecord.dart'; 3 | import 'package:json_annotation/json_annotation.dart'; 4 | 5 | part 'ResolveResponse.g.dart'; 6 | 7 | @JsonSerializable(includeIfNull: false) 8 | class ResolveResponse { 9 | @JsonKey(name: 'Status') 10 | int? status; 11 | @JsonKey(name: 'TC') 12 | bool? tc; 13 | @JsonKey(name: 'RD') 14 | bool? rd; 15 | @JsonKey(name: 'RA') 16 | bool? ra; 17 | @JsonKey(name: 'AD') 18 | bool? ad; 19 | @JsonKey(name: 'CD') 20 | bool? cd; 21 | @JsonKey(name: 'Question') 22 | List? question; 23 | @JsonKey(name: 'Answer') 24 | List? answer; 25 | @JsonKey(name: 'Comment') 26 | String? comment; 27 | 28 | ResolveResponse( 29 | {this.status, 30 | this.tc, 31 | this.rd, 32 | this.ra, 33 | this.ad, 34 | this.cd, 35 | this.question, 36 | this.answer, 37 | this.comment}); 38 | 39 | /* 40 | * Json to ResolveResponse object 41 | */ 42 | factory ResolveResponse.fromJson(Map json) => 43 | _$ResolveResponseFromJson(json); 44 | 45 | /* 46 | * ResolveResponse object to json 47 | */ 48 | Map toJson() => _$ResolveResponseToJson(this); 49 | } 50 | -------------------------------------------------------------------------------- /lib/src/model/ResolveResponse.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'ResolveResponse.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | ResolveResponse _$ResolveResponseFromJson(Map json) => 10 | ResolveResponse( 11 | status: json['Status'] as int?, 12 | tc: json['TC'] as bool?, 13 | rd: json['RD'] as bool?, 14 | ra: json['RA'] as bool?, 15 | ad: json['AD'] as bool?, 16 | cd: json['CD'] as bool?, 17 | question: (json['Question'] as List?) 18 | ?.map((e) => Question.fromJson(e as Map)) 19 | .toList(), 20 | answer: (json['Answer'] as List?) 21 | ?.map((e) => RRecord.fromJson(e as Map)) 22 | .toList(), 23 | comment: json['Comment'] as String?, 24 | ); 25 | 26 | Map _$ResolveResponseToJson(ResolveResponse instance) { 27 | final val = {}; 28 | 29 | void writeNotNull(String key, dynamic value) { 30 | if (value != null) { 31 | val[key] = value; 32 | } 33 | } 34 | 35 | writeNotNull('Status', instance.status); 36 | writeNotNull('TC', instance.tc); 37 | writeNotNull('RD', instance.rd); 38 | writeNotNull('RA', instance.ra); 39 | writeNotNull('AD', instance.ad); 40 | writeNotNull('CD', instance.cd); 41 | writeNotNull('Question', instance.question); 42 | writeNotNull('Answer', instance.answer); 43 | writeNotNull('Comment', instance.comment); 44 | return val; 45 | } 46 | -------------------------------------------------------------------------------- /lib/src/model/asn1/ASN1DumpLine.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/asn1/ASN1ObjectType.dart'; 2 | 3 | /// 4 | /// A line from an ASN1 dump 5 | /// 6 | class ASN1DumpLine { 7 | /// The offset 8 | int offset; 9 | 10 | /// The current depth 11 | int depth; 12 | 13 | /// The header length of the object 14 | int headerLength; 15 | 16 | /// The length of the object 17 | int length; 18 | 19 | /// The readable line representing the object 20 | String line; 21 | 22 | /// The tag of the object as HEX 23 | String tag; 24 | 25 | /// The object type 26 | ASN1ObjectType type; 27 | 28 | ASN1DumpLine({ 29 | required this.offset, 30 | required this.depth, 31 | required this.headerLength, 32 | required this.length, 33 | required this.line, 34 | required this.tag, 35 | required this.type, 36 | }); 37 | 38 | /// 39 | /// Prints out the line information 40 | /// 41 | String lineInfoToString() { 42 | return 'o=$offset d=$depth hl=$headerLength l=$length t=${tag.toUpperCase()}'; 43 | } 44 | 45 | /// 46 | /// Prints out the full line in an OpenSSL style. 47 | /// 48 | /// [spacing] defines the amount of white spaces between the line info and the readable line string 49 | /// 50 | /// ``` 51 | /// 13:d=2 hl=2 l=16 t=2 |----|---> INTEGER 9419718410412351084484106081643920776 52 | /// ``` 53 | /// 54 | @override 55 | String toString({int spacing = 0}) { 56 | var sb = StringBuffer(); 57 | sb.write(lineInfoToString()); 58 | for (var i = 0; i < spacing; i++) { 59 | sb.write(' '); 60 | } 61 | sb.write(line); 62 | return sb.toString(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/src/model/asn1/ASN1DumpWrapper.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/asn1/ASN1DumpLine.dart'; 2 | 3 | /// 4 | /// Wrapper object for ASN1DumpLine 5 | /// 6 | class ASN1DumpWrapper { 7 | /// List of single lines of the dump 8 | List? lines; 9 | 10 | ASN1DumpWrapper({this.lines}); 11 | 12 | /// 13 | /// Adding multiple ASN1DumpLine at once 14 | /// 15 | void addAll(List l) { 16 | lines ??= []; 17 | lines!.addAll(l); 18 | } 19 | 20 | /// 21 | /// Adding a ASN1DumpLine 22 | /// 23 | void add(ASN1DumpLine l) { 24 | lines ??= []; 25 | lines!.add(l); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/src/model/asn1/ASN1ObjectType.dart: -------------------------------------------------------------------------------- 1 | enum ASN1ObjectType { PRIM, CONST } 2 | -------------------------------------------------------------------------------- /lib/src/model/asn1/pkcs5s1_parameter_generator.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:pointycastle/api.dart'; 4 | 5 | class PKCS5S1ParameterGenerator { 6 | Digest digest; 7 | 8 | late Uint8List password; 9 | late Uint8List salt; 10 | late int iterationCount; 11 | 12 | PKCS5S1ParameterGenerator(this.digest); 13 | init(Uint8List password, Uint8List salt, int iterationCount) { 14 | this.password = password; 15 | this.salt = salt; 16 | this.iterationCount = iterationCount; 17 | } 18 | 19 | Uint8List generateDerivedKey() { 20 | var digestBytes = Uint8List(digest.digestSize); 21 | 22 | digest.update(password, 0, password.length); 23 | digest.update(salt, 0, salt.length); 24 | 25 | digest.doFinal(digestBytes, 0); 26 | for (int i = 1; i < iterationCount; i++) { 27 | digest.update(digestBytes, 0, digestBytes.length); 28 | digest.doFinal(digestBytes, 0); 29 | } 30 | 31 | return digestBytes; 32 | } 33 | 34 | KeyParameter generateDerivedParameters(int keySize) { 35 | if (keySize > digest.digestSize) { 36 | throw ArgumentError("Can't generate a derived key $keySize bytes long."); 37 | } 38 | 39 | var dKey = generateDerivedKey(); 40 | 41 | return KeyParameter(dKey); 42 | } 43 | 44 | ParametersWithIV generateDerivedParametersWithIV(int keySize, int ivSize) { 45 | keySize = keySize; 46 | ivSize = ivSize; 47 | 48 | if ((keySize + ivSize) > digest.digestSize) { 49 | throw ArgumentError( 50 | "Can't generate a derived key ${keySize + ivSize} bytes long."); 51 | } 52 | 53 | var dKey = generateDerivedKey(); 54 | 55 | return ParametersWithIV(KeyParameter(dKey), dKey); 56 | } 57 | 58 | CipherParameters generateDerivedMacParameters(int keySize) { 59 | return generateDerivedParameters(keySize); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/src/model/crl/CertificateListData.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/crl/CrlExtensions.dart'; 2 | import 'package:basic_utils/src/model/crl/RevokedCertificate.dart'; 3 | 4 | class CertificateListData { 5 | /// The version 6 | int? version; 7 | 8 | /// The issuer data of this list 9 | Map? issuer; 10 | 11 | /// The signatureAlgorithm of the certificate 12 | String? signatureAlgorithm; 13 | 14 | /// The readable name of the signature algorithm 15 | String? signatureAlgorithmReadableName; 16 | 17 | /// The issue date of this CRL. 18 | DateTime? thisUpdate; 19 | 20 | /// The date by which the next CRL will be issued 21 | DateTime? nextUpdate; 22 | 23 | /// The revoked certificates 24 | List? revokedCertificates; 25 | 26 | /// The extensions 27 | CrlExtensions? extensions; 28 | 29 | CertificateListData({ 30 | this.extensions, 31 | this.issuer, 32 | this.nextUpdate, 33 | this.revokedCertificates, 34 | this.signatureAlgorithm, 35 | this.signatureAlgorithmReadableName, 36 | this.thisUpdate, 37 | this.version, 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /lib/src/model/crl/CertificateRevokeListData.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/crl/CertificateListData.dart'; 2 | 3 | class CertificateRevokeListeData { 4 | /// The certificate list data 5 | CertificateListData? tbsCertList; 6 | 7 | /// The signature algorithm 8 | String? signatureAlgorithm; 9 | 10 | /// The readable name of the signature algorithm 11 | String? signatureAlgorithmReadableName; 12 | 13 | /// The signature 14 | String? signature; 15 | 16 | CertificateRevokeListeData({ 17 | this.tbsCertList, 18 | this.signature, 19 | this.signatureAlgorithm, 20 | this.signatureAlgorithmReadableName, 21 | }); 22 | } 23 | -------------------------------------------------------------------------------- /lib/src/model/crl/CrlEntryExtensionsData.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/crl/CrlReason.dart'; 2 | 3 | class CrlEntryExtensionsData { 4 | CrlReason? reason; 5 | 6 | CrlEntryExtensionsData({this.reason}); 7 | } 8 | -------------------------------------------------------------------------------- /lib/src/model/crl/CrlExtensions.dart: -------------------------------------------------------------------------------- 1 | class CrlExtensions { 2 | String? authorityKeyIdentifier; 3 | int? crlNumber; 4 | 5 | CrlExtensions({ 6 | this.authorityKeyIdentifier, 7 | this.crlNumber, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /lib/src/model/crl/CrlReason.dart: -------------------------------------------------------------------------------- 1 | /// 2 | /// The CRL reason enum. 3 | /// ``` 4 | /// CRLReason ::= ENUMERATED { 5 | /// unspecified (0), 6 | /// keyCompromise (1), 7 | /// cACompromise (2), 8 | /// affiliationChanged (3), 9 | /// superseded (4), 10 | /// cessationOfOperation (5), 11 | /// certificateHold (6), 12 | /// -- value 7 is not used 13 | /// removeFromCRL (8), 14 | /// privilegeWithdrawn (9), 15 | /// aACompromise (10) } 16 | ///``` 17 | /// 18 | enum CrlReason { 19 | unspecified, //0 20 | keyCompromise, //1 21 | cACompromise, //2 22 | affiliationChanged, //3 23 | superseded, //4 24 | cessationOfOperation, //5 25 | certificateHold, //6 26 | removeFromCRL, //8 27 | privilegeWithdrawn, //9 28 | aACompromise //10 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/model/crl/RevokedCertificate.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/crl/CrlEntryExtensionsData.dart'; 2 | 3 | class RevokedCertificate { 4 | /// The serialNumber of the certificate 5 | BigInt? serialNumber; 6 | 7 | /// The revocation time 8 | DateTime? revocationDate; 9 | 10 | /// The extensions 11 | CrlEntryExtensionsData? extensions; 12 | } 13 | -------------------------------------------------------------------------------- /lib/src/model/csr/CertificateSigningRequestData.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/csr/CertificateSigningRequestExtensions.dart'; 2 | import 'package:basic_utils/src/model/csr/CertificationRequestInfo.dart'; 3 | import 'package:basic_utils/src/model/csr/SubjectPublicKeyInfo.dart'; 4 | import 'package:json_annotation/json_annotation.dart'; 5 | 6 | part 'CertificateSigningRequestData.g.dart'; 7 | 8 | @JsonSerializable(includeIfNull: false, explicitToJson: true) 9 | class CertificateSigningRequestData { 10 | /// The certificationRequestInfo 11 | CertificationRequestInfo? certificationRequestInfo; 12 | 13 | /// The version 14 | @Deprecated('Use certificationRequestInfo.version instead') 15 | int? version; 16 | 17 | /// The subject data of the certificate singing request 18 | @Deprecated('Use certificationRequestInfo.subject instead') 19 | Map? subject; 20 | 21 | /// The public key information 22 | @Deprecated('Use certificationRequestInfo.publicKeyInfo instead') 23 | SubjectPublicKeyInfo? publicKeyInfo; 24 | 25 | /// The signature algorithm 26 | String? signatureAlgorithm; 27 | 28 | /// The readable name of the signature algorithm 29 | String? signatureAlgorithmReadableName; 30 | 31 | /// The salt length if algorithm is rsaPSS 32 | int? saltLength; 33 | 34 | /// The digest used for PSS signature 35 | String? pssDigest; 36 | 37 | /// The signature 38 | String? signature; 39 | 40 | /// The plain PEM string 41 | String? plain; 42 | 43 | /// The extension 44 | @Deprecated('Use certificationRequestInfo.extensions instead') 45 | CertificateSigningRequestExtensions? extensions; 46 | 47 | /// The certificationRequestInfo sequence as base64 48 | String? certificationRequestInfoSeq; 49 | 50 | CertificateSigningRequestData({ 51 | this.subject, 52 | this.version, 53 | this.signature, 54 | this.signatureAlgorithm, 55 | this.signatureAlgorithmReadableName, 56 | this.publicKeyInfo, 57 | this.plain, 58 | this.extensions, 59 | this.certificationRequestInfoSeq, 60 | this.certificationRequestInfo, 61 | this.saltLength, 62 | this.pssDigest, 63 | }); 64 | 65 | /* 66 | * Json to CertificateSigningRequestData object 67 | */ 68 | factory CertificateSigningRequestData.fromJson(Map json) => 69 | _$CertificateSigningRequestDataFromJson(json); 70 | 71 | /* 72 | * CertificateSigningRequestData object to json 73 | */ 74 | Map toJson() => _$CertificateSigningRequestDataToJson(this); 75 | } 76 | -------------------------------------------------------------------------------- /lib/src/model/csr/CertificateSigningRequestData.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'CertificateSigningRequestData.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | CertificateSigningRequestData _$CertificateSigningRequestDataFromJson( 10 | Map json) => 11 | CertificateSigningRequestData( 12 | subject: (json['subject'] as Map?)?.map( 13 | (k, e) => MapEntry(k, e as String), 14 | ), 15 | version: json['version'] as int?, 16 | signature: json['signature'] as String?, 17 | signatureAlgorithm: json['signatureAlgorithm'] as String?, 18 | signatureAlgorithmReadableName: 19 | json['signatureAlgorithmReadableName'] as String?, 20 | publicKeyInfo: json['publicKeyInfo'] == null 21 | ? null 22 | : SubjectPublicKeyInfo.fromJson( 23 | json['publicKeyInfo'] as Map), 24 | plain: json['plain'] as String?, 25 | extensions: json['extensions'] == null 26 | ? null 27 | : CertificateSigningRequestExtensions.fromJson( 28 | json['extensions'] as Map), 29 | certificationRequestInfoSeq: 30 | json['certificationRequestInfoSeq'] as String?, 31 | certificationRequestInfo: json['certificationRequestInfo'] == null 32 | ? null 33 | : CertificationRequestInfo.fromJson( 34 | json['certificationRequestInfo'] as Map), 35 | ); 36 | 37 | Map _$CertificateSigningRequestDataToJson( 38 | CertificateSigningRequestData instance) { 39 | final val = {}; 40 | 41 | void writeNotNull(String key, dynamic value) { 42 | if (value != null) { 43 | val[key] = value; 44 | } 45 | } 46 | 47 | writeNotNull( 48 | 'certificationRequestInfo', instance.certificationRequestInfo?.toJson()); 49 | writeNotNull('version', instance.version); 50 | writeNotNull('subject', instance.subject); 51 | writeNotNull('publicKeyInfo', instance.publicKeyInfo?.toJson()); 52 | writeNotNull('signatureAlgorithm', instance.signatureAlgorithm); 53 | writeNotNull('signatureAlgorithmReadableName', 54 | instance.signatureAlgorithmReadableName); 55 | writeNotNull('signature', instance.signature); 56 | writeNotNull('plain', instance.plain); 57 | writeNotNull('extensions', instance.extensions?.toJson()); 58 | writeNotNull( 59 | 'certificationRequestInfoSeq', instance.certificationRequestInfoSeq); 60 | return val; 61 | } 62 | -------------------------------------------------------------------------------- /lib/src/model/csr/CertificateSigningRequestExtensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'CertificateSigningRequestExtensions.g.dart'; 4 | 5 | /// 6 | /// Model that represents the extensions of a x509Certificate 7 | /// 8 | @JsonSerializable(includeIfNull: false, explicitToJson: true) 9 | class CertificateSigningRequestExtensions { 10 | /// The subject alternative names 11 | List? subjectAlternativNames; 12 | 13 | // basicConstraints 14 | // authorityKeyIdentifier 15 | // cRLDistributionPoints 16 | // keyUsage 17 | // extKeyUsage 18 | // certificatePolicies 19 | // authorityInfoAccess => OCSP und caIssuers 20 | 21 | CertificateSigningRequestExtensions({ 22 | this.subjectAlternativNames, 23 | }); 24 | 25 | /* 26 | * Json to CertificateSigningRequestExtensions object 27 | */ 28 | factory CertificateSigningRequestExtensions.fromJson( 29 | Map json) => 30 | _$CertificateSigningRequestExtensionsFromJson(json); 31 | 32 | /* 33 | * CertificateSigningRequestExtensions object to json 34 | */ 35 | Map toJson() => 36 | _$CertificateSigningRequestExtensionsToJson(this); 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/model/csr/CertificateSigningRequestExtensions.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'CertificateSigningRequestExtensions.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | CertificateSigningRequestExtensions 10 | _$CertificateSigningRequestExtensionsFromJson(Map json) => 11 | CertificateSigningRequestExtensions( 12 | subjectAlternativNames: 13 | (json['subjectAlternativNames'] as List?) 14 | ?.map((e) => e as String) 15 | .toList(), 16 | ); 17 | 18 | Map _$CertificateSigningRequestExtensionsToJson( 19 | CertificateSigningRequestExtensions instance) { 20 | final val = {}; 21 | 22 | void writeNotNull(String key, dynamic value) { 23 | if (value != null) { 24 | val[key] = value; 25 | } 26 | } 27 | 28 | writeNotNull('subjectAlternativNames', instance.subjectAlternativNames); 29 | return val; 30 | } 31 | -------------------------------------------------------------------------------- /lib/src/model/csr/CertificationRequestInfo.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/csr/CertificateSigningRequestExtensions.dart'; 2 | import 'package:basic_utils/src/model/csr/SubjectPublicKeyInfo.dart'; 3 | import 'package:json_annotation/json_annotation.dart'; 4 | 5 | part 'CertificationRequestInfo.g.dart'; 6 | 7 | @JsonSerializable(includeIfNull: false, explicitToJson: true) 8 | class CertificationRequestInfo { 9 | /// The version 10 | int? version; 11 | 12 | /// The subject data of the certificate singing request 13 | Map? subject; 14 | 15 | /// The public key information 16 | SubjectPublicKeyInfo? publicKeyInfo; 17 | 18 | CertificateSigningRequestExtensions? extensions; 19 | 20 | CertificationRequestInfo({ 21 | this.subject, 22 | this.version, 23 | this.publicKeyInfo, 24 | this.extensions, 25 | }); 26 | 27 | /* 28 | * Json to CertificationRequestInfo object 29 | */ 30 | factory CertificationRequestInfo.fromJson(Map json) => 31 | _$CertificationRequestInfoFromJson(json); 32 | 33 | /* 34 | * CertificationRequestInfo object to json 35 | */ 36 | Map toJson() => _$CertificationRequestInfoToJson(this); 37 | } 38 | -------------------------------------------------------------------------------- /lib/src/model/csr/CertificationRequestInfo.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'CertificationRequestInfo.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | CertificationRequestInfo _$CertificationRequestInfoFromJson( 10 | Map json) => 11 | CertificationRequestInfo( 12 | subject: (json['subject'] as Map?)?.map( 13 | (k, e) => MapEntry(k, e as String), 14 | ), 15 | version: json['version'] as int?, 16 | publicKeyInfo: json['publicKeyInfo'] == null 17 | ? null 18 | : SubjectPublicKeyInfo.fromJson( 19 | json['publicKeyInfo'] as Map), 20 | extensions: json['extensions'] == null 21 | ? null 22 | : CertificateSigningRequestExtensions.fromJson( 23 | json['extensions'] as Map), 24 | ); 25 | 26 | Map _$CertificationRequestInfoToJson( 27 | CertificationRequestInfo instance) { 28 | final val = {}; 29 | 30 | void writeNotNull(String key, dynamic value) { 31 | if (value != null) { 32 | val[key] = value; 33 | } 34 | } 35 | 36 | writeNotNull('version', instance.version); 37 | writeNotNull('subject', instance.subject); 38 | writeNotNull('publicKeyInfo', instance.publicKeyInfo?.toJson()); 39 | writeNotNull('extensions', instance.extensions?.toJson()); 40 | return val; 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/model/csr/SubjectPublicKeyInfo.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'SubjectPublicKeyInfo.g.dart'; 4 | 5 | /// 6 | /// Model that a public key from a X509Certificate 7 | /// 8 | @JsonSerializable(includeIfNull: false, explicitToJson: true) 9 | class SubjectPublicKeyInfo { 10 | /// The algorithm of the public key 11 | String? algorithm; 12 | 13 | /// The readable name of the algorithm 14 | String? algorithmReadableName; 15 | 16 | /// The parameter of the public key 17 | String? parameter; 18 | 19 | /// The readable name of the parameter 20 | String? parameterReadableName; 21 | 22 | /// The key length of the public key 23 | int? length; 24 | 25 | /// The sha1 thumbprint of the public key 26 | String? sha1Thumbprint; 27 | 28 | /// The sha256 thumbprint of the public key 29 | String? sha256Thumbprint; 30 | 31 | /// The bytes representing the public key as String 32 | String? bytes; 33 | 34 | /// The exponent used on a RSA public key 35 | int? exponent; 36 | 37 | SubjectPublicKeyInfo({ 38 | this.algorithm, 39 | this.length, 40 | this.sha1Thumbprint, 41 | this.sha256Thumbprint, 42 | this.bytes, 43 | this.algorithmReadableName, 44 | this.parameter, 45 | this.parameterReadableName, 46 | this.exponent, 47 | }); 48 | 49 | /* 50 | * Json to SubjectPublicKeyInfo object 51 | */ 52 | factory SubjectPublicKeyInfo.fromJson(Map json) => 53 | _$SubjectPublicKeyInfoFromJson(json); 54 | 55 | /* 56 | * SubjectPublicKeyInfo object to json 57 | */ 58 | Map toJson() => _$SubjectPublicKeyInfoToJson(this); 59 | } 60 | -------------------------------------------------------------------------------- /lib/src/model/csr/SubjectPublicKeyInfo.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'SubjectPublicKeyInfo.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | SubjectPublicKeyInfo _$SubjectPublicKeyInfoFromJson( 10 | Map json) => 11 | SubjectPublicKeyInfo( 12 | algorithm: json['algorithm'] as String?, 13 | length: json['length'] as int?, 14 | sha1Thumbprint: json['sha1Thumbprint'] as String?, 15 | sha256Thumbprint: json['sha256Thumbprint'] as String?, 16 | bytes: json['bytes'] as String?, 17 | algorithmReadableName: json['algorithmReadableName'] as String?, 18 | parameter: json['parameter'] as String?, 19 | parameterReadableName: json['parameterReadableName'] as String?, 20 | exponent: json['exponent'] as int?, 21 | ); 22 | 23 | Map _$SubjectPublicKeyInfoToJson( 24 | SubjectPublicKeyInfo instance) { 25 | final val = {}; 26 | 27 | void writeNotNull(String key, dynamic value) { 28 | if (value != null) { 29 | val[key] = value; 30 | } 31 | } 32 | 33 | writeNotNull('algorithm', instance.algorithm); 34 | writeNotNull('algorithmReadableName', instance.algorithmReadableName); 35 | writeNotNull('parameter', instance.parameter); 36 | writeNotNull('parameterReadableName', instance.parameterReadableName); 37 | writeNotNull('length', instance.length); 38 | writeNotNull('sha1Thumbprint', instance.sha1Thumbprint); 39 | writeNotNull('sha256Thumbprint', instance.sha256Thumbprint); 40 | writeNotNull('bytes', instance.bytes); 41 | writeNotNull('exponent', instance.exponent); 42 | return val; 43 | } 44 | -------------------------------------------------------------------------------- /lib/src/model/exception/HttpResponseException.dart: -------------------------------------------------------------------------------- 1 | class HttpResponseException implements Exception { 2 | final String message; 3 | final String? body; 4 | final String statusCode; 5 | final Map? headers; 6 | 7 | /// The URL of the HTTP request or response that failed. 8 | final Uri? uri; 9 | 10 | HttpResponseException(this.message, this.statusCode, 11 | {this.uri, this.body, this.headers}); 12 | 13 | @override 14 | String toString() => message; 15 | } 16 | -------------------------------------------------------------------------------- /lib/src/model/ocsp/BasicOCSPResponse.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/ocsp/OCSPResponseData.dart'; 2 | 3 | /// 4 | ///``` 5 | /// BasicOCSPResponse ::= SEQUENCE { 6 | /// tbsResponseData ResponseData, 7 | /// signatureAlgorithm AlgorithmIdentifier, 8 | /// signature BIT STRING, 9 | /// certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } 10 | ///``` 11 | /// 12 | class BasicOCSPResponse { 13 | OCSPResponseData? responseData; 14 | 15 | BasicOCSPResponse({this.responseData}); 16 | } 17 | -------------------------------------------------------------------------------- /lib/src/model/ocsp/OCSPCertStatus.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/ocsp/OCSPCertStatusValues.dart'; 2 | 3 | /// 4 | ///``` 5 | ///CertStatus ::= CHOICE { 6 | /// good [0] IMPLICIT NULL, 7 | /// revoked [1] IMPLICIT RevokedInfo, 8 | /// unknown [2] IMPLICIT UnknownInfo } 9 | /// 10 | /// RevokedInfo ::= SEQUENCE { 11 | /// revocationTime GeneralizedTime, 12 | /// revocationReason [0] EXPLICIT CRLReason OPTIONAL } 13 | /// 14 | /// UnknownInfo ::= NULL 15 | ///``` 16 | /// 17 | class OCSPCertStatus { 18 | OCSPCertStatusValues? status; 19 | DateTime? revocationTime; 20 | 21 | OCSPCertStatus({this.status, this.revocationTime}); 22 | } 23 | -------------------------------------------------------------------------------- /lib/src/model/ocsp/OCSPCertStatusValues.dart: -------------------------------------------------------------------------------- 1 | /// 2 | ///``` 3 | ///CertStatus ::= CHOICE { 4 | /// good [0] IMPLICIT NULL, 5 | /// revoked [1] IMPLICIT RevokedInfo, 6 | /// unknown [2] IMPLICIT UnknownInfo } 7 | ///``` 8 | /// 9 | enum OCSPCertStatusValues { GOOD, REVOKED, UNKNOWN } 10 | -------------------------------------------------------------------------------- /lib/src/model/ocsp/OCSPResponse.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/ocsp/BasicOCSPResponse.dart'; 2 | import 'package:basic_utils/src/model/ocsp/OCSPResponseStatus.dart'; 3 | 4 | class OCSPResponse { 5 | OCSPResponseStatus responseStatus; 6 | 7 | BasicOCSPResponse? basicOCSPResponse; 8 | 9 | OCSPResponse(this.responseStatus, {this.basicOCSPResponse}); 10 | } 11 | -------------------------------------------------------------------------------- /lib/src/model/ocsp/OCSPResponseData.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/ocsp/OCSPSingleResponse.dart'; 2 | 3 | /// 4 | ///``` 5 | ///ResponseData ::= SEQUENCE { 6 | /// version [0] EXPLICIT Version DEFAULT v1, 7 | /// responderID ResponderID, 8 | /// producedAt GeneralizedTime, 9 | /// responses SEQUENCE OF SingleResponse, 10 | /// responseExtensions [1] EXPLICIT Extensions OPTIONAL } 11 | ///``` 12 | /// 13 | class OCSPResponseData { 14 | List singleResponse; 15 | 16 | OCSPResponseData(this.singleResponse); 17 | } 18 | -------------------------------------------------------------------------------- /lib/src/model/ocsp/OCSPResponseStatus.dart: -------------------------------------------------------------------------------- 1 | /// 2 | ///``` 3 | ///OCSPResponseStatus ::= ENUMERATED { 4 | /// successful (0), -- Response has valid confirmations 5 | /// malformedRequest (1), -- Illegal confirmation request 6 | /// internalError (2), -- Internal error in issuer 7 | /// tryLater (3), -- Try again later 8 | /// -- (4) is not used 9 | /// sigRequired (5), -- Must sign the request 10 | /// unauthorized (6) -- Request unauthorized 11 | /// } 12 | ///``` 13 | /// 14 | enum OCSPResponseStatus { 15 | SUCCESSFUL, 16 | MALFORMED_REQUEST, 17 | INTERNAL_ERROR, 18 | TRY_LATER, 19 | SIG_REQUIRED, 20 | UNAUTHORIZED 21 | } 22 | -------------------------------------------------------------------------------- /lib/src/model/ocsp/OCSPSingleResponse.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/ocsp/OCSPCertStatus.dart'; 2 | 3 | /// 4 | ///``` 5 | ///SingleResponse ::= SEQUENCE { 6 | /// certID CertID, 7 | /// certStatus CertStatus, 8 | /// thisUpdate GeneralizedTime, 9 | /// nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, 10 | /// singleExtensions [1] EXPLICIT Extensions OPTIONAL } 11 | ///``` 12 | /// 13 | class OCSPSingleResponse { 14 | OCSPCertStatus certStatus; 15 | DateTime thisUpdate; 16 | 17 | OCSPSingleResponse(this.certStatus, this.thisUpdate); 18 | } 19 | -------------------------------------------------------------------------------- /lib/src/model/pkcs7/Pkcs7CertificateData.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/x509/X509CertificateData.dart'; 2 | import 'package:json_annotation/json_annotation.dart'; 3 | 4 | part 'Pkcs7CertificateData.g.dart'; 5 | 6 | @JsonSerializable(includeIfNull: false, explicitToJson: true) 7 | class Pkcs7CertificateData { 8 | /// The syntax version number 9 | int? version; 10 | 11 | /// Indicates the type of the associated content. 12 | String? contentType; 13 | 14 | /// The certificates within the PKCS7 15 | List? certificates; 16 | 17 | Pkcs7CertificateData({this.version, this.certificates, this.contentType}); 18 | 19 | /* 20 | * Json to Pkcs7CertificateData object 21 | */ 22 | factory Pkcs7CertificateData.fromJson(Map json) => 23 | _$Pkcs7CertificateDataFromJson(json); 24 | 25 | /* 26 | * Pkcs7CertificateData object to json 27 | */ 28 | Map toJson() => _$Pkcs7CertificateDataToJson(this); 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/model/pkcs7/Pkcs7CertificateData.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'Pkcs7CertificateData.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | Pkcs7CertificateData _$Pkcs7CertificateDataFromJson( 10 | Map json) => 11 | Pkcs7CertificateData( 12 | version: json['version'] as int?, 13 | certificates: (json['certificates'] as List?) 14 | ?.map((e) => X509CertificateData.fromJson(e as Map)) 15 | .toList(), 16 | contentType: json['contentType'] as String?, 17 | ); 18 | 19 | Map _$Pkcs7CertificateDataToJson( 20 | Pkcs7CertificateData instance) { 21 | final val = {}; 22 | 23 | void writeNotNull(String key, dynamic value) { 24 | if (value != null) { 25 | val[key] = value; 26 | } 27 | } 28 | 29 | writeNotNull('version', instance.version); 30 | writeNotNull('contentType', instance.contentType); 31 | writeNotNull( 32 | 'certificates', instance.certificates?.map((e) => e.toJson()).toList()); 33 | return val; 34 | } 35 | -------------------------------------------------------------------------------- /lib/src/model/x509/CertificateChainCheckData.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/x509/CertificateChainPairCheckResult.dart'; 2 | import 'package:basic_utils/src/model/x509/X509CertificateData.dart'; 3 | 4 | /// 5 | /// Model for representing a certificate chain check. 6 | /// 7 | class CertificateChainCheckData { 8 | /// The chain 9 | List? chain; 10 | 11 | /// 12 | /// The check result for each pair of the chain. 13 | /// The amount of pairs is depending on the length of the chain.7 14 | /// 15 | List? pairs; 16 | 17 | CertificateChainCheckData({this.chain}); 18 | 19 | /// 20 | /// Returns true of the chain is valid. For detail information take a look at 21 | /// the [pairs] field. 22 | /// 23 | bool isValid() { 24 | var valid = true; 25 | if (pairs != null) { 26 | for (var p in pairs!) { 27 | valid = p.isValid(); 28 | if (valid == false) { 29 | break; 30 | } 31 | } 32 | } 33 | return valid; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/src/model/x509/CertificateChainPairCheckResult.dart: -------------------------------------------------------------------------------- 1 | /// 2 | /// Model for representing the pair check 3 | /// 4 | class CertificateChainPairCheckResult { 5 | /// Defines if the issuer of a certificate matches it's parent subject data. 6 | bool dnDataMatch = true; 7 | 8 | /// Defines if the signature of a certificate matches it's parents public key 9 | bool signatureMatch = true; 10 | 11 | CertificateChainPairCheckResult(); 12 | 13 | /// 14 | /// Returns true if all checks where passed successfuly by the pair 15 | /// 16 | bool isValid() { 17 | return dnDataMatch && signatureMatch; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/src/model/x509/ExtendedKeyUsage.dart: -------------------------------------------------------------------------------- 1 | enum ExtendedKeyUsage { 2 | SERVER_AUTH, 3 | CLIENT_AUTH, 4 | CODE_SIGNING, 5 | EMAIL_PROTECTION, 6 | TIME_STAMPING, 7 | OCSP_SIGNING, 8 | BIMI 9 | } 10 | -------------------------------------------------------------------------------- /lib/src/model/x509/KeyUsage.dart: -------------------------------------------------------------------------------- 1 | enum KeyUsage { 2 | /// 0 3 | DIGITAL_SIGNATURE, 4 | /// 1 (Also called contentCommitment now) 5 | NON_REPUDIATION, 6 | /// 2 7 | KEY_ENCIPHERMENT, 8 | /// 3 9 | DATA_ENCIPHERMENT, 10 | /// 4 11 | KEY_AGREEMENT, 12 | /// 5 13 | KEY_CERT_SIGN, 14 | /// 6 15 | CRL_SIGN, 16 | /// 7 17 | ENCIPHER_ONLY, 18 | /// 8 19 | DECIPHER_ONLY 20 | } 21 | -------------------------------------------------------------------------------- /lib/src/model/x509/TbsCertificate.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/csr/SubjectPublicKeyInfo.dart'; 2 | import 'package:basic_utils/src/model/x509/X509CertificateDataExtensions.dart'; 3 | import 'package:json_annotation/json_annotation.dart'; 4 | 5 | import 'X509CertificateValidity.dart'; 6 | 7 | part 'TbsCertificate.g.dart'; 8 | 9 | /// 10 | /// Model that represents the data of a TbsCertificate 11 | /// 12 | @JsonSerializable(includeIfNull: false, explicitToJson: true) 13 | class TbsCertificate { 14 | /// The version of the certificate 15 | int version; 16 | 17 | /// The serialNumber of the certificate 18 | BigInt serialNumber; 19 | 20 | /// The signatureAlgorithm of the certificate 21 | String signatureAlgorithm; 22 | 23 | /// The readable name of the signatureAlgorithm of the certificate 24 | String? signatureAlgorithmReadableName; 25 | 26 | /// The issuer data of the certificate 27 | Map issuer; 28 | 29 | /// The validity of the certificate 30 | X509CertificateValidity validity; 31 | 32 | /// The subject data of the certificate 33 | Map subject; 34 | 35 | /// The public key data from the certificate 36 | SubjectPublicKeyInfo subjectPublicKeyInfo; 37 | 38 | /// The certificate extensions 39 | X509CertificateDataExtensions? extensions; 40 | 41 | TbsCertificate({ 42 | required this.version, 43 | required this.serialNumber, 44 | required this.issuer, 45 | required this.validity, 46 | required this.subject, 47 | required this.subjectPublicKeyInfo, 48 | required this.signatureAlgorithm, 49 | required this.signatureAlgorithmReadableName, 50 | this.extensions, 51 | }); 52 | 53 | /* 54 | * Json to TbsCertificate object 55 | */ 56 | factory TbsCertificate.fromJson(Map json) => 57 | _$TbsCertificateFromJson(json); 58 | 59 | /* 60 | * TbsCertificate object to json 61 | */ 62 | Map toJson() => _$TbsCertificateToJson(this); 63 | } 64 | -------------------------------------------------------------------------------- /lib/src/model/x509/TbsCertificate.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'TbsCertificate.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | TbsCertificate _$TbsCertificateFromJson(Map json) => 10 | TbsCertificate( 11 | version: json['version'] as int, 12 | serialNumber: BigInt.parse(json['serialNumber'] as String), 13 | issuer: Map.from(json['issuer'] as Map), 14 | validity: X509CertificateValidity.fromJson( 15 | json['validity'] as Map), 16 | subject: Map.from(json['subject'] as Map), 17 | subjectPublicKeyInfo: SubjectPublicKeyInfo.fromJson( 18 | json['subjectPublicKeyInfo'] as Map), 19 | signatureAlgorithm: json['signatureAlgorithm'] as String, 20 | signatureAlgorithmReadableName: 21 | json['signatureAlgorithmReadableName'] as String?, 22 | extensions: json['extensions'] == null 23 | ? null 24 | : X509CertificateDataExtensions.fromJson( 25 | json['extensions'] as Map), 26 | ); 27 | 28 | Map _$TbsCertificateToJson(TbsCertificate instance) { 29 | final val = { 30 | 'version': instance.version, 31 | 'serialNumber': instance.serialNumber.toString(), 32 | 'signatureAlgorithm': instance.signatureAlgorithm, 33 | }; 34 | 35 | void writeNotNull(String key, dynamic value) { 36 | if (value != null) { 37 | val[key] = value; 38 | } 39 | } 40 | 41 | writeNotNull('signatureAlgorithmReadableName', 42 | instance.signatureAlgorithmReadableName); 43 | val['issuer'] = instance.issuer; 44 | val['validity'] = instance.validity.toJson(); 45 | val['subject'] = instance.subject; 46 | val['subjectPublicKeyInfo'] = instance.subjectPublicKeyInfo.toJson(); 47 | writeNotNull('extensions', instance.extensions?.toJson()); 48 | return val; 49 | } 50 | -------------------------------------------------------------------------------- /lib/src/model/x509/VmcData.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'VmcData.g.dart'; 4 | 5 | /// 6 | /// Model that represents a verified mark certificate data 7 | /// 8 | @JsonSerializable(includeIfNull: false, explicitToJson: true) 9 | class VmcData { 10 | /// The base64 encoded logo 11 | String? base64Logo; 12 | 13 | /// The logo type 14 | String? type; 15 | 16 | /// The hash 17 | String? hash; 18 | 19 | /// The readable version of the algorithm of the hash 20 | String? hashAlgorithmReadable; 21 | 22 | /// The algorithm of the hash 23 | String? hashAlgorithm; 24 | 25 | VmcData({ 26 | this.base64Logo, 27 | this.hash, 28 | this.hashAlgorithm, 29 | this.hashAlgorithmReadable, 30 | this.type, 31 | }); 32 | 33 | /// 34 | ///Json to VmcData object 35 | /// 36 | factory VmcData.fromJson(Map json) => 37 | _$VmcDataFromJson(json); 38 | 39 | /// 40 | /// VmcData object to json 41 | /// 42 | Map toJson() => _$VmcDataToJson(this); 43 | 44 | String getFullSvgData() { 45 | return 'data:$type;base64,$base64Logo'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/src/model/x509/VmcData.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'VmcData.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | VmcData _$VmcDataFromJson(Map json) => VmcData( 10 | base64Logo: json['base64Logo'] as String?, 11 | hash: json['hash'] as String?, 12 | hashAlgorithm: json['hashAlgorithm'] as String?, 13 | hashAlgorithmReadable: json['hashAlgorithmReadable'] as String?, 14 | type: json['type'] as String?, 15 | ); 16 | 17 | Map _$VmcDataToJson(VmcData instance) { 18 | final val = {}; 19 | 20 | void writeNotNull(String key, dynamic value) { 21 | if (value != null) { 22 | val[key] = value; 23 | } 24 | } 25 | 26 | writeNotNull('base64Logo', instance.base64Logo); 27 | writeNotNull('type', instance.type); 28 | writeNotNull('hash', instance.hash); 29 | writeNotNull('hashAlgorithmReadable', instance.hashAlgorithmReadable); 30 | writeNotNull('hashAlgorithm', instance.hashAlgorithm); 31 | return val; 32 | } 33 | -------------------------------------------------------------------------------- /lib/src/model/x509/X509CertificateData.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/x509/ExtendedKeyUsage.dart'; 2 | import 'package:basic_utils/src/model/x509/TbsCertificate.dart'; 3 | import 'package:basic_utils/src/model/x509/X509CertificateDataExtensions.dart'; 4 | import 'package:basic_utils/src/model/x509/X509CertificatePublicKeyData.dart'; 5 | import 'package:json_annotation/json_annotation.dart'; 6 | 7 | import 'X509CertificateValidity.dart'; 8 | 9 | part 'X509CertificateData.g.dart'; 10 | 11 | /// 12 | /// Model that represents the data of a x509Certificate 13 | /// 14 | @JsonSerializable(includeIfNull: false, explicitToJson: true) 15 | class X509CertificateData { 16 | /// The tbsCertificate data 17 | TbsCertificate? tbsCertificate; 18 | 19 | /// The version of the certificate 20 | @Deprecated('Use tbsCertificate.version instead') 21 | int version; 22 | 23 | /// The serialNumber of the certificate 24 | @Deprecated('Use tbsCertificate.serialNumber instead') 25 | BigInt serialNumber; 26 | 27 | /// The signatureAlgorithm of the certificate 28 | String signatureAlgorithm; 29 | 30 | /// The readable name of the signatureAlgorithm of the certificate 31 | String? signatureAlgorithmReadableName; 32 | 33 | /// The issuer data of the certificate 34 | @Deprecated('Use tbsCertificate.issuer instead') 35 | Map issuer; 36 | 37 | /// The validity of the certificate 38 | @Deprecated('Use tbsCertificate.validity instead') 39 | X509CertificateValidity validity; 40 | 41 | /// The subject data of the certificate 42 | @Deprecated('Use tbsCertificate.subject instead') 43 | Map subject; 44 | 45 | /// The sha1 thumbprint for the certificate 46 | String? sha1Thumbprint; 47 | 48 | /// The sha256 thumbprint for the certificate 49 | String? sha256Thumbprint; 50 | 51 | /// The md5 thumbprint for the certificate 52 | String? md5Thumbprint; 53 | 54 | /// The public key data from the certificate 55 | @Deprecated('Use tbsCertificate.subjectPublicKeyInfo instead') 56 | X509CertificatePublicKeyData publicKeyData; 57 | 58 | /// The subject alternative names 59 | @Deprecated('Use extensions.subjectAlternativNames instead') 60 | List? subjectAlternativNames; 61 | 62 | /// The plain certificate pem string, that was used to decode. 63 | String? plain; 64 | 65 | /// The extended key usage extension 66 | @Deprecated('Use extensions.extKeyUsage instead') 67 | List? extKeyUsage; 68 | 69 | /// The certificate extensions 70 | @Deprecated('Use tbsCertificate.extensions instead') 71 | X509CertificateDataExtensions? extensions; 72 | 73 | /// The signature 74 | String? signature; 75 | 76 | /// The tbsCertificateSeq as base64 string 77 | String? tbsCertificateSeqAsString; 78 | 79 | X509CertificateData({ 80 | required this.version, 81 | required this.serialNumber, 82 | required this.signatureAlgorithm, 83 | required this.issuer, 84 | required this.validity, 85 | required this.subject, 86 | required this.tbsCertificate, 87 | this.signatureAlgorithmReadableName, 88 | this.sha1Thumbprint, 89 | this.sha256Thumbprint, 90 | this.md5Thumbprint, 91 | required this.publicKeyData, 92 | required this.subjectAlternativNames, 93 | this.plain, 94 | this.extKeyUsage, 95 | this.extensions, 96 | this.tbsCertificateSeqAsString, 97 | required this.signature, 98 | }); 99 | 100 | /* 101 | * Json to X509CertificateData object 102 | */ 103 | factory X509CertificateData.fromJson(Map json) => 104 | _$X509CertificateDataFromJson(json); 105 | 106 | /* 107 | * X509CertificateData object to json 108 | */ 109 | Map toJson() => _$X509CertificateDataToJson(this); 110 | } 111 | -------------------------------------------------------------------------------- /lib/src/model/x509/X509CertificateData.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'X509CertificateData.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | X509CertificateData _$X509CertificateDataFromJson(Map json) => 10 | X509CertificateData( 11 | version: json['version'] as int, 12 | serialNumber: BigInt.parse(json['serialNumber'] as String), 13 | signatureAlgorithm: json['signatureAlgorithm'] as String, 14 | issuer: Map.from(json['issuer'] as Map), 15 | validity: X509CertificateValidity.fromJson( 16 | json['validity'] as Map), 17 | subject: Map.from(json['subject'] as Map), 18 | tbsCertificate: json['tbsCertificate'] == null 19 | ? null 20 | : TbsCertificate.fromJson( 21 | json['tbsCertificate'] as Map), 22 | signatureAlgorithmReadableName: 23 | json['signatureAlgorithmReadableName'] as String?, 24 | sha1Thumbprint: json['sha1Thumbprint'] as String?, 25 | sha256Thumbprint: json['sha256Thumbprint'] as String?, 26 | md5Thumbprint: json['md5Thumbprint'] as String?, 27 | publicKeyData: X509CertificatePublicKeyData.fromJson( 28 | json['publicKeyData'] as Map), 29 | subjectAlternativNames: (json['subjectAlternativNames'] as List?) 30 | ?.map((e) => e as String) 31 | .toList(), 32 | plain: json['plain'] as String?, 33 | extKeyUsage: (json['extKeyUsage'] as List?) 34 | ?.map((e) => $enumDecode(_$ExtendedKeyUsageEnumMap, e)) 35 | .toList(), 36 | extensions: json['extensions'] == null 37 | ? null 38 | : X509CertificateDataExtensions.fromJson( 39 | json['extensions'] as Map), 40 | tbsCertificateSeqAsString: json['tbsCertificateSeqAsString'] as String?, 41 | signature: json['signature'] as String?, 42 | ); 43 | 44 | Map _$X509CertificateDataToJson(X509CertificateData instance) { 45 | final val = {}; 46 | 47 | void writeNotNull(String key, dynamic value) { 48 | if (value != null) { 49 | val[key] = value; 50 | } 51 | } 52 | 53 | writeNotNull('tbsCertificate', instance.tbsCertificate?.toJson()); 54 | val['version'] = instance.version; 55 | val['serialNumber'] = instance.serialNumber.toString(); 56 | val['signatureAlgorithm'] = instance.signatureAlgorithm; 57 | writeNotNull('signatureAlgorithmReadableName', 58 | instance.signatureAlgorithmReadableName); 59 | val['issuer'] = instance.issuer; 60 | val['validity'] = instance.validity.toJson(); 61 | val['subject'] = instance.subject; 62 | writeNotNull('sha1Thumbprint', instance.sha1Thumbprint); 63 | writeNotNull('sha256Thumbprint', instance.sha256Thumbprint); 64 | writeNotNull('md5Thumbprint', instance.md5Thumbprint); 65 | val['publicKeyData'] = instance.publicKeyData.toJson(); 66 | writeNotNull('subjectAlternativNames', instance.subjectAlternativNames); 67 | writeNotNull('plain', instance.plain); 68 | writeNotNull('extKeyUsage', 69 | instance.extKeyUsage?.map((e) => _$ExtendedKeyUsageEnumMap[e]!).toList()); 70 | writeNotNull('extensions', instance.extensions?.toJson()); 71 | val['signature'] = instance.signature; 72 | writeNotNull('tbsCertificateSeqAsString', instance.tbsCertificateSeqAsString); 73 | return val; 74 | } 75 | 76 | const _$ExtendedKeyUsageEnumMap = { 77 | ExtendedKeyUsage.SERVER_AUTH: 'SERVER_AUTH', 78 | ExtendedKeyUsage.CLIENT_AUTH: 'CLIENT_AUTH', 79 | ExtendedKeyUsage.CODE_SIGNING: 'CODE_SIGNING', 80 | ExtendedKeyUsage.EMAIL_PROTECTION: 'EMAIL_PROTECTION', 81 | ExtendedKeyUsage.TIME_STAMPING: 'TIME_STAMPING', 82 | ExtendedKeyUsage.OCSP_SIGNING: 'OCSP_SIGNING', 83 | ExtendedKeyUsage.BIMI: 'BIMI', 84 | }; 85 | -------------------------------------------------------------------------------- /lib/src/model/x509/X509CertificateDataExtensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/x509/ExtendedKeyUsage.dart'; 2 | import 'package:basic_utils/src/model/x509/KeyUsage.dart'; 3 | import 'package:basic_utils/src/model/x509/VmcData.dart'; 4 | import 'package:json_annotation/json_annotation.dart'; 5 | 6 | part 'X509CertificateDataExtensions.g.dart'; 7 | 8 | /// 9 | /// Model that represents the extensions of a x509Certificate 10 | /// 11 | @JsonSerializable(includeIfNull: false, explicitToJson: true) 12 | class X509CertificateDataExtensions { 13 | /// The subject alternative names 14 | List? subjectAlternativNames; 15 | 16 | /// The extended key usage extension 17 | List? extKeyUsage; 18 | 19 | /// The key usage extension 20 | List? keyUsage; 21 | 22 | /// The cA field of the basic constraints extension 23 | bool? cA; 24 | 25 | /// The pathLenConstraint field of the basic constraints extension 26 | int? pathLenConstraint; 27 | 28 | /// The base64 encoded VMC logo 29 | VmcData? vmc; 30 | 31 | /// The distribution points for the crl files. Normally a url. 32 | List? cRLDistributionPoints; 33 | 34 | X509CertificateDataExtensions({ 35 | this.subjectAlternativNames, 36 | this.extKeyUsage, 37 | this.keyUsage, 38 | this.cA, 39 | this.pathLenConstraint, 40 | this.vmc, 41 | this.cRLDistributionPoints, 42 | }); 43 | 44 | /* 45 | * Json to X509CertificateDataExtensions object 46 | */ 47 | factory X509CertificateDataExtensions.fromJson(Map json) => 48 | _$X509CertificateDataExtensionsFromJson(json); 49 | 50 | /* 51 | * X509CertificateDataExtensions object to json 52 | */ 53 | Map toJson() => _$X509CertificateDataExtensionsToJson(this); 54 | } 55 | -------------------------------------------------------------------------------- /lib/src/model/x509/X509CertificateDataExtensions.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'X509CertificateDataExtensions.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | X509CertificateDataExtensions _$X509CertificateDataExtensionsFromJson( 10 | Map json) => 11 | X509CertificateDataExtensions( 12 | subjectAlternativNames: (json['subjectAlternativNames'] as List?) 13 | ?.map((e) => e as String) 14 | .toList(), 15 | extKeyUsage: (json['extKeyUsage'] as List?) 16 | ?.map((e) => $enumDecode(_$ExtendedKeyUsageEnumMap, e)) 17 | .toList(), 18 | keyUsage: (json['keyUsage'] as List?) 19 | ?.map((e) => $enumDecode(_$KeyUsageEnumMap, e)) 20 | .toList(), 21 | cA: json['cA'] as bool?, 22 | pathLenConstraint: json['pathLenConstraint'] as int?, 23 | vmc: json['vmc'] == null 24 | ? null 25 | : VmcData.fromJson(json['vmc'] as Map), 26 | cRLDistributionPoints: (json['cRLDistributionPoints'] as List?) 27 | ?.map((e) => e as String) 28 | .toList(), 29 | ); 30 | 31 | Map _$X509CertificateDataExtensionsToJson( 32 | X509CertificateDataExtensions instance) { 33 | final val = {}; 34 | 35 | void writeNotNull(String key, dynamic value) { 36 | if (value != null) { 37 | val[key] = value; 38 | } 39 | } 40 | 41 | writeNotNull('subjectAlternativNames', instance.subjectAlternativNames); 42 | writeNotNull('extKeyUsage', 43 | instance.extKeyUsage?.map((e) => _$ExtendedKeyUsageEnumMap[e]!).toList()); 44 | writeNotNull('keyUsage', 45 | instance.keyUsage?.map((e) => _$KeyUsageEnumMap[e]!).toList()); 46 | writeNotNull('cA', instance.cA); 47 | writeNotNull('pathLenConstraint', instance.pathLenConstraint); 48 | writeNotNull('vmc', instance.vmc?.toJson()); 49 | writeNotNull('cRLDistributionPoints', instance.cRLDistributionPoints); 50 | return val; 51 | } 52 | 53 | const _$ExtendedKeyUsageEnumMap = { 54 | ExtendedKeyUsage.SERVER_AUTH: 'SERVER_AUTH', 55 | ExtendedKeyUsage.CLIENT_AUTH: 'CLIENT_AUTH', 56 | ExtendedKeyUsage.CODE_SIGNING: 'CODE_SIGNING', 57 | ExtendedKeyUsage.EMAIL_PROTECTION: 'EMAIL_PROTECTION', 58 | ExtendedKeyUsage.TIME_STAMPING: 'TIME_STAMPING', 59 | ExtendedKeyUsage.OCSP_SIGNING: 'OCSP_SIGNING', 60 | ExtendedKeyUsage.BIMI: 'BIMI', 61 | }; 62 | 63 | const _$KeyUsageEnumMap = { 64 | KeyUsage.DIGITAL_SIGNATURE: 'DIGITAL_SIGNATURE', 65 | KeyUsage.NON_REPUDIATION: 'NON_REPUDIATION', 66 | KeyUsage.KEY_ENCIPHERMENT: 'KEY_ENCIPHERMENT', 67 | KeyUsage.DATA_ENCIPHERMENT: 'DATA_ENCIPHERMENT', 68 | KeyUsage.KEY_AGREEMENT: 'KEY_AGREEMENT', 69 | KeyUsage.KEY_CERT_SIGN: 'KEY_CERT_SIGN', 70 | KeyUsage.CRL_SIGN: 'CRL_SIGN', 71 | KeyUsage.ENCIPHER_ONLY: 'ENCIPHER_ONLY', 72 | KeyUsage.DECIPHER_ONLY: 'DECIPHER_ONLY', 73 | }; 74 | -------------------------------------------------------------------------------- /lib/src/model/x509/X509CertificateObject.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/model/x509/X509CertificateData.dart'; 2 | import 'package:json_annotation/json_annotation.dart'; 3 | 4 | part 'X509CertificateObject.g.dart'; 5 | 6 | /// 7 | /// Model that represents a x509Certificate 8 | /// 9 | @JsonSerializable(includeIfNull: false, explicitToJson: true) 10 | class X509CertificateObject { 11 | X509CertificateData? data; 12 | 13 | X509CertificateObject(this.data); 14 | 15 | /* 16 | * Json to X509CertificateObject object 17 | */ 18 | factory X509CertificateObject.fromJson(Map json) => 19 | _$X509CertificateObjectFromJson(json); 20 | 21 | /* 22 | * X509CertificateObject object to json 23 | */ 24 | Map toJson() => _$X509CertificateObjectToJson(this); 25 | } 26 | -------------------------------------------------------------------------------- /lib/src/model/x509/X509CertificateObject.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'X509CertificateObject.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | X509CertificateObject _$X509CertificateObjectFromJson( 10 | Map json) => 11 | X509CertificateObject( 12 | json['data'] == null 13 | ? null 14 | : X509CertificateData.fromJson(json['data'] as Map), 15 | ); 16 | 17 | Map _$X509CertificateObjectToJson( 18 | X509CertificateObject instance) { 19 | final val = {}; 20 | 21 | void writeNotNull(String key, dynamic value) { 22 | if (value != null) { 23 | val[key] = value; 24 | } 25 | } 26 | 27 | writeNotNull('data', instance.data?.toJson()); 28 | return val; 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/model/x509/X509CertificatePublicKeyData.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:basic_utils/src/model/csr/SubjectPublicKeyInfo.dart'; 4 | import 'package:json_annotation/json_annotation.dart'; 5 | 6 | part 'X509CertificatePublicKeyData.g.dart'; 7 | 8 | /// 9 | /// Model that a public key from a X509Certificate 10 | /// 11 | @JsonSerializable(includeIfNull: false, explicitToJson: true) 12 | class X509CertificatePublicKeyData { 13 | /// The algorithm of the public key 14 | String? algorithm; 15 | 16 | /// The readable name of the algorithm 17 | String? algorithmReadableName; 18 | 19 | /// The parameter of the public key 20 | String? parameter; 21 | 22 | /// The readable name of the parameter 23 | String? parameterReadableName; 24 | 25 | /// The key length of the public key 26 | int? length; 27 | 28 | /// The sha1 thumbprint of the public key 29 | String? sha1Thumbprint; 30 | 31 | /// The sha256 thumbprint of the public key 32 | String? sha256Thumbprint; 33 | 34 | /// The bytes representing the public key as String 35 | String? bytes; 36 | 37 | @JsonKey(fromJson: plainSha1FromJson, toJson: plainSha1ToJson) 38 | Uint8List? plainSha1; 39 | 40 | /// The exponent used on a RSA public key 41 | int? exponent; 42 | 43 | X509CertificatePublicKeyData({ 44 | this.algorithm, 45 | this.length, 46 | this.sha1Thumbprint, 47 | this.sha256Thumbprint, 48 | this.bytes, 49 | this.plainSha1, 50 | this.algorithmReadableName, 51 | this.parameter, 52 | this.parameterReadableName, 53 | this.exponent, 54 | }); 55 | 56 | /* 57 | * Json to X509CertificatePublicKeyData object 58 | */ 59 | factory X509CertificatePublicKeyData.fromJson(Map json) => 60 | _$X509CertificatePublicKeyDataFromJson(json); 61 | 62 | /* 63 | * X509CertificatePublicKeyData object to json 64 | */ 65 | Map toJson() => _$X509CertificatePublicKeyDataToJson(this); 66 | 67 | static Uint8List? plainSha1FromJson(List? json) { 68 | if (json == null) { 69 | return null; 70 | } 71 | return Uint8List.fromList(json); 72 | } 73 | 74 | static List? plainSha1ToJson(Uint8List? object) { 75 | if (object == null) { 76 | return null; 77 | } 78 | return object.toList(); 79 | } 80 | 81 | X509CertificatePublicKeyData.fromSubjectPublicKeyInfo( 82 | SubjectPublicKeyInfo info) { 83 | algorithm = info.algorithm; 84 | length = info.length; 85 | sha1Thumbprint = info.sha1Thumbprint; 86 | sha256Thumbprint = info.sha256Thumbprint; 87 | bytes = info.bytes; 88 | algorithmReadableName = info.algorithmReadableName; 89 | parameter = info.parameter; 90 | parameterReadableName = info.parameterReadableName; 91 | exponent = info.exponent; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /lib/src/model/x509/X509CertificatePublicKeyData.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'X509CertificatePublicKeyData.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | X509CertificatePublicKeyData _$X509CertificatePublicKeyDataFromJson( 10 | Map json) => 11 | X509CertificatePublicKeyData( 12 | algorithm: json['algorithm'] as String?, 13 | length: json['length'] as int?, 14 | sha1Thumbprint: json['sha1Thumbprint'] as String?, 15 | sha256Thumbprint: json['sha256Thumbprint'] as String?, 16 | bytes: json['bytes'] as String?, 17 | plainSha1: X509CertificatePublicKeyData.plainSha1FromJson( 18 | json['plainSha1'] as List?), 19 | algorithmReadableName: json['algorithmReadableName'] as String?, 20 | parameter: json['parameter'] as String?, 21 | parameterReadableName: json['parameterReadableName'] as String?, 22 | exponent: json['exponent'] as int?, 23 | ); 24 | 25 | Map _$X509CertificatePublicKeyDataToJson( 26 | X509CertificatePublicKeyData instance) { 27 | final val = {}; 28 | 29 | void writeNotNull(String key, dynamic value) { 30 | if (value != null) { 31 | val[key] = value; 32 | } 33 | } 34 | 35 | writeNotNull('algorithm', instance.algorithm); 36 | writeNotNull('algorithmReadableName', instance.algorithmReadableName); 37 | writeNotNull('parameter', instance.parameter); 38 | writeNotNull('parameterReadableName', instance.parameterReadableName); 39 | writeNotNull('length', instance.length); 40 | writeNotNull('sha1Thumbprint', instance.sha1Thumbprint); 41 | writeNotNull('sha256Thumbprint', instance.sha256Thumbprint); 42 | writeNotNull('bytes', instance.bytes); 43 | writeNotNull('plainSha1', 44 | X509CertificatePublicKeyData.plainSha1ToJson(instance.plainSha1)); 45 | writeNotNull('exponent', instance.exponent); 46 | return val; 47 | } 48 | -------------------------------------------------------------------------------- /lib/src/model/x509/X509CertificateValidity.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'X509CertificateValidity.g.dart'; 4 | 5 | /// 6 | /// Model that represents the validity data of a x509Certificate 7 | /// 8 | @JsonSerializable(includeIfNull: false, explicitToJson: true) 9 | class X509CertificateValidity { 10 | /// The start date 11 | DateTime notBefore; 12 | 13 | /// The end date 14 | DateTime notAfter; 15 | 16 | X509CertificateValidity({required this.notBefore,required this.notAfter}); 17 | 18 | /* 19 | * Json to X509CertificateValidity object 20 | */ 21 | factory X509CertificateValidity.fromJson(Map json) => 22 | _$X509CertificateValidityFromJson(json); 23 | 24 | /* 25 | * X509CertificateValidity object to json 26 | */ 27 | Map toJson() => _$X509CertificateValidityToJson(this); 28 | } 29 | -------------------------------------------------------------------------------- /lib/src/model/x509/X509CertificateValidity.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'X509CertificateValidity.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | X509CertificateValidity _$X509CertificateValidityFromJson( 10 | Map json) => 11 | X509CertificateValidity( 12 | notBefore: DateTime.parse(json['notBefore'] as String), 13 | notAfter: DateTime.parse(json['notAfter'] as String), 14 | ); 15 | 16 | Map _$X509CertificateValidityToJson( 17 | X509CertificateValidity instance) => 18 | { 19 | 'notBefore': instance.notBefore.toIso8601String(), 20 | 'notAfter': instance.notAfter.toIso8601String(), 21 | }; 22 | -------------------------------------------------------------------------------- /main_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io'; 3 | 4 | void main(List args) { 5 | var f = File("object_identifiers.csv"); 6 | List> list = []; 7 | for (var l in f.readAsLinesSync()) { 8 | var splitted = l.split(','); 9 | var s = splitted.elementAt(0); 10 | var splittedInts = s.split('.'); 11 | var asInt = []; 12 | for (var i in splittedInts) { 13 | asInt.add(int.parse(i)); 14 | } 15 | list.add({ 16 | 'identifierString': splitted.elementAt(0), 17 | 'readableName': splitted.elementAt(1), 18 | 'identifier': asInt 19 | }); 20 | } 21 | print(json.encode(list)); 22 | } 23 | -------------------------------------------------------------------------------- /object_identifiers.csv: -------------------------------------------------------------------------------- 1 | 1.2.840.113549.1.9.22.1,x509Certificate 2 | 1.2.840.113549.1.9.22.2,sdsiCertificate 3 | 1.2.840.113549.1.9.20,friendlyName 4 | 1.2.840.113549.1.9.21,localKeyID 5 | 1.2.840.113549.1.12.10.1.1,keyBag 6 | 1.2.840.113549.1.12.10.1.2,pkcs-8ShroudedKeyBag 7 | 1.2.840.113549.1.12.10.1.3,certBag 8 | 1.2.840.113549.1.12.10.1.4,crlBag 9 | 1.2.840.113549.1.12.10.1.5,secretBag 10 | 1.2.840.113549.1.12.10.1.6,safeContentsBag 11 | 1.2.840.113549.1.7.1,data 12 | 1.2.840.113549.1.7.6,encryptedData 13 | 1.2.840.113549.1.1.10,rsaPSS 14 | 2.16.840.1.101.3.4.2.1,SHA-256 15 | 2.16.840.1.101.3.4.2.2,SHA-384 16 | 2.16.840.1.101.3.4.2.3,SHA-512 17 | 2.16.840.1.101.3.4.2.4,SHA-224 18 | 2.5.4.3,commonName 19 | 2.5.4.6,countryName 20 | 2.5.4.10,organizationName 21 | 2.5.4.11,organizationalUnitName 22 | 1.3.6.1.4.1.311.60.2.1.3,jurisdictionOfIncorporationC 23 | 1.3.6.1.4.1.311.60.2.1.2,jurisdictionOfIncorporationSP 24 | 1.3.6.1.4.1.311.60.2.1.1,jurisdictionOfIncorporationL 25 | 2.5.4.15,businessCategory 26 | 2.5.4.5,serialNumber 27 | 2.5.4.8,stateOrProvinceName 28 | 2.5.4.7,localityName 29 | 1.2.840.113549.1.1.1,rsaEncryption 30 | 2.5.29.17,subjectAltName 31 | 2.5.29.32,certificatePolicies 32 | 2.16.840.1.113733.1.7.23.6,VeriSign EV policy 33 | 1.3.6.1.5.5.7.2.1,cps 34 | 1.3.6.1.5.5.7.2.2,unotice 35 | 2.5.29.31,cRLDistributionPoints 36 | 2.5.29.37,extKeyUsage 37 | 2.5.29.35,authorityKeyIdentifier 38 | 1.3.6.1.5.5.7.3.1,serverAuth 39 | 1.3.6.1.5.5.7.3.2,clientAuth 40 | 1.3.6.1.5.5.7.1.1,authorityInfoAccess 41 | 1.3.6.1.5.5.7.48.1,ocsp 42 | 1.3.6.1.5.5.7.48.2,caIssuers 43 | 1.2.840.113549.1.1.11,sha256WithRSAEncryption 44 | 1.2.840.113549.1.1.4,md5WithRSAEncryption 45 | 1.3.6.1.4.1.11129.2.4.2,2 46 | 2.23.140.1.1,ev-guidelines 47 | 1.2.840.113549.1.1.5,sha1WithRSAEncryption 48 | 1.2.840.10045.2.1,ecPublicKey 49 | 1.2.840.10045.3.1.7,prime256v1 50 | 1.2.840.10045.4.3.2,ecdsaWithSHA256 51 | 2.5.4.3,CN 52 | 2.5.4.4,SN 53 | 2.5.4.5,SERIALNUMBER 54 | 2.5.4.6,C 55 | 2.5.4.7,L 56 | 2.5.4.8,ST 57 | 2.5.4.8,S 58 | 2.5.4.9,streetAddress 59 | 2.5.4.9,STREET 60 | 2.5.4.10,O 61 | 2.5.4.11,OU 62 | 2.5.4.12,title 63 | 2.5.4.12,T 64 | 2.5.4.12,TITLE 65 | 2.5.4.42,givenName 66 | 2.5.4.42,G 67 | 2.5.4.42,GN 68 | 1.3.132.0.35,secp521r1 69 | 1.3.132.0.34,secp384r1 70 | 1.3.132.0.10,secp256k1 71 | 2.5.29.15,keyUsage 72 | 2.5.29.19,basicConstraints 73 | 2.5.29.14,subjectKeyIdentifier 74 | 1.3.14.3.2.26,SHA1 75 | 1.2.840.113549.1.1.13,sha512WithRSAEncryption 76 | 1.2.840.113549.1.1.12,sha384WithRSAEncryption 77 | 1.2.840.113549.1.1.14,sha224WithRSAEncryption 78 | 1.2.840.113549.1.9.14,extensionRequest 79 | 1.2.840.10045.4.1,ecdsaWithSHA1 80 | 1.2.840.10045.4.3.1,ecdsaWithSHA224 81 | 1.2.840.10045.4.3.3,ecdsaWithSHA384 82 | 1.2.840.10045.4.3.4,ecdsaWithSHA512 83 | 0.9.2342.19200300.100.1.1,UID 84 | 1.2.840.113549.1.9.1,emailAddress 85 | 2.5.4.26,registeredAddress 86 | 2.16.840.1.114412.1.1,digiCertOVCert (Digicert CA policy) 87 | 2.23.140.1.2.2,organization-validated -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: basic_utils 2 | description: Common util classes for Strings, Dates, X509, PKCS, Cryptographie and more. 3 | version: 5.8.2 4 | homepage: https://github.com/Ephenodrom/Dart-Basic-Utils 5 | #publish_to: https://pub.dartlang.org 6 | 7 | environment: 8 | sdk: '>=2.18.0 <4.0.0' 9 | 10 | dependencies: 11 | http: ^1.1.0 12 | logging: ^1.2.0 13 | json_annotation: ^4.8.1 14 | pointycastle: ^4.0.0 15 | archive: ^4.0.2 16 | 17 | dev_dependencies: 18 | build_runner: ^2.4.15 19 | json_serializable: ^6.9.4 20 | test: ^1.25.15 21 | 22 | false_secrets: 23 | - /test/crypto_utils_test.dart 24 | - /test/pkcs12_utils_test.dart 25 | -------------------------------------------------------------------------------- /test/asn1_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io'; 3 | 4 | import 'package:basic_utils/src/Asn1Utils.dart'; 5 | import 'package:test/test.dart'; 6 | 7 | void main() { 8 | var x509Pem = '''-----BEGIN CERTIFICATE----- 9 | MIIFDTCCA/WgAwIBAgIQBxYr+XmB67PWzCkR7C39iDANBgkqhkiG9w0BAQsFADBA 10 | MQswCQYDVQQGEwJVUzERMA8GA1UEChMIT0VNIFRlc3QxHjAcBgNVBAMTFUZ1bGwg 11 | T0VNIFRlc3QgUlNBIFN1YjAeFw0xOTAzMTEwMDAwMDBaFw0yMDAzMTAxMjAwMDBa 12 | MHsxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZCYXllcm4xEzARBgNVBAcTClJlZ2Vu 13 | c2J1cmcxFzAVBgNVBAoTDkludGVyTmV0WCBHbWJIMRQwEgYDVQQLEwtFbnR3aWNr 14 | bHVuZzEXMBUGA1UEAxMOanVua2RyYWdvbnMuZGUwggEiMA0GCSqGSIb3DQEBAQUA 15 | A4IBDwAwggEKAoIBAQDDGv7+2oQyRWvFAt7UxtAQJB6zajegzrlvLLZ4+PhhJt6w 16 | aSDW6IPV7H4uIvgL3cHP68AkATl+2fW0CEPy2i3vO27VDtxMp2oTk/IdPtVbNtZB 17 | sjeFiNVzr7ZaD6z0u41WLEQbR34CmlWbggza3SS0tvPXD02YJpDz/Qm43hz0m+SJ 18 | 0IaesAM7b1tTbmlCxg3rm+CViU9wTsI9eUvOCZIjKS3E3MVcRJZTCCaZMp8JMKct 19 | Ae4B90RunGbpvsYvWo4W4UQMFCVYcZp47FFeWcUnqx03nrSdP3LEEPcePVsRxPeB 20 | ptsZzby9Wf7Sc2UNzTZSGjzxlpItgXdsjL4HiR/VAgMBAAGjggHGMIIBwjAfBgNV 21 | HSMEGDAWgBS8odGV3/ZO7g4f11MzIg9X66vlUjAdBgNVHQ4EFgQUTriCU/8x5yQN 22 | BoQPPYQcUVL7FUIwQQYDVR0RBDowOIIOanVua2RyYWdvbnMuZGWCEnd3dy5qdW5r 23 | ZHJhZ29ucy5kZYISYXBpLmp1bmtkcmFnb25zLmRlMA4GA1UdDwEB/wQEAwIFoDAd 24 | BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwPgYDVR0fBDcwNTAzoDGgL4Yt 25 | aHR0cDovL2NkcC5yYXBpZHNzbC5jb20vRnVsbE9FTVRlc3RSU0FTdWIuY3JsMEwG 26 | A1UdIARFMEMwNwYJYIZIAYb9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3 27 | LmRpZ2ljZXJ0LmNvbS9DUFMwCAYGZ4EMAQICMHUGCCsGAQUFBwEBBGkwZzAmBggr 28 | BgEFBQcwAYYaaHR0cDovL3N0YXR1cy5yYXBpZHNzbC5jb20wPQYIKwYBBQUHMAKG 29 | MWh0dHA6Ly9jYWNlcnRzLnJhcGlkc3NsLmNvbS9GdWxsT0VNVGVzdFJTQVN1Yi5j 30 | cnQwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAwCJAiSMJSYCIrJZdcLmY 31 | zgH/Hd6VUDQzuo/s8Q+UoqpwyPwGnmNpovvzfjtz2+bF0dCQwUWerm61kYF/3IU6 32 | ucrdTW4uS+T11tipJgDUBU8jEHvASe+QNIP7BiNoXCs10SfI8FQajL0HxnHY0vKC 33 | AAQiFStLngxNYduyz4C3ZUjeNjt/8NhCUhd2GZGA6gveHKvck47ZWFbblecH8Odw 34 | nhzR+ztf+lSGoyQW+egNlPog/OLjr//kKx7kjuuvXa5Os8oPLENu6LAjTZJqGvJP 35 | ga7IcCj2gCeuTdS4Ibhx3hiew7cfuGa9XbVd5JJmV8kIoFlzLrZpKB4eVDKqaNWg 36 | /g== 37 | -----END CERTIFICATE-----'''; 38 | 39 | test('Test dump()', () { 40 | Asn1Utils.dump(x509Pem); 41 | }); 42 | 43 | test('Test complexDumpFromASN1Object()', () { 44 | var dump = Asn1Utils.complexDump(x509Pem); 45 | var sb = StringBuffer(); 46 | var length = 0; 47 | for (var l in dump.lines!) { 48 | if (length < l.lineInfoToString().length) { 49 | length = l.lineInfoToString().length; 50 | } 51 | } 52 | 53 | for (var l in dump.lines!) { 54 | if (sb.isNotEmpty) { 55 | sb.write('\n'); 56 | } 57 | sb.write(l.toString(spacing: (length - l.lineInfoToString().length) + 4)); 58 | } 59 | //print(sb.toString()); 60 | var f = File('test_resources/test_dump.txt'); 61 | var txt = f.readAsStringSync(); 62 | expect(sb.toString(), txt); 63 | }); 64 | 65 | test('Test complexDumpFromASN1Object()2', () { 66 | var bytes = [ 67 | 0x04, 68 | 0x16, 69 | 0x04, 70 | 0x14, 71 | 0x08, 72 | 0xB0, 73 | 0xD2, 74 | 0x01, 75 | 0xF3, 76 | 0xBF, 77 | 0x1A, 78 | 0xBC, 79 | 0x60, 80 | 0x3C, 81 | 0xF1, 82 | 0x8C, 83 | 0x37, 84 | 0x0D, 85 | 0x78, 86 | 0xF2, 87 | 0xF6, 88 | 0x27, 89 | 0xAE, 90 | 0xE9 91 | ]; 92 | var dump = Asn1Utils.complexDump(base64.encode(bytes), checkHeader: false); 93 | var sb = StringBuffer(); 94 | var length = 0; 95 | for (var l in dump.lines!) { 96 | if (length < l.lineInfoToString().length) { 97 | length = l.lineInfoToString().length; 98 | } 99 | } 100 | 101 | for (var l in dump.lines!) { 102 | if (sb.isNotEmpty) { 103 | sb.write('\n'); 104 | } 105 | sb.write(l.toString(spacing: (length - l.lineInfoToString().length) + 4)); 106 | } 107 | var expected = 108 | '''o=0 d=0 hl=2 l=22 t=4 OCTET STRING (22 byte) 041408B0D201F3BF1ABC603CF18C370D78F2F627AEE9\no=2 d=1 hl=2 l=20 t=4 |----> OCTET STRING (20 byte) 08B0D201F3BF1ABC603CF18C370D78F2F627AEE9'''; 109 | expect(sb.toString(), expected); 110 | }); 111 | } 112 | -------------------------------------------------------------------------------- /test/boolean_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/BooleanUtils.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | group( 6 | 'Test list and', 7 | () { 8 | test('GIVEN all true THEN true', () { 9 | final result = BooleanUtils.and([true, true]); 10 | expect(result, true); 11 | }); 12 | 13 | test('GIVEN one false THEN false', () { 14 | final result = BooleanUtils.and([true, false]); 15 | expect(result, false); 16 | }); 17 | 18 | test('GIVEN all false THEN false', () { 19 | final result = BooleanUtils.and([false, false]); 20 | expect(result, false); 21 | }); 22 | 23 | test('GIVEN one false THEN false', () { 24 | final result = BooleanUtils.and([true, false, true]); 25 | expect(result, false); 26 | }); 27 | }, 28 | ); 29 | 30 | group( 31 | 'Test list or', 32 | () { 33 | test('GIVEN all true THEN true', () { 34 | final result = BooleanUtils.or([true, true]); 35 | expect(result, true); 36 | }); 37 | 38 | test('GIVEN one false THEN true', () { 39 | final result = BooleanUtils.or([true, false]); 40 | expect(result, true); 41 | }); 42 | 43 | test('GIVEN all false THEN false', () { 44 | final result = BooleanUtils.or([false, false]); 45 | expect(result, false); 46 | }); 47 | 48 | test('GIVEN one false THEN true', () { 49 | final result = BooleanUtils.or([true, false, true]); 50 | expect(result, true); 51 | }); 52 | }, 53 | ); 54 | 55 | group( 56 | 'Test list xor', 57 | () { 58 | test('GIVEN all true THEN false', () { 59 | final result = BooleanUtils.xor([true, true]); 60 | expect(result, false); 61 | }); 62 | 63 | test('GIVEN one false THEN true', () { 64 | final result = BooleanUtils.xor([true, false]); 65 | expect(result, true); 66 | }); 67 | 68 | test('GIVEN all false THEN false', () { 69 | final result = BooleanUtils.xor([false, false]); 70 | expect(result, false); 71 | }); 72 | 73 | test('GIVEN one false THEN true', () { 74 | final result = BooleanUtils.xor([true, false, true]); 75 | expect(result, false); 76 | }); 77 | }, 78 | ); 79 | 80 | group('booleanValues', () { 81 | test('GIVEN nothing THEN boolean values', () { 82 | final result = BooleanUtils.booleanValues(); 83 | expect(result, [false, true]); 84 | }); 85 | }); 86 | 87 | group('compare', () { 88 | test('GIVEN true and true THEN 0', () { 89 | final result = BooleanUtils.compare(true, true); 90 | expect(result, 0); 91 | }); 92 | 93 | test('GIVEN false and false THEN 0', () { 94 | final result = BooleanUtils.compare(false, false); 95 | expect(result, 0); 96 | }); 97 | 98 | test('GIVEN true and false THEN 1', () { 99 | final result = BooleanUtils.compare(true, false); 100 | expect(result, 1); 101 | }); 102 | 103 | test('GIVEN false and true THEN -1', () { 104 | final result = BooleanUtils.compare(false, true); 105 | expect(result, -1); 106 | }); 107 | }); 108 | 109 | group('toBoolean', () { 110 | test('GIVEN 0 THEN boolean false', () { 111 | final result = BooleanUtils.toBoolean(0); 112 | expect(result, false); 113 | }); 114 | 115 | test('GIVEN 1 THEN boolean false', () { 116 | final result = BooleanUtils.toBoolean(1); 117 | expect(result, true); 118 | }); 119 | 120 | test('GIVEN 2 THEN boolean false', () { 121 | final result = BooleanUtils.toBoolean(2); 122 | expect(result, true); 123 | }); 124 | 125 | test('GIVEN -1 THEN boolean false', () { 126 | final result = BooleanUtils.toBoolean(-1); 127 | expect(result, true); 128 | }); 129 | }); 130 | 131 | group('toBooleanObject', () { 132 | test('GIVEN "true" THEN true', () { 133 | final result = BooleanUtils.toBooleanObject('true'); 134 | expect(result, true); 135 | }); 136 | 137 | test('GIVEN "false" THEN false', () { 138 | final result = BooleanUtils.toBooleanObject('false'); 139 | expect(result, false); 140 | }); 141 | 142 | test('GIVEN "yes" THEN true', () { 143 | final result = BooleanUtils.toBooleanObject('yes'); 144 | expect(result, true); 145 | }); 146 | 147 | test('GIVEN "no" THEN false', () { 148 | final result = BooleanUtils.toBooleanObject('no'); 149 | expect(result, false); 150 | }); 151 | 152 | test('GIVEN "t" THEN true', () { 153 | final result = BooleanUtils.toBooleanObject('t'); 154 | expect(result, true); 155 | }); 156 | 157 | test('GIVEN "f" THEN false', () { 158 | final result = BooleanUtils.toBooleanObject('f'); 159 | expect(result, false); 160 | }); 161 | 162 | test('GIVEN "1" THEN true', () { 163 | final result = BooleanUtils.toBooleanObject('1'); 164 | expect(result, true); 165 | }); 166 | 167 | test('GIVEN "0" THEN false', () { 168 | final result = BooleanUtils.toBooleanObject('0'); 169 | expect(result, false); 170 | }); 171 | }); 172 | 173 | group('toBooleanDefaultIfNull', () { 174 | test('GIVEN true and default false THEN true', () { 175 | final result = BooleanUtils.toBooleanDefaultIfNull(true, false); 176 | expect(result, true); 177 | }); 178 | 179 | test('GIVEN true and default true THEN true', () { 180 | final result = BooleanUtils.toBooleanDefaultIfNull(true, true); 181 | expect(result, true); 182 | }); 183 | 184 | test('GIVEN true and default false THEN true', () { 185 | final result = BooleanUtils.toBooleanDefaultIfNull(false, true); 186 | expect(result, false); 187 | }); 188 | 189 | test('GIVEN false and default false THEN true', () { 190 | final result = BooleanUtils.toBooleanDefaultIfNull(false, false); 191 | expect(result, false); 192 | }); 193 | 194 | test('GIVEN null and default true THEN true', () { 195 | final result = BooleanUtils.toBooleanDefaultIfNull(null, true); 196 | expect(result, true); 197 | }); 198 | 199 | test('GIVEN null and default false THEN true', () { 200 | final result = BooleanUtils.toBooleanDefaultIfNull(null, false); 201 | expect(result, false); 202 | }); 203 | }); 204 | 205 | group('toInteger', () { 206 | test('GIVEN true THEN 1', () { 207 | final result = BooleanUtils.toInteger(true); 208 | expect(result, 1); 209 | }); 210 | 211 | test('GIVEN false THEN 0', () { 212 | final result = BooleanUtils.toInteger(false); 213 | expect(result, 0); 214 | }); 215 | }); 216 | 217 | group('toBooleanString', () { 218 | test('GIVEN true THEN "true', () { 219 | final result = BooleanUtils.toBooleanString(true); 220 | expect(result, 'true'); 221 | }); 222 | 223 | test('GIVEN false THEN "false"', () { 224 | final result = BooleanUtils.toBooleanString(false); 225 | expect(result, 'false'); 226 | }); 227 | }); 228 | } 229 | -------------------------------------------------------------------------------- /test/color_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/ColorUtils.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('Test hex to int', () { 6 | expect(ColorUtils.hexToInt('#FFFFFF'), 0xFFFFFFFF); 7 | expect(ColorUtils.hexToInt('FFFFFF'), 0xFFFFFFFF); 8 | expect(ColorUtils.hexToInt('#EF5350'), 0xFFEF5350); 9 | expect(ColorUtils.hexToInt('000001'), 0xFF000001); 10 | expect(ColorUtils.hexToInt('00000002'), 0x00000002); 11 | expect(ColorUtils.hexToInt('3'), 0xFF000003); 12 | expect(ColorUtils.hexToInt('#4'), 0xFF000004); 13 | }); 14 | 15 | test('Test int to hex', () { 16 | expect(ColorUtils.intToHex(0xFFFFFFFF), '#FFFFFF'); 17 | expect(ColorUtils.intToHex(0xFFEF5350), '#EF5350'); 18 | expect(ColorUtils.intToHex(16777215), '#FFFFFF'); 19 | expect(ColorUtils.intToHex(15684432), '#EF5350'); 20 | expect(ColorUtils.intToHex(0xFF0000FA), '#0000FA'); 21 | expect(ColorUtils.intToHex(0x100000FB), '#0000FB'); 22 | expect(ColorUtils.intToHex(0x000000FC), '#0000FC'); 23 | }); 24 | 25 | test('Test shade hex', () { 26 | expect(ColorUtils.shadeColor('#6699CC', 20), '#7ab8f5'); 27 | expect(ColorUtils.shadeColor('#69C', -50), '#334d66'); 28 | expect(ColorUtils.shadeColor('#9c27b0', -32.1), '#6a1a78'); 29 | }); 30 | 31 | test('Test fill up hex', () { 32 | expect(ColorUtils.fillUpHex('#69C'), '#6699CC'); 33 | expect(ColorUtils.fillUpHex('69C'), '#6699CC'); 34 | }); 35 | 36 | test('Test is dark', () { 37 | expect(ColorUtils.isDark('#000000'), true); 38 | expect(ColorUtils.isDark('#FFFFFF'), false); 39 | }); 40 | 41 | test('Test contrast color', () { 42 | expect(ColorUtils.contrastColor('#000000'), '#FFFFFF'); 43 | expect(ColorUtils.contrastColor('#FFFFFF'), '#000000'); 44 | }); 45 | 46 | test('Test basic colors form hex', () { 47 | var bC = ColorUtils.basicColorsFromHex('#4287f5'); 48 | 49 | expect(bC[ColorUtils.BASIC_COLOR_RED], 66); 50 | expect(bC[ColorUtils.BASIC_COLOR_GREEN], 135); 51 | expect(bC[ColorUtils.BASIC_COLOR_BLUE], 245); 52 | }); 53 | 54 | test('Test calculate relative luminance', () { 55 | expect(ColorUtils.calculateRelativeLuminance(255, 0, 0), 0.3); 56 | }); 57 | 58 | test('Test swatch color', () { 59 | var colors = ColorUtils.swatchColor('#f44336'); 60 | expect(colors.elementAt(0), '#ff755f'); 61 | expect(colors.elementAt(1), '#ff6b56'); 62 | expect(colors.elementAt(2), '#ff614e'); 63 | expect(colors.elementAt(3), '#ff5746'); 64 | expect(colors.elementAt(4), '#ff4d3e'); 65 | expect(colors.elementAt(5), '#f44336'); 66 | expect(colors.elementAt(6), '#cf392e'); 67 | expect(colors.elementAt(7), '#ab2f26'); 68 | expect(colors.elementAt(8), '#86251e'); 69 | expect(colors.elementAt(9), '#621b16'); 70 | expect(colors.elementAt(10), '#3d110e'); 71 | }); 72 | 73 | test('Test invert color', () { 74 | expect(ColorUtils.invertColor('#FFFFFF'), '#000000'); 75 | expect(ColorUtils.invertColor('#FF00FF'), '#00ff00'); 76 | expect(ColorUtils.invertColor('000000'), 'ffffff'); 77 | expect(ColorUtils.invertColor('#FFA8FF'), '#005700'); 78 | }); 79 | } 80 | -------------------------------------------------------------------------------- /test/date_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/DateUtils.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('Test stringToDateTime with now', () { 6 | var now = DateTime.now(); 7 | var actual = DateUtils.stringToDateTime('now'); 8 | expect(actual.year, now.year); 9 | expect(actual.month, now.month); 10 | expect(actual.day, now.day); 11 | expect(actual.hour, now.hour); 12 | expect(actual.minute, now.minute); 13 | expect(actual.second, now.second); 14 | }); 15 | 16 | test('Test stringToDateTime with add rem', () { 17 | var time = DateTime.parse('2019-07-11 13:27:00'); 18 | var actual = DateUtils.stringToDateTime('+1 week 2 days 4 hours 2 seconds', 19 | time: time); 20 | expect(actual.year, 2019); 21 | expect(actual.month, 7); 22 | expect(actual.day, 20); 23 | expect(actual.hour, 17); 24 | expect(actual.minute, 27); 25 | expect(actual.second, 2); 26 | time = DateTime.parse('2019-07-30 13:27:00'); 27 | actual = DateUtils.stringToDateTime('+1 week 2 days 4 hours 2 seconds', 28 | time: time); 29 | expect(actual.year, 2019); 30 | expect(actual.month, 8); 31 | expect(actual.day, 8); 32 | expect(actual.hour, 17); 33 | expect(actual.minute, 27); 34 | expect(actual.second, 2); 35 | time = DateTime.parse('2019-07-30 13:27:00'); 36 | actual = DateUtils.stringToDateTime('+1 w 2 d 4 h 2 s', time: time); 37 | expect(actual.year, 2019); 38 | expect(actual.month, 8); 39 | expect(actual.day, 8); 40 | expect(actual.hour, 17); 41 | expect(actual.minute, 27); 42 | expect(actual.second, 2); 43 | time = DateTime.parse('2019-07-11 13:27:00'); 44 | actual = DateUtils.stringToDateTime('+24 hours', time: time); 45 | expect(actual.year, 2019); 46 | expect(actual.month, 7); 47 | expect(actual.day, 12); 48 | expect(actual.hour, 13); 49 | expect(actual.minute, 27); 50 | expect(actual.second, 0); 51 | time = DateTime.parse('2019-07-11 13:27:00'); 52 | actual = DateUtils.stringToDateTime('-24 hours', time: time); 53 | expect(actual.year, 2019); 54 | expect(actual.month, 7); 55 | expect(actual.day, 10); 56 | expect(actual.hour, 13); 57 | expect(actual.minute, 27); 58 | expect(actual.second, 0); 59 | time = DateTime.parse('2019-07-11 13:27:00'); 60 | actual = DateUtils.stringToDateTime( 61 | '+1 week 2 days at 0 hours 0 minutes 0 seconds', 62 | time: time); 63 | expect(actual.year, 2019); 64 | expect(actual.month, 7); 65 | expect(actual.day, 20); 66 | expect(actual.hour, 0); 67 | expect(actual.minute, 0); 68 | expect(actual.second, 0); 69 | 70 | time = DateTime.parse('2019-07-11 13:27:00'); 71 | actual = 72 | DateUtils.stringToDateTime('+1 week 2 days at 00:00:00', time: time); 73 | expect(actual.year, 2019); 74 | expect(actual.month, 7); 75 | expect(actual.day, 20); 76 | expect(actual.hour, 0); 77 | expect(actual.minute, 0); 78 | expect(actual.second, 0); 79 | }); 80 | 81 | test('Test stringToDateTime with yesterday tomorrow', () { 82 | var time = DateTime.parse('2019-07-11 13:27:00'); 83 | var actual = DateUtils.stringToDateTime('tomorrow', time: time); 84 | expect(actual.year, 2019); 85 | expect(actual.month, 7); 86 | expect(actual.day, 12); 87 | expect(actual.hour, 13); 88 | expect(actual.minute, 27); 89 | expect(actual.second, 0); 90 | 91 | time = DateTime.parse('2019-07-11 13:27:00'); 92 | actual = DateUtils.stringToDateTime('tomorrow at 00:00:00', time: time); 93 | expect(actual.year, 2019); 94 | expect(actual.month, 7); 95 | expect(actual.day, 12); 96 | expect(actual.hour, 0); 97 | expect(actual.minute, 0); 98 | expect(actual.second, 0); 99 | }); 100 | 101 | test('Test stringToDateTime with last and next', () { 102 | var time = DateTime.parse('2019-09-02 13:27:00'); 103 | var actual = DateUtils.stringToDateTime('next sunday', time: time); 104 | expect(actual.year, 2019); 105 | expect(actual.month, 9); 106 | expect(actual.day, 8); 107 | expect(actual.hour, 13); 108 | expect(actual.minute, 27); 109 | expect(actual.second, 0); 110 | actual = DateUtils.stringToDateTime('last sunday', time: time); 111 | expect(actual.year, 2019); 112 | expect(actual.month, 9); 113 | expect(actual.day, 1); 114 | expect(actual.hour, 13); 115 | expect(actual.minute, 27); 116 | expect(actual.second, 0); 117 | actual = DateUtils.stringToDateTime('last friday at 10:27:00', time: time); 118 | expect(actual.year, 2019); 119 | expect(actual.month, 8); 120 | expect(actual.day, 30); 121 | expect(actual.hour, 10); 122 | expect(actual.minute, 27); 123 | expect(actual.second, 0); 124 | actual = DateUtils.stringToDateTime('next friday at 2 pm', time: time); 125 | expect(actual.year, 2019); 126 | expect(actual.month, 9); 127 | expect(actual.day, 6); 128 | expect(actual.hour, 14); 129 | expect(actual.minute, 0); 130 | expect(actual.second, 0); 131 | 132 | actual = DateUtils.stringToDateTime('10:27:00 last friday', time: time); 133 | expect(actual.year, 2019); 134 | expect(actual.month, 8); 135 | expect(actual.day, 30); 136 | expect(actual.hour, 10); 137 | expect(actual.minute, 27); 138 | expect(actual.second, 0); 139 | 140 | actual = DateUtils.stringToDateTime('2 pm next friday', time: time); 141 | expect(actual.year, 2019); 142 | expect(actual.month, 9); 143 | expect(actual.day, 6); 144 | expect(actual.hour, 14); 145 | expect(actual.minute, 0); 146 | expect(actual.second, 0); 147 | 148 | actual = DateUtils.stringToDateTime('2 pm next week', time: time); 149 | expect(actual.year, 2019); 150 | expect(actual.month, 9); 151 | expect(actual.day, 9); 152 | expect(actual.hour, 14); 153 | expect(actual.minute, 0); 154 | expect(actual.second, 0); 155 | }); 156 | 157 | test('Test stringToDateTime with yesterday tomorrow', () { 158 | var time = DateTime.parse('2019-07-11 13:27:00'); 159 | var actual = DateUtils.stringToDateTime('tomorrow', time: time); 160 | expect(actual.year, 2019); 161 | expect(actual.month, 7); 162 | expect(actual.day, 12); 163 | expect(actual.hour, 13); 164 | expect(actual.minute, 27); 165 | expect(actual.second, 0); 166 | 167 | time = DateTime.parse('2019-07-11 13:27:00'); 168 | actual = DateUtils.stringToDateTime('tomorrow at 00:00:00', time: time); 169 | expect(actual.year, 2019); 170 | expect(actual.month, 7); 171 | expect(actual.day, 12); 172 | expect(actual.hour, 0); 173 | expect(actual.minute, 0); 174 | expect(actual.second, 0); 175 | }); 176 | 177 | test('Test stringToDateTime with ago', () { 178 | var time = DateTime.parse('2019-09-02 13:27:00'); 179 | var actual = DateUtils.stringToDateTime('2 weeks ago', time: time); 180 | expect(actual.year, 2019); 181 | expect(actual.month, 8); 182 | expect(actual.day, 19); 183 | expect(actual.hour, 13); 184 | expect(actual.minute, 27); 185 | expect(actual.second, 0); 186 | actual = DateUtils.stringToDateTime('3 months ago at 00:00:00', time: time); 187 | expect(actual.year, 2019); 188 | expect(actual.month, 6); 189 | expect(actual.day, 2); 190 | expect(actual.hour, 0); 191 | expect(actual.minute, 0); 192 | expect(actual.second, 0); 193 | actual = DateUtils.stringToDateTime('3 days ago', time: time); 194 | expect(actual.year, 2019); 195 | expect(actual.month, 8); 196 | expect(actual.day, 30); 197 | expect(actual.hour, 13); 198 | expect(actual.minute, 27); 199 | expect(actual.second, 0); 200 | }); 201 | 202 | test('Test stringToDateTime with date', () { 203 | var actual = DateUtils.stringToDateTime('10 September 2019'); 204 | expect(actual.year, 2019); 205 | expect(actual.month, 9); 206 | expect(actual.day, 10); 207 | expect(actual.hour, 0); 208 | expect(actual.minute, 0); 209 | expect(actual.second, 0); 210 | actual = DateUtils.stringToDateTime('10 September 2019 at 01:01:01'); 211 | expect(actual.year, 2019); 212 | expect(actual.month, 9); 213 | expect(actual.day, 10); 214 | expect(actual.hour, 1); 215 | expect(actual.minute, 1); 216 | expect(actual.second, 1); 217 | actual = DateUtils.stringToDateTime('29 Feb 2020 at 13:45:59'); 218 | expect(actual.year, 2020); 219 | expect(actual.month, 2); 220 | expect(actual.day, 29); 221 | expect(actual.hour, 13); 222 | expect(actual.minute, 45); 223 | expect(actual.second, 59); 224 | }); 225 | 226 | test('Test getCalendarWeek', () { 227 | var date = DateTime.parse('2020-01-02 13:27:00'); 228 | expect(DateUtils.getCalendarWeek(date), 1); 229 | 230 | date = DateTime.parse('2019-12-31 13:27:00'); 231 | expect(DateUtils.getCalendarWeek(date), 53); 232 | }); 233 | } 234 | -------------------------------------------------------------------------------- /test/dns_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/basic_utils.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('Test lookupRecord', () async { 6 | var records = await DnsUtils.lookupRecord('google.de', RRecordType.A); 7 | expect(records?.elementAt(0).data.isEmpty, false); 8 | expect(records?.elementAt(0).rType, 1); 9 | }); 10 | 11 | test('Test lookupRecord Cloudflare', () async { 12 | var records = await DnsUtils.lookupRecord('google.de', RRecordType.A, 13 | provider: DnsApiProvider.CLOUDFLARE); 14 | expect(records?.elementAt(0).data.isEmpty, false); 15 | expect(records?.elementAt(0).rType, 1); 16 | }); 17 | 18 | test('Test reverseDns', () async { 19 | var records = await DnsUtils.reverseDns('172.217.22.14'); 20 | expect(records!.elementAt(0).data.isEmpty, false); 21 | expect(records.elementAt(0).rType, 12); 22 | }); 23 | 24 | test('Test getReverseAddr', () async { 25 | var reversed = DnsUtils.getReverseAddr('172.217.22.14'); 26 | expect(reversed, '14.22.217.172.in-addr.arpa'); 27 | 28 | reversed = DnsUtils.getReverseAddr('2a00:1450:4001:81a::200e'); 29 | expect(reversed, 'e.0.0.2.a.1.8.1.0.0.4.0.5.4.1.0.0.a.2.ip6.arpa'); 30 | 31 | reversed = DnsUtils.getReverseAddr('12345'); 32 | expect(reversed, null); 33 | }); 34 | 35 | test('Test toBind', () async { 36 | var r = 37 | RRecord(name: 'foo.bar.de.', rType: 16, ttl: 300, data: 'helloWorld'); 38 | var bind = DnsUtils.toBind(r); 39 | expect(bind, 'foo.bar.de.\t\t300\tIN\tTXT\t\"helloWorld\"'); 40 | }); 41 | } 42 | -------------------------------------------------------------------------------- /test/domain_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/basic_utils.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('Test splitDomainName', () { 6 | expect(DomainUtils.splitDomainName('example.com'), ['example', 'com']); 7 | expect(DomainUtils.splitDomainName('subdomain.example.com'), 8 | ['subdomain', 'example', 'com']); 9 | }); 10 | 11 | test('Test parseDomain', () { 12 | var domain = DomainUtils.parseDomain('example.com'); 13 | expect(domain.toString(), 'example.com'); 14 | expect(domain?.sld, 'example'); 15 | expect(domain?.tld, 'com'); 16 | expect(domain?.subTld, null); 17 | 18 | domain = DomainUtils.parseDomain('treehouse.com'); 19 | expect(domain.toString(), 'treehouse.com'); 20 | expect(domain!.sld, 'treehouse'); 21 | expect(domain.tld, 'com'); 22 | expect(domain.subTld, null); 23 | 24 | domain = DomainUtils.parseDomain('example.co.uk')!; 25 | expect(domain.sld, 'example'); 26 | expect(domain.tld, 'uk'); 27 | expect(domain.subTld, 'co'); 28 | 29 | domain = DomainUtils.parseDomain('subdomain.example.co.uk')!; 30 | expect(domain.sld, 'example'); 31 | expect(domain.tld, 'uk'); 32 | expect(domain.subTld, 'co'); 33 | 34 | domain = DomainUtils.parseDomain('example'); 35 | expect(domain, null); 36 | 37 | domain = DomainUtils.parseDomain('star.bd'); 38 | expect(domain?.sld, 'star'); 39 | expect(domain?.subTld, null); 40 | expect(domain?.tld, 'bd'); 41 | 42 | domain = DomainUtils.parseDomain('whatever.fantasy.example.com'); 43 | expect(domain.toString(), 'example.com'); 44 | expect(domain?.sld, 'example'); 45 | expect(domain?.subTld, null); 46 | expect(domain?.tld, 'com'); 47 | 48 | domain = DomainUtils.parseDomain('公司.cn'); 49 | expect(domain.toString(), '公司.cn'); 50 | expect(domain?.sld, '公司'); 51 | expect(domain?.subTld, null); 52 | expect(domain?.tld, 'cn'); 53 | 54 | domain = DomainUtils.parseDomain('test.我爱你'); 55 | expect(domain.toString(), 'test.我爱你'); 56 | expect(domain?.sld, 'test'); 57 | expect(domain?.subTld, null); 58 | expect(domain?.tld, '我爱你'); 59 | 60 | domain = DomainUtils.parseDomain('xn--6qq986b3xl.com'); 61 | expect(domain.toString(), 'xn--6qq986b3xl.com'); 62 | expect(domain?.sld, 'xn--6qq986b3xl'); 63 | expect(domain?.subTld, null); 64 | expect(domain?.tld, 'com'); 65 | 66 | domain = DomainUtils.parseDomain('test.xn--6qq986b3xl'); 67 | expect(domain.toString(), 'test.xn--6qq986b3xl'); 68 | expect(domain?.sld, 'test'); 69 | expect(domain?.subTld, null); 70 | expect(domain?.tld, 'xn--6qq986b3xl'); 71 | 72 | domain = DomainUtils.parseDomain('test.москва'); 73 | expect(domain.toString(), 'test.москва'); 74 | expect(domain?.sld, 'test'); 75 | expect(domain?.subTld, null); 76 | expect(domain?.tld, 'москва'); 77 | 78 | domain = DomainUtils.parseDomain('www.example.com'); 79 | expect(domain.toString(), 'example.com'); 80 | expect(domain?.sld, 'example'); 81 | expect(domain?.subTld, null); 82 | expect(domain?.tld, 'com'); 83 | }); 84 | 85 | test('Test isCCTLD', () { 86 | expect(DomainUtils.isCCTLD('com'), false); 87 | expect(DomainUtils.isCCTLD('de'), true); 88 | expect(DomainUtils.isCCTLD('xn--mgba3a4f16a'), true); 89 | }); 90 | 91 | test('Test isGTLD', () { 92 | expect(DomainUtils.isGTLD('com'), true); 93 | expect(DomainUtils.isGTLD('de'), false); 94 | expect(DomainUtils.isGTLD('xn--mgba3a4f16a'), false); 95 | }); 96 | 97 | test('Test isNGTLD', () { 98 | expect(DomainUtils.isNGTLD('rocks'), true); 99 | expect(DomainUtils.isNGTLD('de'), false); 100 | expect(DomainUtils.isNGTLD('xn--mgba3a4f16a'), false); 101 | }); 102 | 103 | test('Test isTld', () { 104 | expect(DomainUtils.isTld('rocks'), true); 105 | expect(DomainUtils.isTld('de'), true); 106 | expect(DomainUtils.isTld('xn--mgba3a4f16a'), true); 107 | expect(DomainUtils.isTld('fooBar'), false); 108 | }); 109 | 110 | test('Test isSubDomain', () { 111 | expect(DomainUtils.isSubDomain('www.test.de'), true); 112 | expect(DomainUtils.isSubDomain('sub1.test.de'), true); 113 | expect(DomainUtils.isSubDomain('sub2.sub1.test.de'), true); 114 | expect(DomainUtils.isSubDomain('www.test.de.com'), true); 115 | expect(DomainUtils.isSubDomain('test.de.com'), false); 116 | expect(DomainUtils.isSubDomain('test.de'), false); 117 | }); 118 | 119 | test('Test isSubTld', () { 120 | expect(DomainUtils.isSubTld('ac', 'com'), true); 121 | expect(DomainUtils.isSubTld('ae', 'net'), true); 122 | expect(DomainUtils.isSubTld('aero', 'agents'), true); 123 | expect(DomainUtils.isSubTld('com', 'foobar'), false); 124 | expect(DomainUtils.isSubTld('de', 'subtld'), false); 125 | }); 126 | 127 | test('Test isDomainName', () { 128 | expect(DomainUtils.isDomainName('example.co.uk'), true); 129 | expect(DomainUtils.isDomainName('example'), false); 130 | expect(DomainUtils.isDomainName('example.com'), true); 131 | expect(DomainUtils.isDomainName('example.qwertzu'), false); 132 | expect(DomainUtils.isDomainName('www.example.de'), false); 133 | expect(DomainUtils.isDomainName('*.example.de'), false); 134 | expect(DomainUtils.isDomainName('www.'), false); 135 | expect(DomainUtils.isDomainName('..'), false); 136 | }); 137 | 138 | test('Test isSubDomainOf', () { 139 | expect(DomainUtils.isSubDomainOf('sub1.domain.com', 'domain.com'), true); 140 | expect(DomainUtils.isSubDomainOf('sub2.sub1.domain.com', 'sub1.domain.com'), 141 | true); 142 | expect(DomainUtils.isSubDomainOf('sub1.domain2.com', 'domain.com'), false); 143 | }); 144 | 145 | test('Test getDomainFromUrl', () { 146 | expect(DomainUtils.getDomainFromUrl('http://example.com').toString(), 147 | 'example.com'); 148 | expect( 149 | DomainUtils.getDomainFromUrl('https://example.com/foobar').toString(), 150 | 'example.com'); 151 | expect( 152 | DomainUtils.getDomainFromUrl('https://example.com/foobar?key=foo') 153 | .toString(), 154 | 'example.com'); 155 | expect(DomainUtils.getDomainFromUrl('www.example.com').toString(), 156 | 'example.com'); 157 | expect(DomainUtils.getDomainFromUrl('http://www.example.com').toString(), 158 | 'example.com'); 159 | expect(DomainUtils.getDomainFromUrl('https://www.example.com').toString(), 160 | 'example.com'); 161 | expect(DomainUtils.getDomainFromUrl('http://sub1.example.com').toString(), 162 | 'example.com'); 163 | expect(DomainUtils.getDomainFromUrl('https://sub1.example.com').toString(), 164 | 'example.com'); 165 | }); 166 | 167 | test('Test splitSubdomainInDomains', () { 168 | var splitted = 169 | DomainUtils.splitSubdomainInDomains('sub3.sub2.sub1.domain.com'); 170 | expect(splitted.length, 4); 171 | expect(splitted.elementAt(0), 'sub3.sub2.sub1.domain.com'); 172 | expect(splitted.elementAt(1), 'sub2.sub1.domain.com'); 173 | expect(splitted.elementAt(2), 'sub1.domain.com'); 174 | expect(splitted.elementAt(3), 'domain.com'); 175 | 176 | splitted = 177 | DomainUtils.splitSubdomainInDomains('sub3.sub2.sub1.domain.de.com'); 178 | 179 | expect(splitted.length, 4); 180 | expect(splitted.elementAt(0), 'sub3.sub2.sub1.domain.de.com'); 181 | expect(splitted.elementAt(1), 'sub2.sub1.domain.de.com'); 182 | expect(splitted.elementAt(2), 'sub1.domain.de.com'); 183 | expect(splitted.elementAt(3), 'domain.de.com'); 184 | }); 185 | 186 | test('Test toIDN', () { 187 | expect(DomainUtils.toIDN('24jönköping.se'), 'xn--24jnkping-27ac.se'); 188 | expect(DomainUtils.toIDN('포르쉐.asia'), 'xn--2w2b25nmlp.asia'); 189 | expect(DomainUtils.toIDN('едоша33.рф'), 'xn--33-6kcpe9cwd.xn--p1ai'); 190 | expect(DomainUtils.toIDN('321österreich.de'), 'xn--321sterreich-6ib.de'); 191 | expect(DomainUtils.toIDN('321österreich'), 'xn--321sterreich-6ib'); 192 | }); 193 | 194 | test('Test fromIDN', () { 195 | expect(DomainUtils.fromIDN('xn--24jnkping-27ac.se'), '24jönköping.se'); 196 | expect(DomainUtils.fromIDN('xn--2w2b25nmlp.asia'), '포르쉐.asia'); 197 | expect(DomainUtils.fromIDN('xn--33-6kcpe9cwd.xn--p1ai'), 'едоша33.рф'); 198 | expect(DomainUtils.fromIDN('xn--321sterreich-6ib.de'), '321österreich.de'); 199 | expect(DomainUtils.fromIDN('xn--321sterreich-6ib'), '321österreich'); 200 | }); 201 | } 202 | -------------------------------------------------------------------------------- /test/email_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/basic_utils.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('Test isEmail', () { 6 | expect(EmailUtils.isEmail('plainaddress'), false); 7 | expect(EmailUtils.isEmail('#@%^%#\$@#\$@#.com'), false); 8 | expect(EmailUtils.isEmail('@domain.com'), false); 9 | expect(EmailUtils.isEmail('Joe Smith < email@domain.com >'), false); 10 | expect(EmailUtils.isEmail('email.domain.com'), false); 11 | expect(EmailUtils.isEmail('email @domain@domain.com'), false); 12 | expect(EmailUtils.isEmail('.email @domain.com'), false); 13 | expect(EmailUtils.isEmail('email.@domain.com'), false); 14 | expect(EmailUtils.isEmail('email..email@domain.com'), true); 15 | expect(EmailUtils.isEmail('あいうえお@domain.com'), false); 16 | expect(EmailUtils.isEmail('email@domain.com(Joe Smith)'), false); 17 | expect(EmailUtils.isEmail('email @domain'), false); 18 | expect(EmailUtils.isEmail('email@-domain.com'), true); 19 | expect(EmailUtils.isEmail('test@foobar.rocks'), true); 20 | expect(EmailUtils.isEmail('email @domain.web'), false); 21 | expect(EmailUtils.isEmail('email@111.222.333.44444'), false); 22 | expect(EmailUtils.isEmail('email @domain..com'), false); 23 | }); 24 | 25 | test('Test parseEmailAddress', () { 26 | expect(EmailUtils.parseEmailAddress('plainaddress'), null); 27 | var email = EmailUtils.parseEmailAddress('test@test.de')!; 28 | expect(email.local, 'test'); 29 | expect(email.domain.toString(), 'test.de'); 30 | 31 | email = EmailUtils.parseEmailAddress('jon.doe@test.de')!; 32 | expect(email.local, 'jon.doe'); 33 | expect(email.domain.toString(), 'test.de'); 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /test/enum_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/EnumUtils.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | enum Day { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday } 5 | 6 | void main() { 7 | test('Test getEnum', () { 8 | final result = EnumUtils.getEnum('Wednesday', Day.values, Day.Monday); 9 | expect(result, Day.Wednesday); 10 | }); 11 | 12 | test('Test getEnum', () { 13 | final result = EnumUtils.getEnum( 14 | 'wednesday', 15 | Day.values, 16 | Day.Monday, 17 | ignoreCase: true, 18 | ); 19 | expect(result, Day.Wednesday); 20 | }); 21 | 22 | test('Test getEnum', () { 23 | final result = EnumUtils.getEnum( 24 | 'random_string', 25 | Day.values, 26 | Day.Monday, 27 | ); 28 | expect(result, Day.Monday); 29 | }); 30 | 31 | test('Test isValidEnum', () { 32 | final result = EnumUtils.isValidEnum( 33 | 'Monday', 34 | Day.values, 35 | ); 36 | expect(result, true); 37 | }); 38 | 39 | test('Test isValidEnum', () { 40 | final result = EnumUtils.isValidEnum( 41 | 'monday', 42 | Day.values, 43 | ignoreCase: true, 44 | ); 45 | expect(result, true); 46 | }); 47 | 48 | test('Test isValidEnum', () { 49 | final result = EnumUtils.isValidEnum( 50 | 'random_string', 51 | Day.values, 52 | ); 53 | expect(result, false); 54 | }); 55 | 56 | test('Test getEnumMap', () { 57 | final result = EnumUtils.getEnumMap(Day.values); 58 | final expected = { 59 | 'Monday': Day.Monday, 60 | 'Tuesday': Day.Tuesday, 61 | 'Wednesday': Day.Wednesday, 62 | 'Thursday': Day.Thursday, 63 | 'Friday': Day.Friday, 64 | 'Saturday': Day.Saturday, 65 | 'Sunday': Day.Sunday 66 | }; 67 | expect(result, expected); 68 | }); 69 | } 70 | -------------------------------------------------------------------------------- /test/hex_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:basic_utils/basic_utils.dart'; 4 | import 'package:test/test.dart'; 5 | 6 | void main() { 7 | test('Test encode', () { 8 | expect( 9 | HexUtils.encode(Uint8List.fromList( 10 | [0x02, 0x02, 0x08, 0x00], 11 | )), 12 | '02020800'); 13 | }); 14 | 15 | test('Test decode', () { 16 | expect( 17 | HexUtils.decode('02020800'), 18 | Uint8List.fromList( 19 | [0x02, 0x02, 0x08, 0x00], 20 | ), 21 | ); 22 | expect( 23 | HexUtils.decode('2020800'), 24 | Uint8List.fromList( 25 | [0x02, 0x02, 0x08, 0x00], 26 | ), 27 | ); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /test/http_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/basic_utils.dart'; 2 | import 'package:http/http.dart'; 3 | import 'package:test/test.dart'; 4 | import 'package:http/testing.dart'; 5 | import 'dart:convert'; 6 | 7 | void main() { 8 | test('Test addQueryParameterToUrl', () { 9 | var queryParameters = {}; 10 | queryParameters.putIfAbsent('hello', () => 'world'); 11 | queryParameters.putIfAbsent('list[]', () => ['item1', 'item2']); 12 | expect( 13 | HttpUtils.addQueryParameterToUrl( 14 | 'super-api.com/dosomething', queryParameters), 15 | 'super-api.com/dosomething?hello=world&list%5B%5D=item1&list%5B%5D=item2'); 16 | }); 17 | 18 | test('Test addQueryParameterToUrl for url with existing query parameters', 19 | () { 20 | var queryParameters = {}; 21 | queryParameters.putIfAbsent('hello', () => 'world'); 22 | queryParameters.putIfAbsent('list[]', () => ['item1', 'item2']); 23 | expect( 24 | HttpUtils.addQueryParameterToUrl( 25 | 'super-api.com/dosomething?foo=bar', queryParameters), 26 | 'super-api.com/dosomething?hello=world&list%5B%5D=item1&list%5B%5D=item2&foo=bar'); 27 | }); 28 | 29 | test('Test getQueryParameterFromUrl', () { 30 | expect( 31 | HttpUtils.getQueryParameterFromUrl('super-api.com/dosomething'), null); 32 | var queryParameters = HttpUtils.getQueryParameterFromUrl( 33 | 'super-api.com/dosomething?hello=world')!; 34 | expect(queryParameters.length, 1); 35 | expect(queryParameters.containsKey('hello'), true); 36 | expect(queryParameters['hello'], 'world'); 37 | 38 | queryParameters = HttpUtils.getQueryParameterFromUrl( 39 | 'super-api.com/dosomething?hello=world&list[]=value1&list[]=value2')!; 40 | expect(queryParameters.length, 2); 41 | expect(queryParameters.containsKey('hello'), true); 42 | expect(queryParameters.containsKey('list[]'), true); 43 | expect(queryParameters['list[]'] is List, true); 44 | expect(queryParameters['list[]'].length, 2); 45 | }); 46 | 47 | test('Test get', () async { 48 | HttpUtils.client = MockClient((request) async { 49 | final mapJson = {'id': 123}; 50 | return Response(json.encode(mapJson), 200); 51 | }); 52 | final item = await HttpUtils.getForJson('api.com/item'); 53 | expect(item['id'], 123); 54 | }); 55 | 56 | test('Test delete', () async { 57 | HttpUtils.client = MockClient((request) async { 58 | return Response(json.encode({}), 200); 59 | }); 60 | var response = await HttpUtils.deleteForJson('api.com/item/1'); 61 | expect(response.isEmpty, true); 62 | }); 63 | 64 | test('Test get with 404', () async { 65 | HttpUtils.client = MockClient((request) async { 66 | return Response(json.encode({}), 404); 67 | }); 68 | expect(HttpUtils.getForJson('api.com/item'), 69 | throwsA(TypeMatcher())); 70 | }); 71 | 72 | test('Test get with 500', () async { 73 | HttpUtils.client = MockClient((request) async { 74 | return Response(json.encode({}), 500); 75 | }); 76 | expect(HttpUtils.getForJson('api.com/item'), 77 | throwsA(TypeMatcher())); 78 | }); 79 | 80 | test('Test post', () async { 81 | HttpUtils.client = MockClient((request) async { 82 | final mapJson = {'id': 123}; 83 | return Response(json.encode(mapJson), 200); 84 | }); 85 | final item = 86 | await HttpUtils.postForJson('api.com/item', body: '{"id": 123}'); 87 | expect(item['id'], 123); 88 | }); 89 | 90 | test('Test put', () async { 91 | HttpUtils.client = MockClient((request) async { 92 | final mapJson = {'id': 124}; 93 | return Response(json.encode(mapJson), 200); 94 | }); 95 | final item = 96 | await HttpUtils.putForJson('api.com/item', body: '{"id": 124}'); 97 | expect(item['id'], 124); 98 | }); 99 | 100 | test('Test response headers', () async { 101 | var headers = { 102 | 'authorization': 103 | 'ShelfAuthJwtSession eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXV...' 104 | }; 105 | HttpUtils.client = MockClient((request) async { 106 | final mapJson = {'id': 123}; 107 | return Response(json.encode(mapJson), 200, headers: headers); 108 | }); 109 | var response = await HttpUtils.getForFullResponse('api.com/item'); 110 | expect(response.headers['authorization'], 111 | 'ShelfAuthJwtSession eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXV...'); 112 | }); 113 | } 114 | -------------------------------------------------------------------------------- /test/iterable_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/src/IterableUtils.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('Test randomItem', () { 6 | var list = [1, 2, 3]; 7 | expect(IterableUtils.randomItem(list), isIn(list)); 8 | }); 9 | 10 | test('Empty iterable throws exception', () { 11 | expect(() => IterableUtils.randomItem([]), throwsRangeError); 12 | }); 13 | 14 | test('Test isNullOrEmpty', () { 15 | var list = [1, 2, 3, 4]; 16 | var emptyList = []; 17 | var nullList; 18 | expect(IterableUtils.isNullOrEmpty(list), false); 19 | expect(IterableUtils.isNullOrEmpty(emptyList), true); 20 | expect(IterableUtils.isNullOrEmpty(nullList), true); 21 | }); 22 | 23 | test('Test isNotNullOrEmpty', () { 24 | var list = [1, 2, 3, 4]; 25 | var emptyList = []; 26 | var nullList; 27 | expect(IterableUtils.isNotNullOrEmpty(list), true); 28 | expect(IterableUtils.isNotNullOrEmpty(emptyList), false); 29 | expect(IterableUtils.isNotNullOrEmpty(nullList), false); 30 | }); 31 | 32 | test('Test chunk', () { 33 | var list = [1, 2, 3, 4, 5, 6, 7, 8]; 34 | var subLists = IterableUtils.chunk(list, 2); 35 | expect(subLists.length, 4); 36 | expect(subLists.elementAt(0).length, 2); 37 | }); 38 | 39 | test('Test zip', () { 40 | final expected = [1, 2, 3, 4, 5, 6]; 41 | final list1 = [1, 3, 5]; 42 | final list2 = [2, 4, 6]; 43 | final subZip = IterableUtils.zip(list1, list2); 44 | expect(subZip, expected); 45 | }); 46 | 47 | test('Test zip with letters', () { 48 | final expected = [1, 'a', 3, 'b', 5, 'c']; 49 | final list1 = [1, 3, 5]; 50 | final list2 = ['a', 'b', 'c']; 51 | final subZip = IterableUtils.zip(list1, list2); 52 | expect(subZip, expected); 53 | }); 54 | 55 | test('Test emptyIfNull', () { 56 | final expected = [1, 3, 5]; 57 | final list1 = [1, 3, 5]; 58 | final result = IterableUtils.emptyIfNull(list1); 59 | expect(result, expected); 60 | }); 61 | 62 | test('Test emptyIfNull when null', () { 63 | final expected = []; 64 | final Iterable? list1 = null; 65 | final result = IterableUtils.emptyIfNull(list1); 66 | expect(result, expected); 67 | }); 68 | 69 | test('Test union', () { 70 | final expected = [1, 2, 3, 'a', 'b', 'c']; 71 | final list1 = [1, 2, 3]; 72 | final list2 = ['a', 'b', 'c']; 73 | final result = IterableUtils.union(list1, list2); 74 | expect(result, expected); 75 | }); 76 | 77 | test('Test union with same values', () { 78 | final expected = [1, 2, 3]; 79 | final list1 = [1, 2, 3]; 80 | final list2 = [1, 2, 3]; 81 | final result = IterableUtils.union(list1, list2); 82 | expect(result, expected); 83 | }); 84 | 85 | test('Test containsAll', () { 86 | final expected = true; 87 | final list1 = [1, 2, 3]; 88 | final list2 = [1, 2, 3]; 89 | final result = IterableUtils.containsAll(list1, list2); 90 | expect(result, expected); 91 | }); 92 | 93 | test('Test containsAll with empty list2', () { 94 | final expected = true; 95 | final list1 = [1, 2, 3]; 96 | final list2 = []; 97 | final result = IterableUtils.containsAll(list1, list2); 98 | expect(result, expected); 99 | }); 100 | 101 | test('Test containsAll with a values', () { 102 | final expected = true; 103 | final list1 = [1, 2, 3]; 104 | final list2 = [1]; 105 | final result = IterableUtils.containsAll(list1, list2); 106 | expect(result, expected); 107 | }); 108 | 109 | test('Test containsAll with few values', () { 110 | final expected = false; 111 | final list1 = [1, 2, 3]; 112 | final list2 = [4, 5, 6]; 113 | final result = IterableUtils.containsAll(list1, list2); 114 | expect(result, expected); 115 | }); 116 | 117 | test('Test containsAny', () { 118 | final expected = true; 119 | final list1 = [1, 2, 3]; 120 | final list2 = [3]; 121 | final result = IterableUtils.containsAny(list1, list2); 122 | expect(result, expected); 123 | }); 124 | 125 | test('Test containsAny without', () { 126 | final expected = false; 127 | final list1 = [1, 2, 3]; 128 | final list2 = [5]; 129 | final result = IterableUtils.containsAny(list1, list2); 130 | expect(result, expected); 131 | }); 132 | 133 | test('Test containsAny empty', () { 134 | final expected = false; 135 | final list1 = [1, 2, 3]; 136 | final list2 = []; 137 | final result = IterableUtils.containsAny(list1, list2); 138 | expect(result, expected); 139 | }); 140 | 141 | test('Test size with null', () { 142 | final expected = 0; 143 | final list1 = null; 144 | final result = IterableUtils.size(list1); 145 | expect(result, expected); 146 | }); 147 | 148 | test('Test size with iterable', () { 149 | final expected = 3; 150 | final list1 = [1, 2, 3]; 151 | final result = IterableUtils.size(list1); 152 | expect(result, expected); 153 | }); 154 | 155 | test('Test size with map', () { 156 | final expected = 1; 157 | final map1 = {}; 158 | map1['key'] = 1; 159 | final result = IterableUtils.size(map1); 160 | expect(result, expected); 161 | }); 162 | 163 | test('Test size with dynamic', () { 164 | final expected = 1; 165 | final dynamic object = {}; 166 | object['key'] = 1; 167 | final result = IterableUtils.size(object); 168 | expect(result, expected); 169 | }); 170 | 171 | test('Test size with dynamic without length', () { 172 | final object = _Foo(); 173 | expect(() => IterableUtils.size(object), 174 | throwsA(TypeMatcher())); 175 | }); 176 | 177 | test('Test size with dynamic without length', () { 178 | final expected = 1; 179 | final object = _FooLength(1); 180 | final result = IterableUtils.size(object); 181 | expect(result, expected); 182 | }); 183 | 184 | /// 185 | /// 186 | /// 187 | test('Test sizeIsEmpty with null', () { 188 | final expected = true; 189 | final list1 = null; 190 | final result = IterableUtils.sizeIsEmpty(list1); 191 | expect(result, expected); 192 | }); 193 | 194 | test('Test sizeIsEmpty with iterable', () { 195 | final expected = false; 196 | final list1 = [1, 2, 3]; 197 | final result = IterableUtils.sizeIsEmpty(list1); 198 | expect(result, expected); 199 | }); 200 | 201 | test('Test sizeIsEmpty with map', () { 202 | final expected = false; 203 | final map1 = {}; 204 | map1['key'] = 1; 205 | final result = IterableUtils.sizeIsEmpty(map1); 206 | expect(result, expected); 207 | }); 208 | 209 | test('Test sizeIsEmpty with dynamic', () { 210 | final expected = false; 211 | final dynamic object = {}; 212 | object['key'] = 1; 213 | final result = IterableUtils.sizeIsEmpty(object); 214 | expect(result, expected); 215 | }); 216 | 217 | test('Test sizeIsEmpty with dynamic without length', () { 218 | final object = _Foo(); 219 | expect(() => IterableUtils.sizeIsEmpty(object), 220 | throwsA(TypeMatcher())); 221 | }); 222 | 223 | test('Test sizeIsEmpty with dynamic without length', () { 224 | final expected = false; 225 | final object = _FooLength(1); 226 | final result = IterableUtils.sizeIsEmpty(object); 227 | expect(result, expected); 228 | }); 229 | 230 | test('Test intersection', () { 231 | final expected = [1, 3]; 232 | final list1 = [1, 2, 3]; 233 | final list2 = [1, 'a', 3]; 234 | final result = IterableUtils.intersection(list1, list2); 235 | expect(result, expected); 236 | }); 237 | 238 | test('Test subtract', () { 239 | final expected = [2]; 240 | final list1 = [1, 2, 3]; 241 | final list2 = [1, 'a', 3]; 242 | final result = IterableUtils.subtract(list1, list2); 243 | expect(result, expected); 244 | }); 245 | 246 | test('Test permutate', () { 247 | var list1 = [1, 2, 3, 4]; 248 | var result = IterableUtils.permutate(list1); 249 | expect(result.length, 24); 250 | 251 | var list2 = ['A', 'B', 'C']; 252 | result = IterableUtils.permutate(list2); 253 | expect(result.length, 6); 254 | }); 255 | 256 | test('Test swap', () { 257 | final list1 = [1, 2, 3, 4]; 258 | IterableUtils.swap(list1, 0, 1); 259 | expect(list1.length, 4); 260 | expect(list1.elementAt(0), 2); 261 | expect(list1.elementAt(1), 1); 262 | expect(list1.elementAt(2), 3); 263 | expect(list1.elementAt(3), 4); 264 | }); 265 | } 266 | 267 | class _Foo {} 268 | 269 | class _FooLength { 270 | final int length; 271 | 272 | const _FooLength(this.length); 273 | } 274 | -------------------------------------------------------------------------------- /test/sort_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/basic_utils.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('Test quickSort', () { 6 | var sorted = SortUtils.quickSort([5, 4, 1, 2, 3]); 7 | 8 | expect(sorted[0], 1); 9 | expect(sorted[1], 2); 10 | expect(sorted[2], 3); 11 | expect(sorted[3], 4); 12 | expect(sorted[4], 5); 13 | 14 | sorted = SortUtils.quickSort(['a', 'b', 'e', 'c', 'd']); 15 | 16 | expect(sorted[0], 'a'); 17 | expect(sorted[1], 'b'); 18 | expect(sorted[2], 'c'); 19 | expect(sorted[3], 'd'); 20 | expect(sorted[4], 'e'); 21 | }); 22 | 23 | test('Test bubbleSort', () { 24 | var sorted = SortUtils.bubbleSort([5, 4, 1, 2, 3]); 25 | 26 | expect(sorted[0], 1); 27 | expect(sorted[1], 2); 28 | expect(sorted[2], 3); 29 | expect(sorted[3], 4); 30 | expect(sorted[4], 5); 31 | 32 | sorted = SortUtils.bubbleSort(['a', 'b', 'e', 'c', 'd']); 33 | 34 | expect(sorted[0], 'a'); 35 | expect(sorted[1], 'b'); 36 | expect(sorted[2], 'c'); 37 | expect(sorted[3], 'd'); 38 | expect(sorted[4], 'e'); 39 | }); 40 | 41 | test('Test heapSort', () { 42 | var sorted = SortUtils.heapSort([5, 4, 1, 2, 3]); 43 | 44 | expect(sorted[0], 1); 45 | expect(sorted[1], 2); 46 | expect(sorted[2], 3); 47 | expect(sorted[3], 4); 48 | expect(sorted[4], 5); 49 | 50 | sorted = SortUtils.heapSort(['a', 'b', 'e', 'c', 'd']); 51 | 52 | expect(sorted[0], 'a'); 53 | expect(sorted[1], 'b'); 54 | expect(sorted[2], 'c'); 55 | expect(sorted[3], 'd'); 56 | expect(sorted[4], 'e'); 57 | }); 58 | } 59 | -------------------------------------------------------------------------------- /test/string_utils_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:basic_utils/basic_utils.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('Test defaultString', () { 6 | expect(StringUtils.defaultString('Hello', defaultStr: 'World'), 'Hello'); 7 | expect(StringUtils.defaultString(null, defaultStr: 'World'), 'World'); 8 | }); 9 | 10 | test('Test camelCaseToUpperUnderscore', () { 11 | expect(StringUtils.camelCaseToUpperUnderscore('camelCase'), 'CAMEL_CASE'); 12 | }); 13 | 14 | test('Test camelCaseToLowerUnderscore', () { 15 | expect(StringUtils.camelCaseToLowerUnderscore('camelCase'), 'camel_case'); 16 | expect(StringUtils.camelCaseToLowerUnderscore('a_b'), 'a_b'); 17 | }); 18 | 19 | test('Test isLowerCase', () { 20 | expect(StringUtils.isLowerCase('c'), true); 21 | expect(StringUtils.isLowerCase('C'), false); 22 | }); 23 | 24 | test('Test isUpperCase', () { 25 | expect(StringUtils.isUpperCase('C'), true); 26 | expect(StringUtils.isUpperCase('c'), false); 27 | }); 28 | 29 | test('Test isNullOrEmpty', () { 30 | expect(StringUtils.isNullOrEmpty(''), true); 31 | expect(StringUtils.isNullOrEmpty(null), true); 32 | expect(StringUtils.isNullOrEmpty('Hello'), false); 33 | }); 34 | 35 | test('Test isNotNullOrEmpty', () { 36 | expect(StringUtils.isNotNullOrEmpty(''), false); 37 | expect(StringUtils.isNotNullOrEmpty(null), false); 38 | expect(StringUtils.isNotNullOrEmpty('Hello'), true); 39 | }); 40 | 41 | test('Test isAscii', () { 42 | expect(StringUtils.isAscii('I am pure ascii'), true); 43 | expect(StringUtils.isAscii('I am nö ascii'), false); 44 | }); 45 | 46 | test('Test capitalize', () { 47 | expect(StringUtils.capitalize('HELLO'), 'Hello'); 48 | expect(StringUtils.capitalize('World'), 'World'); 49 | expect(StringUtils.capitalize('helloworld'), 'Helloworld'); 50 | 51 | expect(StringUtils.capitalize('the quick lazy fox', allWords: true), 52 | 'The Quick Lazy Fox'); 53 | 54 | expect(StringUtils.capitalize('THE QUICK LAZY FOX', allWords: true), 55 | 'The Quick Lazy Fox'); 56 | 57 | expect( 58 | StringUtils.capitalize('hello, my name is Jon. my last name is doe!', 59 | allWords: true), 60 | 'Hello, My Name Is Jon. My Last Name Is Doe!'); 61 | }); 62 | 63 | test('Test reverse', () { 64 | expect(StringUtils.reverse('hello'), 'olleh'); 65 | }); 66 | 67 | test('Test count char', () { 68 | expect(StringUtils.countChars('Hello my name is Jon Doe.', 'e'), 3); 69 | expect(StringUtils.countChars('Hello my name is Jon Doe.', 'E'), 0); 70 | expect( 71 | StringUtils.countChars('Hello my namE is Jon Doe.', 'e', 72 | caseSensitive: false), 73 | 3); 74 | expect( 75 | StringUtils.countChars('Hello my namE is Jon Doe.', 'E', 76 | caseSensitive: false), 77 | 3); 78 | }); 79 | 80 | test('Test equalsIgnoreCase', () { 81 | expect(StringUtils.equalsIgnoreCase('hello', 'HELLO'), true); 82 | }); 83 | 84 | test('Test isDigit', () { 85 | expect(StringUtils.isDigit('1'), true); 86 | expect(StringUtils.isDigit('12345'), true); 87 | expect(StringUtils.isDigit('1a356'), false); 88 | expect(StringUtils.isDigit('q3dm16'), false); 89 | expect(StringUtils.isDigit(''), false); 90 | }); 91 | 92 | test('Test inList', () { 93 | var list = ['a', 'b', 'c', 'A']; 94 | expect(StringUtils.inList('c', list), true); 95 | expect(StringUtils.inList('d', list), false); 96 | expect(StringUtils.inList('A', list, ignoreCase: true), true); 97 | expect(StringUtils.inList('D', list, ignoreCase: true), false); 98 | }); 99 | 100 | test('Test isPalindrome', () { 101 | expect(StringUtils.isPalindrome('aha'), true); 102 | expect(StringUtils.isPalindrome('123454321'), true); 103 | expect(StringUtils.isPalindrome('1a356'), false); 104 | expect(StringUtils.isPalindrome('hello'), false); 105 | }); 106 | 107 | test('Test hidePartial', () { 108 | expect(StringUtils.hidePartial('1234567890'), '*****67890'); 109 | expect( 110 | StringUtils.hidePartial('1234567890', begin: 2, end: 6), '12****7890'); 111 | expect(StringUtils.hidePartial('1234567890', begin: 1), '1****67890'); 112 | expect( 113 | StringUtils.hidePartial('1234567890', begin: 2, end: 14), '12********'); 114 | }); 115 | 116 | test('Test addCharAtPosition', () { 117 | expect(StringUtils.addCharAtPosition('1234567890', '-', 3), '123-4567890'); 118 | expect(StringUtils.addCharAtPosition('1234567890', '-', 3, repeat: true), 119 | '123-456-789-0'); 120 | expect(StringUtils.addCharAtPosition('1234567890', '-', 12), '1234567890'); 121 | expect( 122 | StringUtils.addCharAtPosition( 123 | '1F6254CEDA7E9E9AEBF8B687BDFB5CC03AD1B3E7', ' ', 2, 124 | repeat: true), 125 | '1F 62 54 CE DA 7E 9E 9A EB F8 B6 87 BD FB 5C C0 3A D1 B3 E7'); 126 | }); 127 | 128 | test('Test chunk', () { 129 | var chunked = StringUtils.chunk('aaaabbbbccccdddd', 4); 130 | expect(chunked.length, 4); 131 | expect(chunked.elementAt(0), 'aaaa'); 132 | expect(chunked.elementAt(1), 'bbbb'); 133 | expect(chunked.elementAt(2), 'cccc'); 134 | expect(chunked.elementAt(3), 'dddd'); 135 | }); 136 | 137 | test('Test Pick Only', () { 138 | expect(StringUtils.pickOnly('123456789'), '123456789'); 139 | expect(StringUtils.pickOnly('123456789', from: 3, to: 8), '345678'); 140 | expect(StringUtils.pickOnly('123456789', to: 5), '12345'); 141 | expect(StringUtils.pickOnly('123456789', from: 7), '789'); 142 | }); 143 | 144 | test('Test Remove Character at Position', () { 145 | expect(StringUtils.removeCharAtPosition('flutterr', 8), 'flutter'); 146 | expect(StringUtils.removeCharAtPosition('iintel', 1), 'intel'); 147 | expect(StringUtils.removeCharAtPosition('strinng', 5), 'string'); 148 | }); 149 | 150 | test('Test Remove Pattern', () { 151 | expect(StringUtils.removeExp('Hello This World', 'This'), 'Hello World'); 152 | expect(StringUtils.removeExp('All all all', 'all'), 'All'); 153 | expect( 154 | StringUtils.removeExp('All all all', 'all', repeat: false), 'All all'); 155 | expect( 156 | StringUtils.removeExp('All all all', 'all', caseSensitive: false), ''); 157 | }); 158 | 159 | test('Test Truncate', () { 160 | expect(StringUtils.truncate('This is a Dart Utility Library', 26), 161 | 'This is a Dart Utility Lib...'); 162 | expect( 163 | StringUtils.truncate('This is a Dart Utility Library', 26, 164 | symbol: '***'), 165 | 'This is a Dart Utility Lib***'); 166 | }); 167 | 168 | test('Test Generate Random String', () { 169 | var testing1 = StringUtils.generateRandomString(10); 170 | expect(testing1, testing1.length == 10 ? testing1 : false); 171 | 172 | var testing2 = 173 | StringUtils.generateRandomString(5, from: '1234565fhshsbAJSJSSU'); 174 | expect(testing2, testing2.length == 5 ? testing2 : false); 175 | 176 | var isAlphabetInly = 177 | StringUtils.generateRandomString(20, numeric: false, special: false); 178 | expect(RegExp(r'^[a-zA-Z]+$').hasMatch(isAlphabetInly), true); 179 | 180 | var isNumericOnly = 181 | StringUtils.generateRandomString(20, alphabet: false, special: false); 182 | expect(RegExp(r'^[0-9]+$').hasMatch(isNumericOnly), true); 183 | 184 | var isAlphaNumericOInly = StringUtils.generateRandomString( 185 | 20, 186 | special: false, 187 | ); 188 | expect(RegExp(r'^[a-zA-Z0-9]+$').hasMatch(isAlphaNumericOInly), true); 189 | 190 | var isSpecialOnly = 191 | StringUtils.generateRandomString(20, numeric: false, alphabet: false); 192 | expect(!RegExp(r'^[a-zA-Z0-9]+$').hasMatch(isSpecialOnly), true); 193 | }); 194 | 195 | test('Test generateRandomString()', () { 196 | var l = StringUtils.generateRandomStrings(10, 10); 197 | expect(l.length, 10); 198 | }); 199 | 200 | test('Test toPascalCase', () { 201 | expect(StringUtils.toPascalCase('hello world'), 'HelloWorld'); 202 | expect(StringUtils.toPascalCase('Hello World'), 'HelloWorld'); 203 | expect(StringUtils.toPascalCase('Hello World'), 'HelloWorld'); 204 | expect(StringUtils.toPascalCase('helloworld'), 'Helloworld'); 205 | expect(StringUtils.toPascalCase('hello_world'), 'HelloWorld'); 206 | expect(StringUtils.toPascalCase('Hello_World'), 'HelloWorld'); 207 | expect(StringUtils.toPascalCase('HELLO_WORLD'), 'HelloWorld'); 208 | }); 209 | 210 | test('Test isIP', () { 211 | expect(StringUtils.isIP('127.0.0.1'), true); 212 | expect(StringUtils.isIP('0.0.0.0'), true); 213 | expect(StringUtils.isIP('255.255.255.255'), true); 214 | expect(StringUtils.isIP('1.2.3.4'), true); 215 | expect(StringUtils.isIP('::1'), true); 216 | expect(StringUtils.isIP('2001:db8:0000:1:1:1:1:1'), true); 217 | expect(StringUtils.isIP('abc'), false); 218 | expect(StringUtils.isIP('256.0.0.0'), false); 219 | expect(StringUtils.isIP('0.0.0.256'), false); 220 | expect(StringUtils.isIP('26.0.0.256'), false); 221 | }); 222 | } 223 | -------------------------------------------------------------------------------- /test_resources/RapidSSLTLSRSACAG1.crl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ephenodrom/Dart-Basic-Utils/187d58396c36377b914c98831d4d73e37e37980d/test_resources/RapidSSLTLSRSACAG1.crl -------------------------------------------------------------------------------- /test_resources/github_com_cert_chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFajCCBPGgAwIBAgIQDNCovsYyz+ZF7KCpsIT7HDAKBggqhkjOPQQDAzBWMQsw 3 | CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMTAwLgYDVQQDEydEaWdp 4 | Q2VydCBUTFMgSHlicmlkIEVDQyBTSEEzODQgMjAyMCBDQTEwHhcNMjMwMjE0MDAw 5 | MDAwWhcNMjQwMzE0MjM1OTU5WjBmMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2Fs 6 | aWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEChMMR2l0SHVi 7 | LCBJbmMuMRMwEQYDVQQDEwpnaXRodWIuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D 8 | AQcDQgAEo6QDRgPfRlFWy8k5qyLN52xZlnqToPu5QByQMog2xgl2nFD1Vfd2Xmgg 9 | nO4i7YMMFTAQQUReMqyQodWq8uVDs6OCA48wggOLMB8GA1UdIwQYMBaAFAq8CCkX 10 | jKU5bXoOzjPHLrPt+8N6MB0GA1UdDgQWBBTHByd4hfKdM8lMXlZ9XNaOcmfr3jAl 11 | BgNVHREEHjAcggpnaXRodWIuY29tgg53d3cuZ2l0aHViLmNvbTAOBgNVHQ8BAf8E 12 | BAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMIGbBgNVHR8EgZMw 13 | gZAwRqBEoEKGQGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRMU0h5 14 | YnJpZEVDQ1NIQTM4NDIwMjBDQTEtMS5jcmwwRqBEoEKGQGh0dHA6Ly9jcmw0LmRp 15 | Z2ljZXJ0LmNvbS9EaWdpQ2VydFRMU0h5YnJpZEVDQ1NIQTM4NDIwMjBDQTEtMS5j 16 | cmwwPgYDVR0gBDcwNTAzBgZngQwBAgIwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3 17 | dy5kaWdpY2VydC5jb20vQ1BTMIGFBggrBgEFBQcBAQR5MHcwJAYIKwYBBQUHMAGG 18 | GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBPBggrBgEFBQcwAoZDaHR0cDovL2Nh 19 | Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VExTSHlicmlkRUNDU0hBMzg0MjAy 20 | MENBMS0xLmNydDAJBgNVHRMEAjAAMIIBgAYKKwYBBAHWeQIEAgSCAXAEggFsAWoA 21 | dwDuzdBk1dsazsVct520zROiModGfLzs3sNRSFlGcR+1mwAAAYZQ3Rv6AAAEAwBI 22 | MEYCIQDkFq7T4iy6gp+pefJLxpRS7U3gh8xQymmxtI8FdzqU6wIhALWfw/nLD63Q 23 | YPIwG3EFchINvWUfB6mcU0t2lRIEpr8uAHYASLDja9qmRzQP5WoC+p0w6xxSActW 24 | 3SyB2bu/qznYhHMAAAGGUN0cKwAABAMARzBFAiAePGAyfiBR9dbhr31N9ZfESC5G 25 | V2uGBTcyTyUENrH3twIhAPwJfsB8A4MmNr2nW+sdE1n2YiCObW+3DTHr2/UR7lvU 26 | AHcAO1N3dT4tuYBOizBbBv5AO2fYT8P0x70ADS1yb+H61BcAAAGGUN0cOgAABAMA 27 | SDBGAiEAzOBr9OZ0+6OSZyFTiywN64PysN0FLeLRyL5jmEsYrDYCIQDu0jtgWiMI 28 | KU6CM0dKcqUWLkaFE23c2iWAhYAHqrFRRzAKBggqhkjOPQQDAwNnADBkAjAE3A3U 29 | 3jSZCpwfqOHBdlxi9ASgKTU+wg0qw3FqtfQ31OwLYFdxh0MlNk/HwkjRSWgCMFbQ 30 | vMkXEPvNvv4t30K6xtpG26qmZ+6OiISBIIXMljWnsiYR1gyZnTzIg3AQSw4Vmw== 31 | -----END CERTIFICATE----- 32 | -----BEGIN CERTIFICATE----- 33 | MIIEFzCCAv+gAwIBAgIQB/LzXIeod6967+lHmTUlvTANBgkqhkiG9w0BAQwFADBh 34 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 35 | d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD 36 | QTAeFw0yMTA0MTQwMDAwMDBaFw0zMTA0MTMyMzU5NTlaMFYxCzAJBgNVBAYTAlVT 37 | MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxMDAuBgNVBAMTJ0RpZ2lDZXJ0IFRMUyBI 38 | eWJyaWQgRUNDIFNIQTM4NCAyMDIwIENBMTB2MBAGByqGSM49AgEGBSuBBAAiA2IA 39 | BMEbxppbmNmkKaDp1AS12+umsmxVwP/tmMZJLwYnUcu/cMEFesOxnYeJuq20ExfJ 40 | qLSDyLiQ0cx0NTY8g3KwtdD3ImnI8YDEe0CPz2iHJlw5ifFNkU3aiYvkA8ND5b8v 41 | c6OCAYIwggF+MBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFAq8CCkXjKU5 42 | bXoOzjPHLrPt+8N6MB8GA1UdIwQYMBaAFAPeUDVW0Uy7ZvCj4hsbw5eyPdFVMA4G 43 | A1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwdgYI 44 | KwYBBQUHAQEEajBoMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5j 45 | b20wQAYIKwYBBQUHMAKGNGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdp 46 | Q2VydEdsb2JhbFJvb3RDQS5jcnQwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2Ny 47 | bDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDA9BgNVHSAE 48 | NjA0MAsGCWCGSAGG/WwCATAHBgVngQwBATAIBgZngQwBAgEwCAYGZ4EMAQICMAgG 49 | BmeBDAECAzANBgkqhkiG9w0BAQwFAAOCAQEAR1mBf9QbH7Bx9phdGLqYR5iwfnYr 50 | 6v8ai6wms0KNMeZK6BnQ79oU59cUkqGS8qcuLa/7Hfb7U7CKP/zYFgrpsC62pQsY 51 | kDUmotr2qLcy/JUjS8ZFucTP5Hzu5sn4kL1y45nDHQsFfGqXbbKrAjbYwrwsAZI/ 52 | BKOLdRHHuSm8EdCGupK8JvllyDfNJvaGEwwEqonleLHBTnm8dqMLUeTF0J5q/hos 53 | Vq4GNiejcxwIfZMy0MJEGdqN9A57HSgDKwmKdsp33Id6rHtSJlWncg+d0ohP/rEh 54 | xRqhqjn1VtvChMQ1H3Dau0bwhr9kAMQ+959GG50jBbl9s08PqUU643QwmA== 55 | -----END CERTIFICATE----- 56 | -----BEGIN CERTIFICATE----- 57 | MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh 58 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 59 | d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD 60 | QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT 61 | MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j 62 | b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG 63 | 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB 64 | CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 65 | nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt 66 | 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P 67 | T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 68 | gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO 69 | BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR 70 | TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw 71 | DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr 72 | hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg 73 | 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF 74 | PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls 75 | YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk 76 | CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= 77 | -----END CERTIFICATE----- -------------------------------------------------------------------------------- /test_resources/rapid_ssl_broken_chain.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIEszCCA5ugAwIBAgIQCyWUIs7ZgSoVoE6ZUooO+jANBgkqhkiG9w0BAQsFADBh 3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 4 | d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH 5 | MjAeFw0xNzExMDIxMjI0MzNaFw0yNzExMDIxMjI0MzNaMGAxCzAJBgNVBAYTAlVT 6 | MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j 7 | b20xHzAdBgNVBAMTFlJhcGlkU1NMIFRMUyBSU0EgQ0EgRzEwggEiMA0GCSqGSIb3 8 | DQEBAQUAA4IBDwAwggEKAoIBAQC/uVklRBI1FuJdUEkFCuDL/I3aJQiaZ6aibRHj 9 | ap/ap9zy1aYNrphe7YcaNwMoPsZvXDR+hNJOo9gbgOYVTPq8gXc84I75YKOHiVA4 10 | NrJJQZ6p2sJQyqx60HkEIjzIN+1LQLfXTlpuznToOa1hyTD0yyitFyOYwURM+/CI 11 | 8FNFMpBhw22hpeAQkOOLmsqT5QZJYeik7qlvn8gfD+XdDnk3kkuuu0eG+vuyrSGr 12 | 5uX5LRhFWlv1zFQDch/EKmd163m6z/ycx/qLa9zyvILc7cQpb+k7TLra9WE17YPS 13 | n9ANjG+ECo9PDW3N9lwhKQCNvw1gGoguyCQu7HE7BnW8eSSFAgMBAAGjggFmMIIB 14 | YjAdBgNVHQ4EFgQUDNtsgkkPSmcKuBTuesRIUojrVjgwHwYDVR0jBBgwFoAUTiJU 15 | IBiV5uNu5g/6+rkS7QYXjzkwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsG 16 | AQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMDQGCCsGAQUFBwEB 17 | BCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEIGA1Ud 18 | HwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEds 19 | b2JhbFJvb3RHMi5jcmwwYwYDVR0gBFwwWjA3BglghkgBhv1sAQEwKjAoBggrBgEF 20 | BQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzALBglghkgBhv1sAQIw 21 | CAYGZ4EMAQIBMAgGBmeBDAECAjANBgkqhkiG9w0BAQsFAAOCAQEAGUSlOb4K3Wtm 22 | SlbmE50UYBHXM0SKXPqHMzk6XQUpCheF/4qU8aOhajsyRQFDV1ih/uPIg7YHRtFi 23 | CTq4G+zb43X1T77nJgSOI9pq/TqCwtukZ7u9VLL3JAq3Wdy2moKLvvC8tVmRzkAe 24 | 0xQCkRKIjbBG80MSyDX/R4uYgj6ZiNT/Zg6GI6RofgqgpDdssLc0XIRQEotxIZcK 25 | zP3pGJ9FCbMHmMLLyuBd+uCWvVcF2ogYAawufChS/PT61D9rqzPRS5I2uqa3tmIT 26 | 44JhJgWhBnFMb7AGQkvNq9KNS9dd3GWc17H/dXa1enoxzWjE0hBdFjxPhUb0W3wi 27 | 8o34/m8Fxw== 28 | -----END CERTIFICATE----- 29 | -----BEGIN CERTIFICATE----- 30 | MIIDOzCCAiOgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMSAwHgYDVQQDExdEaWdp 31 | Q2VydCBHbG9iYWwgUm9vdCBHMjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lD 32 | ZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTAeFw0yMjA4MjIwNzA0 33 | MzVaFw0yMzA4MjIwNzA0MzVaMGExIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBS 34 | b290IEcyMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD 35 | VQQLExB3d3cuZGlnaWNlcnQuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 36 | CgKCAQEAooFbhcIBXLXv/J1Ujfq0BhpezNIjaqvcPwYhtA7/c3niWDQpOHcQe9f4 37 | 12hs9vOX2h4IyP26JSJD1SvBGoz5ZbzsfvuZkebZVtu9F2x68JrUhuZlsknxm7Yu 38 | lNXWaE/TwXF+NphaKsEjv8mhXsStIcqQJ5zG7Z694+U+s5ff4Zv1NfRT6oi48Qxx 39 | TGQSPFlmRIA8Xt+sFBI+mRs/5ZJY1E9TdeurG109flsv4Pfn5CraHSI0X9/XLtzc 40 | XbZUXShO4zzvJR4jxGzCJ1wVMCBQukQ6+PxYuKMiDk4x9o6+14YqMtOvJNUUAUVL 41 | ucftLg9yTEFC0btgCZYgShvmBI6qCwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQAg 42 | zaa45EVimuuxQsEw1/2EVYdXV44iPZycZfFVQ7Pb7Zt2PJ4ZSPOGyEf+0Nl9R2me 43 | bI3IJdgcLEtjKpm/NzO2yykwZv76veuc4XTODgiXV4Y9bkBA6LGWBysvB7y0ORmz 44 | fnWA9k69n2EcCUtWhjYMuQTgAvCsQLLexWE8PS0JAosQaqee94DvPbw3Hvh1PSdH 45 | DQTQHPPNiVCMfoIDxNPvNF5lk6nvtgS1fhcuj0tNqLmVHlFpGeZbFgqM7l7ElSmD 46 | dmX/b3BKkjC99ZICSqaUelMvwlI076fgjHeAfN2V1cW7M9T/ha7HuZlQtU/4Bid6 47 | f2Ad8oGbTUcQlJkwgYwD 48 | -----END CERTIFICATE----- --------------------------------------------------------------------------------