From d37fd189b2439bd1872c50eae74c6c47ebfe7440 Mon Sep 17 00:00:00 2001 From: LAOBILAXI Date: Mon, 11 May 2026 16:42:42 +0800 Subject: [PATCH 1/4] first --- plugins/srktoolbox/.cspell.json | 17 + plugins/srktoolbox/.dockerignore | 6 + plugins/srktoolbox/.editorconfig | 18 + plugins/srktoolbox/.gitattributes | 1 + plugins/srktoolbox/.gitignore | 15 + plugins/srktoolbox/.npmignore | 7 + plugins/srktoolbox/.nvmrc | 1 + plugins/srktoolbox/CHANGELOG.md | 1013 + plugins/srktoolbox/CHANGELOG_SRKTOOLBOX.md | 33 + plugins/srktoolbox/CODE_OF_CONDUCT.md | 46 + plugins/srktoolbox/Dockerfile | 2 + plugins/srktoolbox/Gruntfile.js | 440 + plugins/srktoolbox/LICENSE | 202 + plugins/srktoolbox/README.md | 363 + plugins/srktoolbox/SECURITY.md | 26 + plugins/srktoolbox/babel.config.js | 27 + plugins/srktoolbox/eslint.config.mjs | 129 + plugins/srktoolbox/index.html | 11 + plugins/srktoolbox/nightwatch.json | 32 + plugins/srktoolbox/package-lock.json | 24662 ++++++++++++++++ plugins/srktoolbox/package.json | 215 + plugins/srktoolbox/plugin.json | 31 + plugins/srktoolbox/pnpm-lock.yaml | 12457 ++++++++ plugins/srktoolbox/postcss.config.js | 9 + plugins/srktoolbox/public/logo.png | Bin 0 -> 4272 bytes plugins/srktoolbox/public/plugin.json | 81 + .../srktoolbox/public/preload/package.json | 3 + plugins/srktoolbox/public/preload/services.js | 27 + plugins/srktoolbox/src/App.vue | 25 + plugins/srktoolbox/src/Hello/index.vue | 25 + plugins/srktoolbox/src/Read/index.vue | 105 + plugins/srktoolbox/src/Write/index.vue | 40 + plugins/srktoolbox/src/core/Chef.mjs | 183 + plugins/srktoolbox/src/core/ChefWorker.js | 294 + plugins/srktoolbox/src/core/Dish.mjs | 569 + plugins/srktoolbox/src/core/Ingredient.mjs | 132 + plugins/srktoolbox/src/core/Operation.mjs | 322 + plugins/srktoolbox/src/core/Recipe.mjs | 358 + plugins/srktoolbox/src/core/Utils.mjs | 1606 + .../src/core/config/Categories.json | 593 + .../core/config/scripts/generateConfig.mjs | 147 + .../core/config/scripts/generateOpsIndex.mjs | 60 + .../core/config/scripts/newMinorVersion.mjs | 203 + .../src/core/config/scripts/newOperation.mjs | 230 + .../src/core/dishTypes/DishBigNumber.mjs | 38 + .../src/core/dishTypes/DishByteArray.mjs | 31 + .../src/core/dishTypes/DishFile.mjs | 42 + .../src/core/dishTypes/DishHTML.mjs | 26 + .../src/core/dishTypes/DishJSON.mjs | 32 + .../src/core/dishTypes/DishListFile.mjs | 80 + .../src/core/dishTypes/DishNumber.mjs | 33 + .../src/core/dishTypes/DishString.mjs | 33 + .../src/core/dishTypes/DishType.mjs | 38 + .../srktoolbox/src/core/dishTypes/index.mjs | 26 + .../srktoolbox/src/core/errors/DishError.mjs | 26 + .../core/errors/ExcludedOperationError.mjs | 25 + .../src/core/errors/OperationError.mjs | 26 + plugins/srktoolbox/src/core/errors/index.mjs | 9 + .../srktoolbox/src/core/lib/Arithmetic.mjs | 139 + plugins/srktoolbox/src/core/lib/BCD.mjs | 50 + plugins/srktoolbox/src/core/lib/Bacon.mjs | 68 + plugins/srktoolbox/src/core/lib/Base32.mjs | 23 + plugins/srktoolbox/src/core/lib/Base45.mjs | 27 + plugins/srktoolbox/src/core/lib/Base58.mjs | 24 + plugins/srktoolbox/src/core/lib/Base64.mjs | 185 + plugins/srktoolbox/src/core/lib/Base85.mjs | 48 + plugins/srktoolbox/src/core/lib/Base92.mjs | 46 + plugins/srktoolbox/src/core/lib/Bech32.mjs | 371 + plugins/srktoolbox/src/core/lib/Binary.mjs | 80 + plugins/srktoolbox/src/core/lib/BitwiseOp.mjs | 132 + plugins/srktoolbox/src/core/lib/Blowfish.mjs | 436 + plugins/srktoolbox/src/core/lib/Bombe.mjs | 756 + plugins/srktoolbox/src/core/lib/Braille.mjs | 15 + .../src/core/lib/CanvasComponents.mjs | 204 + plugins/srktoolbox/src/core/lib/Charts.mjs | 181 + plugins/srktoolbox/src/core/lib/ChrEnc.mjs | 310 + .../srktoolbox/src/core/lib/CipherSaber2.mjs | 34 + plugins/srktoolbox/src/core/lib/Ciphers.mjs | 90 + plugins/srktoolbox/src/core/lib/Code.mjs | 29 + plugins/srktoolbox/src/core/lib/Colossus.mjs | 417 + .../src/core/lib/ConvertCoordinates.mjs | 670 + plugins/srktoolbox/src/core/lib/Crypt.mjs | 11 + plugins/srktoolbox/src/core/lib/DateTime.mjs | 313 + plugins/srktoolbox/src/core/lib/Decimal.mjs | 37 + plugins/srktoolbox/src/core/lib/Delim.mjs | 85 + plugins/srktoolbox/src/core/lib/Enigma.mjs | 369 + plugins/srktoolbox/src/core/lib/Extract.mjs | 70 + .../src/core/lib/FileSignatures.mjs | 4213 +++ plugins/srktoolbox/src/core/lib/FileType.mjs | 267 + .../srktoolbox/src/core/lib/FlowControl.mjs | 20 + .../srktoolbox/src/core/lib/FuzzyMatch.mjs | 253 + plugins/srktoolbox/src/core/lib/Hash.mjs | 28 + plugins/srktoolbox/src/core/lib/Hex.mjs | 135 + plugins/srktoolbox/src/core/lib/IP.mjs | 679 + plugins/srktoolbox/src/core/lib/JA4.mjs | 292 + plugins/srktoolbox/src/core/lib/JWT.mjs | 24 + plugins/srktoolbox/src/core/lib/LS47.mjs | 244 + plugins/srktoolbox/src/core/lib/LZNT1.mjs | 90 + plugins/srktoolbox/src/core/lib/LZString.mjs | 23 + .../srktoolbox/src/core/lib/LoremIpsum.mjs | 230 + plugins/srktoolbox/src/core/lib/Lorenz.mjs | 156 + plugins/srktoolbox/src/core/lib/Magic.mjs | 1126 + plugins/srktoolbox/src/core/lib/Modhex.mjs | 167 + plugins/srktoolbox/src/core/lib/PGP.mjs | 118 + plugins/srktoolbox/src/core/lib/Protobuf.mjs | 562 + plugins/srktoolbox/src/core/lib/Protocol.mjs | 52 + plugins/srktoolbox/src/core/lib/PublicKey.mjs | 62 + plugins/srktoolbox/src/core/lib/QRCode.mjs | 113 + plugins/srktoolbox/src/core/lib/RSA.mjs | 17 + plugins/srktoolbox/src/core/lib/Rotate.mjs | 103 + plugins/srktoolbox/src/core/lib/SIGABA.mjs | 502 + plugins/srktoolbox/src/core/lib/SM2.mjs | 258 + plugins/srktoolbox/src/core/lib/SM4.mjs | 331 + plugins/srktoolbox/src/core/lib/Salsa20.mjs | 144 + plugins/srktoolbox/src/core/lib/Sort.mjs | 117 + plugins/srktoolbox/src/core/lib/Stream.mjs | 338 + plugins/srktoolbox/src/core/lib/TLS.mjs | 879 + plugins/srktoolbox/src/core/lib/TLVParser.mjs | 78 + plugins/srktoolbox/src/core/lib/Typex.mjs | 227 + plugins/srktoolbox/src/core/lib/XXTEA.mjs | 174 + plugins/srktoolbox/src/core/lib/Zlib.mjs | 21 + .../src/core/operations/A1Z26CipherDecode.mjs | 97 + .../src/core/operations/A1Z26CipherEncode.mjs | 63 + .../srktoolbox/src/core/operations/ADD.mjs | 79 + .../src/core/operations/AESDecrypt.mjs | 161 + .../src/core/operations/AESEncrypt.mjs | 162 + .../src/core/operations/AESKeyUnwrap.mjs | 130 + .../src/core/operations/AESKeyWrap.mjs | 117 + .../src/core/operations/AMFDecode.mjs | 54 + .../src/core/operations/AMFEncode.mjs | 54 + .../srktoolbox/src/core/operations/AND.mjs | 79 + .../src/core/operations/AddLineNumbers.mjs | 55 + .../src/core/operations/AddTextToImage.mjs | 321 + .../src/core/operations/Adler32Checksum.mjs | 56 + .../core/operations/AffineCipherDecode.mjs | 108 + .../core/operations/AffineCipherEncode.mjs | 80 + .../src/core/operations/AlternatingCaps.mjs | 55 + .../src/core/operations/AnalyseHash.mjs | 186 + .../src/core/operations/AnalyseUUID.mjs | 50 + .../srktoolbox/src/core/operations/Argon2.mjs | 119 + .../src/core/operations/Argon2Compare.mjs | 60 + .../src/core/operations/AtbashCipher.mjs | 69 + .../src/core/operations/AvroToJSON.mjs | 78 + .../src/core/operations/BLAKE2b.mjs | 81 + .../src/core/operations/BLAKE2s.mjs | 82 + .../srktoolbox/src/core/operations/BLAKE3.mjs | 58 + .../src/core/operations/BSONDeserialise.mjs | 51 + .../src/core/operations/BSONSerialise.mjs | 51 + .../src/core/operations/BaconCipherDecode.mjs | 151 + .../src/core/operations/BaconCipherEncode.mjs | 103 + .../srktoolbox/src/core/operations/Bcrypt.mjs | 58 + .../src/core/operations/BcryptCompare.mjs | 60 + .../src/core/operations/BcryptParse.mjs | 51 + .../src/core/operations/BifidCipherDecode.mjs | 127 + .../src/core/operations/BifidCipherEncode.mjs | 132 + .../src/core/operations/BitShiftLeft.mjs | 79 + .../src/core/operations/BitShiftRight.mjs | 86 + .../src/core/operations/BlowfishDecrypt.mjs | 101 + .../src/core/operations/BlowfishEncrypt.mjs | 101 + .../src/core/operations/BlurImage.mjs | 112 + .../srktoolbox/src/core/operations/Bombe.mjs | 179 + .../src/core/operations/Bzip2Compress.mjs | 75 + .../src/core/operations/Bzip2Decompress.mjs | 75 + .../src/core/operations/CBORDecode.mjs | 43 + .../src/core/operations/CBOREncode.mjs | 43 + .../srktoolbox/src/core/operations/CMAC.mjs | 151 + .../src/core/operations/CNIDVerify.mjs | 66 + .../src/core/operations/CRCChecksum.mjs | 1112 + .../src/core/operations/CSSBeautify.mjs | 49 + .../src/core/operations/CSSMinify.mjs | 49 + .../src/core/operations/CSSSelector.mjs | 93 + .../src/core/operations/CSVToJSON.mjs | 82 + .../srktoolbox/src/core/operations/CTPH.mjs | 43 + .../src/core/operations/CaesarBoxCipher.mjs | 63 + .../src/core/operations/CaretMdecode.mjs | 100 + .../src/core/operations/CartesianProduct.mjs | 99 + .../core/operations/CetaceanCipherDecode.mjs | 65 + .../core/operations/CetaceanCipherEncode.mjs | 53 + .../srktoolbox/src/core/operations/ChaCha.mjs | 236 + .../src/core/operations/ChangeIPFormat.mjs | 140 + .../src/core/operations/ChiSquare.mjs | 56 + .../core/operations/CipherSaber2Decrypt.mjs | 63 + .../core/operations/CipherSaber2Encrypt.mjs | 67 + .../src/core/operations/CitrixCTX1Decode.mjs | 61 + .../src/core/operations/CitrixCTX1Encode.mjs | 52 + .../src/core/operations/Colossus.mjs | 586 + .../src/core/operations/Comment.mjs | 50 + .../src/core/operations/CompareCTPHHashes.mjs | 54 + .../core/operations/CompareSSDEEPHashes.mjs | 54 + .../src/core/operations/ConditionalJump.mjs | 89 + .../src/core/operations/ContainImage.mjs | 174 + .../src/core/operations/ConvertArea.mjs | 115 + .../operations/ConvertCoordinateFormat.mjs | 97 + .../src/core/operations/ConvertDataUnits.mjs | 114 + .../src/core/operations/ConvertDistance.mjs | 99 + .../core/operations/ConvertImageFormat.mjs | 139 + .../src/core/operations/ConvertLeetSpeak.mjs | 118 + .../src/core/operations/ConvertMass.mjs | 146 + .../src/core/operations/ConvertSpeed.mjs | 99 + .../core/operations/ConvertToNATOAlphabet.mjs | 84 + .../src/core/operations/CountOccurrences.mjs | 67 + .../src/core/operations/CoverImage.mjs | 154 + .../src/core/operations/CropImage.mjs | 167 + .../src/core/operations/DESDecrypt.mjs | 110 + .../src/core/operations/DESEncrypt.mjs | 96 + .../src/core/operations/DNSOverHTTPS.mjs | 144 + .../src/core/operations/DateTimeDelta.mjs | 109 + .../core/operations/DechunkHTTPResponse.mjs | 60 + .../src/core/operations/DecodeNetBIOSName.mjs | 69 + .../src/core/operations/DecodeText.mjs | 58 + .../src/core/operations/DefangIPAddresses.mjs | 73 + .../src/core/operations/DefangURL.mjs | 104 + .../src/core/operations/DeriveEVPKey.mjs | 149 + .../src/core/operations/DeriveHKDFKey.mjs | 140 + .../src/core/operations/DerivePBKDF2Key.mjs | 80 + .../src/core/operations/DetectFileType.mjs | 83 + .../srktoolbox/src/core/operations/Diff.mjs | 137 + .../src/core/operations/DisassembleX86.mjs | 136 + .../src/core/operations/DitherImage.mjs | 89 + .../srktoolbox/src/core/operations/Divide.mjs | 53 + .../src/core/operations/DropBytes.mjs | 125 + .../src/core/operations/DropNthBytes.mjs | 81 + .../src/core/operations/ECDSASign.mjs | 109 + .../operations/ECDSASignatureConversion.mjs | 148 + .../src/core/operations/ECDSAVerify.mjs | 163 + .../src/core/operations/ELFInfo.mjs | 915 + .../src/core/operations/EncodeNetBIOSName.mjs | 62 + .../src/core/operations/EncodeText.mjs | 60 + .../srktoolbox/src/core/operations/Enigma.mjs | 217 + .../src/core/operations/Entropy.mjs | 432 + .../src/core/operations/EscapeString.mjs | 96 + .../operations/EscapeUnicodeCharacters.mjs | 81 + .../core/operations/ExpandAlphabetRange.mjs | 48 + .../src/core/operations/ExtractDates.mjs | 60 + .../src/core/operations/ExtractDomains.mjs | 78 + .../src/core/operations/ExtractEXIF.mjs | 65 + .../core/operations/ExtractEmailAddresses.mjs | 75 + .../src/core/operations/ExtractFilePaths.mjs | 104 + .../src/core/operations/ExtractFiles.mjs | 125 + .../src/core/operations/ExtractHashes.mjs | 86 + .../src/core/operations/ExtractID3.mjs | 326 + .../core/operations/ExtractIPAddresses.mjs | 124 + .../src/core/operations/ExtractLSB.mjs | 122 + .../core/operations/ExtractMACAddresses.mjs | 73 + .../src/core/operations/ExtractRGBA.mjs | 69 + .../src/core/operations/ExtractURLs.mjs | 72 + .../src/core/operations/FangURL.mjs | 80 + .../src/core/operations/FernetDecrypt.mjs | 65 + .../src/core/operations/FernetEncrypt.mjs | 56 + .../src/core/operations/FileTree.mjs | 96 + .../srktoolbox/src/core/operations/Filter.mjs | 75 + .../src/core/operations/FindReplace.mjs | 96 + .../core/operations/Fletcher16Checksum.mjs | 52 + .../core/operations/Fletcher32Checksum.mjs | 60 + .../core/operations/Fletcher64Checksum.mjs | 64 + .../src/core/operations/Fletcher8Checksum.mjs | 52 + .../src/core/operations/FlipImage.mjs | 107 + .../srktoolbox/src/core/operations/Fork.mjs | 128 + .../core/operations/FormatMACAddresses.mjs | 124 + .../core/operations/FrequencyDistribution.mjs | 134 + .../src/core/operations/FromBCD.mjs | 125 + .../src/core/operations/FromBase.mjs | 66 + .../src/core/operations/FromBase32.mjs | 108 + .../src/core/operations/FromBase45.mjs | 103 + .../src/core/operations/FromBase58.mjs | 115 + .../src/core/operations/FromBase62.mjs | 67 + .../src/core/operations/FromBase64.mjs | 177 + .../src/core/operations/FromBase85.mjs | 162 + .../src/core/operations/FromBase92.mjs | 57 + .../src/core/operations/FromBech32.mjs | 151 + .../src/core/operations/FromBinary.mjs | 127 + .../src/core/operations/FromBraille.mjs | 72 + .../operations/FromCaseInsensitiveRegex.mjs | 41 + .../src/core/operations/FromCharcode.mjs | 87 + .../src/core/operations/FromDecimal.mjs | 90 + .../src/core/operations/FromFloat.mjs | 80 + .../src/core/operations/FromHTMLEntity.mjs | 1541 + .../src/core/operations/FromHex.mjs | 154 + .../src/core/operations/FromHexContent.mjs | 76 + .../src/core/operations/FromHexdump.mjs | 168 + .../src/core/operations/FromMessagePack.mjs | 49 + .../src/core/operations/FromModhex.mjs | 86 + .../src/core/operations/FromMorseCode.mjs | 156 + .../src/core/operations/FromOctal.mjs | 84 + .../src/core/operations/FromPunycode.mjs | 55 + .../core/operations/FromQuotedPrintable.mjs | 71 + .../src/core/operations/FromUNIXTimestamp.mjs | 94 + .../src/core/operations/FuzzyMatch.mjs | 123 + .../src/core/operations/GOSTDecrypt.mjs | 153 + .../src/core/operations/GOSTEncrypt.mjs | 153 + .../src/core/operations/GOSTHash.mjs | 93 + .../src/core/operations/GOSTKeyUnwrap.mjs | 144 + .../src/core/operations/GOSTKeyWrap.mjs | 144 + .../src/core/operations/GOSTSign.mjs | 144 + .../src/core/operations/GOSTVerify.mjs | 138 + .../core/operations/GenerateAllChecksums.mjs | 256 + .../src/core/operations/GenerateAllHashes.mjs | 181 + .../operations/GenerateDeBruijnSequence.mjs | 87 + .../core/operations/GenerateECDSAKeyPair.mjs | 104 + .../src/core/operations/GenerateHOTP.mjs | 70 + .../src/core/operations/GenerateImage.mjs | 193 + .../core/operations/GenerateLoremIpsum.mjs | 72 + .../core/operations/GeneratePGPKeyPair.mjs | 124 + .../src/core/operations/GenerateQRCode.mjs | 96 + .../core/operations/GenerateRSAKeyPair.mjs | 90 + .../src/core/operations/GenerateTOTP.mjs | 75 + .../src/core/operations/GenerateUUID.mjs | 80 + .../core/operations/GenericCodeBeautify.mjs | 163 + .../src/core/operations/GetAllCasings.mjs | 55 + .../src/core/operations/GetTime.mjs | 65 + .../src/core/operations/GroupIPAddresses.mjs | 139 + .../srktoolbox/src/core/operations/Gunzip.mjs | 53 + .../srktoolbox/src/core/operations/Gzip.mjs | 91 + .../srktoolbox/src/core/operations/HAS160.mjs | 51 + .../operations/HASSHClientFingerprint.mjs | 168 + .../operations/HASSHServerFingerprint.mjs | 168 + .../srktoolbox/src/core/operations/HMAC.mjs | 84 + .../src/core/operations/HTMLToText.mjs | 43 + .../src/core/operations/HTTPRequest.mjs | 149 + .../src/core/operations/HammingDistance.mjs | 100 + .../src/core/operations/HaversineDistance.mjs | 61 + .../srktoolbox/src/core/operations/Head.mjs | 70 + .../src/core/operations/HeatmapChart.mjs | 268 + .../src/core/operations/HexDensityChart.mjs | 298 + .../core/operations/HexToObjectIdentifier.mjs | 43 + .../src/core/operations/HexToPEM.mjs | 49 + .../operations/IPv6TransitionAddresses.mjs | 211 + .../operations/ImageBrightnessContrast.mjs | 112 + .../src/core/operations/ImageFilter.mjs | 104 + .../ImageHueSaturationLightness.mjs | 141 + .../src/core/operations/ImageOpacity.mjs | 96 + .../core/operations/IndexOfCoincidence.mjs | 109 + .../src/core/operations/InvertImage.mjs | 87 + .../src/core/operations/JA3Fingerprint.mjs | 207 + .../src/core/operations/JA3SFingerprint.mjs | 147 + .../src/core/operations/JA4Fingerprint.mjs | 75 + .../core/operations/JA4ServerFingerprint.mjs | 68 + .../src/core/operations/JPathExpression.mjs | 73 + .../src/core/operations/JSONBeautify.mjs | 246 + .../src/core/operations/JSONMinify.mjs | 43 + .../src/core/operations/JSONToCSV.mjs | 144 + .../src/core/operations/JSONtoYAML.mjs | 48 + .../src/core/operations/JWKToPem.mjs | 82 + .../src/core/operations/JWTDecode.mjs | 60 + .../src/core/operations/JWTSign.mjs | 72 + .../src/core/operations/JWTVerify.mjs | 65 + .../core/operations/JavaScriptBeautify.mjs | 97 + .../src/core/operations/JavaScriptMinify.mjs | 47 + .../src/core/operations/JavaScriptParser.mjs | 80 + plugins/srktoolbox/src/core/operations/Jq.mjs | 59 + .../src/core/operations/Jsonata.mjs | 67 + .../srktoolbox/src/core/operations/Jump.mjs | 68 + .../srktoolbox/src/core/operations/Keccak.mjs | 70 + .../srktoolbox/src/core/operations/LMHash.mjs | 43 + .../src/core/operations/LS47Decrypt.mjs | 59 + .../src/core/operations/LS47Encrypt.mjs | 64 + .../src/core/operations/LZ4Compress.mjs | 45 + .../src/core/operations/LZ4Decompress.mjs | 45 + .../src/core/operations/LZMACompress.mjs | 66 + .../src/core/operations/LZMADecompress.mjs | 59 + .../src/core/operations/LZNT1Decompress.mjs | 43 + .../src/core/operations/LZStringCompress.mjs | 57 + .../core/operations/LZStringDecompress.mjs | 58 + .../srktoolbox/src/core/operations/Label.mjs | 50 + .../core/operations/LevenshteinDistance.mjs | 100 + .../srktoolbox/src/core/operations/Lorenz.mjs | 763 + .../src/core/operations/LuhnChecksum.mjs | 98 + .../srktoolbox/src/core/operations/MD2.mjs | 50 + .../srktoolbox/src/core/operations/MD4.mjs | 43 + .../srktoolbox/src/core/operations/MD5.mjs | 43 + .../srktoolbox/src/core/operations/MD6.mjs | 67 + .../src/core/operations/MIMEDecoding.mjs | 173 + .../srktoolbox/src/core/operations/Magic.mjs | 170 + .../srktoolbox/src/core/operations/Mean.mjs | 53 + .../srktoolbox/src/core/operations/Median.mjs | 53 + .../srktoolbox/src/core/operations/Merge.mjs | 52 + .../operations/MicrosoftScriptDecoder.mjs | 227 + .../src/core/operations/MultipleBombe.mjs | 307 + .../src/core/operations/Multiply.mjs | 54 + .../src/core/operations/MurmurHash3.mjs | 141 + .../srktoolbox/src/core/operations/NOT.mjs | 70 + .../srktoolbox/src/core/operations/NTHash.mjs | 50 + .../src/core/operations/NormaliseImage.mjs | 85 + .../src/core/operations/NormaliseUnicode.mjs | 64 + .../src/core/operations/Numberwang.mjs | 101 + plugins/srktoolbox/src/core/operations/OR.mjs | 80 + .../core/operations/ObjectIdentifierToHex.mjs | 43 + .../src/core/operations/OffsetChecker.mjs | 109 + .../OpticalCharacterRecognition.mjs | 98 + .../src/core/operations/PEMToHex.mjs | 70 + .../src/core/operations/PEMToJWK.mjs | 90 + .../src/core/operations/PGPDecrypt.mjs | 89 + .../core/operations/PGPDecryptAndVerify.mjs | 126 + .../src/core/operations/PGPEncrypt.mjs | 81 + .../src/core/operations/PGPEncryptAndSign.mjs | 96 + .../src/core/operations/PGPVerify.mjs | 113 + .../src/core/operations/PHPDeserialize.mjs | 173 + .../src/core/operations/PHPSerialize.mjs | 126 + .../src/core/operations/PLISTViewer.mjs | 135 + .../src/core/operations/PadLines.mjs | 72 + .../core/operations/ParseASN1HexString.mjs | 57 + .../src/core/operations/ParseCSR.mjs | 392 + .../src/core/operations/ParseColourCode.mjs | 198 + .../src/core/operations/ParseDateTime.mjs | 85 + .../src/core/operations/ParseIPRange.mjs | 91 + .../src/core/operations/ParseIPv4Header.mjs | 132 + .../src/core/operations/ParseIPv6Address.mjs | 278 + .../operations/ParseObjectIDTimestamp.mjs | 49 + .../src/core/operations/ParseQRCode.mjs | 64 + .../src/core/operations/ParseSSHHostKey.mjs | 161 + .../src/core/operations/ParseTCP.mjs | 247 + .../src/core/operations/ParseTLSRecord.mjs | 886 + .../src/core/operations/ParseTLV.mjs | 79 + .../src/core/operations/ParseUDP.mjs | 91 + .../operations/ParseUNIXFilePermissions.mjs | 334 + .../src/core/operations/ParseURI.mjs | 72 + .../src/core/operations/ParseUserAgent.mjs | 65 + .../src/core/operations/ParseX509CRL.mjs | 393 + .../core/operations/ParseX509Certificate.mjs | 233 + .../src/core/operations/PlayMedia.mjs | 103 + .../src/core/operations/PowerSet.mjs | 95 + .../src/core/operations/ProtobufDecode.mjs | 67 + .../src/core/operations/ProtobufEncode.mjs | 56 + .../PseudoRandomNumberGenerator.mjs | 88 + .../src/core/operations/PubKeyFromCert.mjs | 70 + .../src/core/operations/PubKeyFromPrivKey.mjs | 84 + .../srktoolbox/src/core/operations/RAKE.mjs | 146 + .../src/core/operations/RC2Decrypt.mjs | 78 + .../src/core/operations/RC2Encrypt.mjs | 79 + .../srktoolbox/src/core/operations/RC4.mjs | 91 + .../src/core/operations/RC4Drop.mjs | 97 + .../srktoolbox/src/core/operations/RIPEMD.mjs | 50 + .../srktoolbox/src/core/operations/ROT13.mjs | 116 + .../src/core/operations/ROT13BruteForce.mjs | 104 + .../srktoolbox/src/core/operations/ROT47.mjs | 91 + .../src/core/operations/ROT47BruteForce.mjs | 84 + .../src/core/operations/ROT8000.mjs | 125 + .../src/core/operations/RSADecrypt.mjs | 88 + .../src/core/operations/RSAEncrypt.mjs | 91 + .../src/core/operations/RSASign.mjs | 76 + .../src/core/operations/RSAVerify.mjs | 86 + .../srktoolbox/src/core/operations/Rabbit.mjs | 249 + .../core/operations/RailFenceCipherDecode.mjs | 83 + .../core/operations/RailFenceCipherEncode.mjs | 76 + .../operations/RandomizeColourPalette.mjs | 85 + .../src/core/operations/RawDeflate.mjs | 61 + .../src/core/operations/RawInflate.mjs | 92 + .../src/core/operations/Register.mjs | 122 + .../src/core/operations/RegularExpression.mjs | 274 + .../src/core/operations/RemoveDiacritics.mjs | 43 + .../src/core/operations/RemoveEXIF.mjs | 58 + .../src/core/operations/RemoveLineNumbers.mjs | 41 + .../src/core/operations/RemoveNullBytes.mjs | 46 + .../src/core/operations/RemoveWhitespace.mjs | 88 + .../src/core/operations/RenderImage.mjs | 114 + .../src/core/operations/RenderMarkdown.mjs | 71 + .../src/core/operations/ResizeImage.mjs | 154 + .../srktoolbox/src/core/operations/Return.mjs | 45 + .../src/core/operations/Reverse.mjs | 89 + .../src/core/operations/RisonDecode.mjs | 59 + .../src/core/operations/RisonEncode.mjs | 61 + .../src/core/operations/RoarCipherDecode.mjs | 87 + .../src/core/operations/RoarCipherEncode.mjs | 78 + .../src/core/operations/RotateImage.mjs | 96 + .../src/core/operations/RotateLeft.mjs | 84 + .../src/core/operations/RotateRight.mjs | 84 + .../srktoolbox/src/core/operations/SHA0.mjs | 50 + .../srktoolbox/src/core/operations/SHA1.mjs | 50 + .../srktoolbox/src/core/operations/SHA2.mjs | 94 + .../srktoolbox/src/core/operations/SHA3.mjs | 70 + .../srktoolbox/src/core/operations/SIGABA.mjs | 287 + .../src/core/operations/SM2Decrypt.mjs | 73 + .../src/core/operations/SM2Encrypt.mjs | 79 + .../srktoolbox/src/core/operations/SM3.mjs | 59 + .../src/core/operations/SM4Decrypt.mjs | 90 + .../src/core/operations/SM4Encrypt.mjs | 90 + .../src/core/operations/SQLBeautify.mjs | 49 + .../src/core/operations/SQLMinify.mjs | 42 + .../srktoolbox/src/core/operations/SSDEEP.mjs | 43 + .../srktoolbox/src/core/operations/SUB.mjs | 79 + .../src/core/operations/Salsa20.mjs | 156 + .../core/operations/ScanForEmbeddedFiles.mjs | 80 + .../src/core/operations/ScatterChart.mjs | 201 + .../srktoolbox/src/core/operations/Scrypt.mjs | 92 + .../src/core/operations/SeriesChart.mjs | 232 + .../src/core/operations/SetDifference.mjs | 89 + .../src/core/operations/SetIntersection.mjs | 89 + .../src/core/operations/SetUnion.mjs | 99 + .../srktoolbox/src/core/operations/Shake.mjs | 73 + .../src/core/operations/SharpenImage.mjs | 203 + .../src/core/operations/ShowBase64Offsets.mjs | 175 + .../src/core/operations/ShowOnMap.mjs | 123 + .../src/core/operations/Shuffle.mjs | 80 + .../srktoolbox/src/core/operations/Sleep.mjs | 49 + .../srktoolbox/src/core/operations/Snefru.mjs | 60 + .../srktoolbox/src/core/operations/Sort.mjs | 80 + .../srktoolbox/src/core/operations/Split.mjs | 57 + .../core/operations/SplitColourChannels.mjs | 130 + .../src/core/operations/StandardDeviation.mjs | 55 + .../src/core/operations/Streebog.mjs | 65 + .../src/core/operations/Strings.mjs | 141 + .../src/core/operations/StripHTMLTags.mjs | 74 + .../src/core/operations/StripHTTPHeaders.mjs | 52 + .../src/core/operations/StripIPv4Header.mjs | 59 + .../src/core/operations/StripTCPHeader.mjs | 62 + .../src/core/operations/StripUDPHeader.mjs | 53 + .../src/core/operations/Subsection.mjs | 163 + .../src/core/operations/Substitute.mjs | 114 + .../src/core/operations/Subtract.mjs | 54 + .../srktoolbox/src/core/operations/Sum.mjs | 54 + .../src/core/operations/SwapCase.mjs | 78 + .../src/core/operations/SwapEndianness.mjs | 140 + .../core/operations/SymmetricDifference.mjs | 101 + .../src/core/operations/SyntaxHighlighter.mjs | 81 + .../src/core/operations/TCPIPChecksum.mjs | 56 + .../srktoolbox/src/core/operations/Tail.mjs | 72 + .../src/core/operations/TakeBytes.mjs | 119 + .../src/core/operations/TakeNthBytes.mjs | 81 + .../srktoolbox/src/core/operations/Tar.mjs | 144 + .../src/core/operations/Template.mjs | 55 + .../operations/TextEncodingBruteForce.mjs | 94 + .../srktoolbox/src/core/operations/ToBCD.mjs | 144 + .../srktoolbox/src/core/operations/ToBase.mjs | 56 + .../src/core/operations/ToBase32.mjs | 89 + .../src/core/operations/ToBase45.mjs | 84 + .../src/core/operations/ToBase58.mjs | 92 + .../src/core/operations/ToBase62.mjs | 64 + .../src/core/operations/ToBase64.mjs | 79 + .../src/core/operations/ToBase85.mjs | 96 + .../src/core/operations/ToBase92.mjs | 69 + .../src/core/operations/ToBech32.mjs | 94 + .../src/core/operations/ToBinary.mjs | 90 + .../src/core/operations/ToBraille.mjs | 72 + .../core/operations/ToCNNumberUpperCase.mjs | 86 + .../src/core/operations/ToCamelCase.mjs | 56 + .../operations/ToCaseInsensitiveRegex.mjs | 97 + .../src/core/operations/ToCharcode.mjs | 89 + .../src/core/operations/ToDecimal.mjs | 62 + .../src/core/operations/ToFloat.mjs | 82 + .../src/core/operations/ToHTMLEntity.mjs | 1514 + .../srktoolbox/src/core/operations/ToHex.mjs | 134 + .../src/core/operations/ToHexContent.mjs | 85 + .../src/core/operations/ToHexdump.mjs | 197 + .../src/core/operations/ToKebabCase.mjs | 56 + .../src/core/operations/ToLowerCase.mjs | 67 + .../src/core/operations/ToMessagePack.mjs | 55 + .../src/core/operations/ToModhex.mjs | 57 + .../src/core/operations/ToMorseCode.mjs | 157 + .../src/core/operations/ToOctal.mjs | 52 + .../src/core/operations/ToPunycode.mjs | 55 + .../src/core/operations/ToQuotedPrintable.mjs | 248 + .../src/core/operations/ToSnakeCase.mjs | 55 + .../src/core/operations/ToTable.mjs | 248 + .../src/core/operations/ToUNIXTimestamp.mjs | 80 + .../src/core/operations/ToUpperCase.mjs | 97 + .../operations/TranslateDateTimeFormat.mjs | 95 + .../src/core/operations/TripleDESDecrypt.mjs | 112 + .../src/core/operations/TripleDESEncrypt.mjs | 99 + .../srktoolbox/src/core/operations/Typex.mjs | 253 + .../UNIXTimestampToWindowsFiletime.mjs | 95 + .../src/core/operations/URLDecode.mjs | 61 + .../src/core/operations/URLEncode.mjs | 71 + .../src/core/operations/UnescapeString.mjs | 43 + .../operations/UnescapeUnicodeCharacters.mjs | 93 + .../src/core/operations/UnicodeTextFormat.mjs | 69 + .../srktoolbox/src/core/operations/Unique.mjs | 70 + .../srktoolbox/src/core/operations/Untar.mjs | 111 + .../srktoolbox/src/core/operations/Unzip.mjs | 85 + .../src/core/operations/VarIntDecode.mjs | 59 + .../src/core/operations/VarIntEncode.mjs | 60 + .../src/core/operations/ViewBitPlane.mjs | 105 + .../operations/Vigen\347\214\253reDecode.mjs" | 104 + .../operations/Vigen\347\214\253reEncode.mjs" | 109 + .../src/core/operations/Whirlpool.mjs | 57 + .../WindowsFiletimeToUNIXTimestamp.mjs | 92 + .../src/core/operations/XKCDRandomNumber.mjs | 41 + .../src/core/operations/XMLBeautify.mjs | 49 + .../src/core/operations/XMLMinify.mjs | 49 + .../srktoolbox/src/core/operations/XOR.mjs | 91 + .../src/core/operations/XORBruteForce.mjs | 141 + .../src/core/operations/XORChecksum.mjs | 61 + .../src/core/operations/XPathExpression.mjs | 82 + .../src/core/operations/XSalsa20.mjs | 158 + .../src/core/operations/XXTEADecrypt.mjs | 59 + .../src/core/operations/XXTEAEncrypt.mjs | 54 + .../src/core/operations/YAMLToJSON.mjs | 47 + .../src/core/operations/YARARules.mjs | 143 + .../srktoolbox/src/core/operations/Zip.mjs | 105 + .../src/core/operations/ZlibDeflate.mjs | 55 + .../src/core/operations/ZlibInflate.mjs | 91 + .../src/core/vendor/DisassembleX86-64.mjs | 5760 ++++ .../src/core/vendor/gost/gostCipher.mjs | 2259 ++ .../src/core/vendor/gost/gostCoding.mjs | 1160 + .../src/core/vendor/gost/gostCrypto.mjs | 1653 ++ .../src/core/vendor/gost/gostDigest.mjs | 1260 + .../src/core/vendor/gost/gostEngine.mjs | 451 + .../src/core/vendor/gost/gostRandom.mjs | 128 + .../src/core/vendor/gost/gostSign.mjs | 2023 ++ .../src/core/vendor/remove-exif.mjs | 151 + .../tesseract/lang-data/eng.traineddata.gz | Bin 0 -> 10923060 bytes plugins/srktoolbox/src/env.d.ts | 23 + plugins/srktoolbox/src/main.css | 63 + plugins/srktoolbox/src/main.ts | 5 + plugins/srktoolbox/src/node/File.mjs | 76 + plugins/srktoolbox/src/node/NodeDish.mjs | 84 + plugins/srktoolbox/src/node/NodeRecipe.mjs | 104 + plugins/srktoolbox/src/node/api.mjs | 357 + plugins/srktoolbox/src/node/apiUtils.mjs | 86 + .../src/node/config/excludedOperations.mjs | 24 + .../node/config/scripts/generateNodeIndex.mjs | 127 + plugins/srktoolbox/src/node/repl.mjs | 36 + plugins/srktoolbox/src/node/wrapper.js | 11 + plugins/srktoolbox/src/web/App.mjs | 851 + plugins/srktoolbox/src/web/HTMLCategory.mjs | 62 + plugins/srktoolbox/src/web/HTMLIngredient.mjs | 424 + plugins/srktoolbox/src/web/HTMLOperation.mjs | 179 + plugins/srktoolbox/src/web/Manager.mjs | 362 + plugins/srktoolbox/src/web/html/index.html | 914 + plugins/srktoolbox/src/web/index.js | 77 + .../static/fonts/MaterialIcons-Regular.ttf | Bin 0 -> 354228 bytes .../static/fonts/bmfonts/Roboto72White.fnt | 491 + .../static/fonts/bmfonts/Roboto72White.png | Bin 0 -> 52730 bytes .../fonts/bmfonts/RobotoBlack72White.fnt | 494 + .../fonts/bmfonts/RobotoBlack72White.png | Bin 0 -> 50192 bytes .../fonts/bmfonts/RobotoMono72White.fnt | 110 + .../fonts/bmfonts/RobotoMono72White.png | Bin 0 -> 52580 bytes .../fonts/bmfonts/RobotoSlab72White.fnt | 498 + .../fonts/bmfonts/RobotoSlab72White.png | Bin 0 -> 54282 bytes plugins/srktoolbox/src/web/static/ga.html | 12 + .../src/web/static/images/IMAGE_LICENCES.md | 11 + .../src/web/static/images/bombe.svg | 261 + .../web/static/images/cook_female-32x32.png | Bin 0 -> 1709 bytes .../src/web/static/images/cook_male-32x32.png | Bin 0 -> 1624 bytes .../web/static/images/cyberchef-128x128.png | Bin 0 -> 5970 bytes .../web/static/images/cyberchef-256x256.png | Bin 0 -> 14616 bytes .../src/web/static/images/cyberchef-32x32.png | Bin 0 -> 1154 bytes .../web/static/images/cyberchef-512x512.png | Bin 0 -> 32687 bytes .../src/web/static/images/cyberchef-64x64.png | Bin 0 -> 2557 bytes .../src/web/static/images/favicon.ico | Bin 0 -> 15406 bytes .../web/static/images/favicon.ico.original | Bin 0 -> 1082 bytes .../src/web/static/images/file-128x128.png | Bin 0 -> 19378 bytes .../src/web/static/images/file-32x32.png | Bin 0 -> 1946 bytes .../src/web/static/images/fork_me.png | Bin 0 -> 5453 bytes .../src/web/static/images/gitter-badge.svg | 1 + .../src/web/static/images/logo/cyberchef.svg | 728 + .../web/static/images/logo/cyberchef_512.png | Bin 0 -> 39069 bytes .../static/images/logo/cyberchef_banner.svg | 754 + .../images/logo/cyberchef_banner_1500.png | Bin 0 -> 61737 bytes .../web/static/images/logo/cyberchef_hat.svg | 146 + .../static/images/logo/cyberchef_hat_512.png | Bin 0 -> 20519 bytes .../images/logo/cyberchef_hat_text_512.png | Bin 0 -> 29359 bytes .../static/images/logo/cyberchef_human.svg | 1157 + .../static/images/logo/cyberchef_robot.svg | 833 + .../src/web/static/images/multitool-32x32.png | Bin 0 -> 1695 bytes .../src/web/static/images/rocket-1.svg | 12 + .../src/web/static/images/srk-128x128.png | Bin 0 -> 4272 bytes .../src/web/static/images/srk-32x32.png | Bin 0 -> 1106 bytes plugins/srktoolbox/src/web/static/sitemap.mjs | 33 + .../src/web/static/structuredData.json | 26 + .../web/stylesheets/components/_button.css | 13 + .../src/web/stylesheets/components/_list.css | 52 + .../web/stylesheets/components/_operation.css | 326 + .../src/web/stylesheets/components/_pane.css | 54 + .../srktoolbox/src/web/stylesheets/index.css | 40 + .../srktoolbox/src/web/stylesheets/index.js | 17 + .../src/web/stylesheets/layout/_banner.css | 34 + .../src/web/stylesheets/layout/_controls.css | 69 + .../src/web/stylesheets/layout/_io.css | 592 + .../src/web/stylesheets/layout/_modals.css | 116 + .../web/stylesheets/layout/_operations.css | 43 + .../src/web/stylesheets/layout/_recipe.css | 17 + .../src/web/stylesheets/layout/_structure.css | 79 + .../src/web/stylesheets/operations/diff.css | 8 + .../src/web/stylesheets/operations/json.css | 79 + .../src/web/stylesheets/preloader.css | 162 + .../src/web/stylesheets/themes/_classic.css | 138 + .../src/web/stylesheets/themes/_dark.css | 131 + .../src/web/stylesheets/themes/_geocities.css | 131 + .../web/stylesheets/themes/_solarizedDark.css | 148 + .../stylesheets/themes/_solarizedLight.css | 150 + .../src/web/stylesheets/utils/_general.css | 92 + .../src/web/stylesheets/utils/_overrides.css | 257 + .../srktoolbox/src/web/utils/copyOverride.mjs | 125 + .../srktoolbox/src/web/utils/editorUtils.mjs | 138 + .../srktoolbox/src/web/utils/fileDetails.mjs | 149 + .../srktoolbox/src/web/utils/htmlWidget.mjs | 134 + .../srktoolbox/src/web/utils/sidePanel.mjs | 263 + .../srktoolbox/src/web/utils/statusBar.mjs | 517 + .../web/waiters/BackgroundWorkerWaiter.mjs | 178 + .../src/web/waiters/BindingsWaiter.mjs | 310 + .../src/web/waiters/ControlsWaiter.mjs | 473 + .../src/web/waiters/HighlighterWaiter.mjs | 140 + .../src/web/waiters/InputWaiter.mjs | 1699 ++ .../src/web/waiters/OperationsWaiter.mjs | 316 + .../src/web/waiters/OptionsWaiter.mjs | 209 + .../src/web/waiters/OutputWaiter.mjs | 1691 ++ .../src/web/waiters/RecipeWaiter.mjs | 652 + .../src/web/waiters/SeasonalWaiter.mjs | 61 + .../srktoolbox/src/web/waiters/TabWaiter.mjs | 252 + .../src/web/waiters/TimingWaiter.mjs | 184 + .../src/web/waiters/WindowWaiter.mjs | 63 + .../src/web/waiters/WorkerWaiter.mjs | 890 + .../srktoolbox/src/web/workers/DishWorker.mjs | 116 + .../src/web/workers/InputWorker.mjs | 965 + .../src/web/workers/LoaderWorker.js | 80 + .../srktoolbox/src/web/workers/ZipWorker.mjs | 82 + plugins/srktoolbox/tsconfig.json | 19 + plugins/srktoolbox/vite.config.js | 19 + plugins/srktoolbox/webpack.config.js | 263 + 709 files changed, 153001 insertions(+) create mode 100644 plugins/srktoolbox/.cspell.json create mode 100644 plugins/srktoolbox/.dockerignore create mode 100644 plugins/srktoolbox/.editorconfig create mode 100644 plugins/srktoolbox/.gitattributes create mode 100644 plugins/srktoolbox/.gitignore create mode 100644 plugins/srktoolbox/.npmignore create mode 100644 plugins/srktoolbox/.nvmrc create mode 100644 plugins/srktoolbox/CHANGELOG.md create mode 100644 plugins/srktoolbox/CHANGELOG_SRKTOOLBOX.md create mode 100644 plugins/srktoolbox/CODE_OF_CONDUCT.md create mode 100644 plugins/srktoolbox/Dockerfile create mode 100644 plugins/srktoolbox/Gruntfile.js create mode 100644 plugins/srktoolbox/LICENSE create mode 100644 plugins/srktoolbox/README.md create mode 100644 plugins/srktoolbox/SECURITY.md create mode 100644 plugins/srktoolbox/babel.config.js create mode 100644 plugins/srktoolbox/eslint.config.mjs create mode 100644 plugins/srktoolbox/index.html create mode 100644 plugins/srktoolbox/nightwatch.json create mode 100644 plugins/srktoolbox/package-lock.json create mode 100644 plugins/srktoolbox/package.json create mode 100644 plugins/srktoolbox/plugin.json create mode 100644 plugins/srktoolbox/pnpm-lock.yaml create mode 100644 plugins/srktoolbox/postcss.config.js create mode 100644 plugins/srktoolbox/public/logo.png create mode 100644 plugins/srktoolbox/public/plugin.json create mode 100644 plugins/srktoolbox/public/preload/package.json create mode 100644 plugins/srktoolbox/public/preload/services.js create mode 100644 plugins/srktoolbox/src/App.vue create mode 100644 plugins/srktoolbox/src/Hello/index.vue create mode 100644 plugins/srktoolbox/src/Read/index.vue create mode 100644 plugins/srktoolbox/src/Write/index.vue create mode 100644 plugins/srktoolbox/src/core/Chef.mjs create mode 100644 plugins/srktoolbox/src/core/ChefWorker.js create mode 100644 plugins/srktoolbox/src/core/Dish.mjs create mode 100644 plugins/srktoolbox/src/core/Ingredient.mjs create mode 100644 plugins/srktoolbox/src/core/Operation.mjs create mode 100644 plugins/srktoolbox/src/core/Recipe.mjs create mode 100644 plugins/srktoolbox/src/core/Utils.mjs create mode 100644 plugins/srktoolbox/src/core/config/Categories.json create mode 100644 plugins/srktoolbox/src/core/config/scripts/generateConfig.mjs create mode 100644 plugins/srktoolbox/src/core/config/scripts/generateOpsIndex.mjs create mode 100644 plugins/srktoolbox/src/core/config/scripts/newMinorVersion.mjs create mode 100644 plugins/srktoolbox/src/core/config/scripts/newOperation.mjs create mode 100644 plugins/srktoolbox/src/core/dishTypes/DishBigNumber.mjs create mode 100644 plugins/srktoolbox/src/core/dishTypes/DishByteArray.mjs create mode 100644 plugins/srktoolbox/src/core/dishTypes/DishFile.mjs create mode 100644 plugins/srktoolbox/src/core/dishTypes/DishHTML.mjs create mode 100644 plugins/srktoolbox/src/core/dishTypes/DishJSON.mjs create mode 100644 plugins/srktoolbox/src/core/dishTypes/DishListFile.mjs create mode 100644 plugins/srktoolbox/src/core/dishTypes/DishNumber.mjs create mode 100644 plugins/srktoolbox/src/core/dishTypes/DishString.mjs create mode 100644 plugins/srktoolbox/src/core/dishTypes/DishType.mjs create mode 100644 plugins/srktoolbox/src/core/dishTypes/index.mjs create mode 100644 plugins/srktoolbox/src/core/errors/DishError.mjs create mode 100644 plugins/srktoolbox/src/core/errors/ExcludedOperationError.mjs create mode 100644 plugins/srktoolbox/src/core/errors/OperationError.mjs create mode 100644 plugins/srktoolbox/src/core/errors/index.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Arithmetic.mjs create mode 100644 plugins/srktoolbox/src/core/lib/BCD.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Bacon.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Base32.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Base45.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Base58.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Base64.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Base85.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Base92.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Bech32.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Binary.mjs create mode 100644 plugins/srktoolbox/src/core/lib/BitwiseOp.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Blowfish.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Bombe.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Braille.mjs create mode 100644 plugins/srktoolbox/src/core/lib/CanvasComponents.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Charts.mjs create mode 100644 plugins/srktoolbox/src/core/lib/ChrEnc.mjs create mode 100644 plugins/srktoolbox/src/core/lib/CipherSaber2.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Ciphers.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Code.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Colossus.mjs create mode 100644 plugins/srktoolbox/src/core/lib/ConvertCoordinates.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Crypt.mjs create mode 100644 plugins/srktoolbox/src/core/lib/DateTime.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Decimal.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Delim.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Enigma.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Extract.mjs create mode 100644 plugins/srktoolbox/src/core/lib/FileSignatures.mjs create mode 100644 plugins/srktoolbox/src/core/lib/FileType.mjs create mode 100644 plugins/srktoolbox/src/core/lib/FlowControl.mjs create mode 100644 plugins/srktoolbox/src/core/lib/FuzzyMatch.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Hash.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Hex.mjs create mode 100644 plugins/srktoolbox/src/core/lib/IP.mjs create mode 100644 plugins/srktoolbox/src/core/lib/JA4.mjs create mode 100644 plugins/srktoolbox/src/core/lib/JWT.mjs create mode 100644 plugins/srktoolbox/src/core/lib/LS47.mjs create mode 100644 plugins/srktoolbox/src/core/lib/LZNT1.mjs create mode 100644 plugins/srktoolbox/src/core/lib/LZString.mjs create mode 100644 plugins/srktoolbox/src/core/lib/LoremIpsum.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Lorenz.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Magic.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Modhex.mjs create mode 100644 plugins/srktoolbox/src/core/lib/PGP.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Protobuf.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Protocol.mjs create mode 100644 plugins/srktoolbox/src/core/lib/PublicKey.mjs create mode 100644 plugins/srktoolbox/src/core/lib/QRCode.mjs create mode 100644 plugins/srktoolbox/src/core/lib/RSA.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Rotate.mjs create mode 100644 plugins/srktoolbox/src/core/lib/SIGABA.mjs create mode 100644 plugins/srktoolbox/src/core/lib/SM2.mjs create mode 100644 plugins/srktoolbox/src/core/lib/SM4.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Salsa20.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Sort.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Stream.mjs create mode 100644 plugins/srktoolbox/src/core/lib/TLS.mjs create mode 100644 plugins/srktoolbox/src/core/lib/TLVParser.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Typex.mjs create mode 100644 plugins/srktoolbox/src/core/lib/XXTEA.mjs create mode 100644 plugins/srktoolbox/src/core/lib/Zlib.mjs create mode 100644 plugins/srktoolbox/src/core/operations/A1Z26CipherDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/A1Z26CipherEncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ADD.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AESDecrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AESEncrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AESKeyUnwrap.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AESKeyWrap.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AMFDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AMFEncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AND.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AddLineNumbers.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AddTextToImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Adler32Checksum.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AffineCipherDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AffineCipherEncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AlternatingCaps.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AnalyseHash.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AnalyseUUID.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Argon2.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Argon2Compare.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AtbashCipher.mjs create mode 100644 plugins/srktoolbox/src/core/operations/AvroToJSON.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BLAKE2b.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BLAKE2s.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BLAKE3.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BSONDeserialise.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BSONSerialise.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BaconCipherDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BaconCipherEncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Bcrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BcryptCompare.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BcryptParse.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BifidCipherDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BifidCipherEncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BitShiftLeft.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BitShiftRight.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BlowfishDecrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BlowfishEncrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/BlurImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Bombe.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Bzip2Compress.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Bzip2Decompress.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CBORDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CBOREncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CMAC.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CNIDVerify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CRCChecksum.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CSSBeautify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CSSMinify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CSSSelector.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CSVToJSON.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CTPH.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CaesarBoxCipher.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CaretMdecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CartesianProduct.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CetaceanCipherDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CetaceanCipherEncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ChaCha.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ChangeIPFormat.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ChiSquare.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CipherSaber2Decrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CipherSaber2Encrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CitrixCTX1Decode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CitrixCTX1Encode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Colossus.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Comment.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CompareCTPHHashes.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CompareSSDEEPHashes.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ConditionalJump.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ContainImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ConvertArea.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ConvertCoordinateFormat.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ConvertDataUnits.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ConvertDistance.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ConvertImageFormat.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ConvertLeetSpeak.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ConvertMass.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ConvertSpeed.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ConvertToNATOAlphabet.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CountOccurrences.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CoverImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/CropImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DESDecrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DESEncrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DNSOverHTTPS.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DateTimeDelta.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DechunkHTTPResponse.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DecodeNetBIOSName.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DecodeText.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DefangIPAddresses.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DefangURL.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DeriveEVPKey.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DeriveHKDFKey.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DerivePBKDF2Key.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DetectFileType.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Diff.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DisassembleX86.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DitherImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Divide.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DropBytes.mjs create mode 100644 plugins/srktoolbox/src/core/operations/DropNthBytes.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ECDSASign.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ECDSASignatureConversion.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ECDSAVerify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ELFInfo.mjs create mode 100644 plugins/srktoolbox/src/core/operations/EncodeNetBIOSName.mjs create mode 100644 plugins/srktoolbox/src/core/operations/EncodeText.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Enigma.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Entropy.mjs create mode 100644 plugins/srktoolbox/src/core/operations/EscapeString.mjs create mode 100644 plugins/srktoolbox/src/core/operations/EscapeUnicodeCharacters.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExpandAlphabetRange.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractDates.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractDomains.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractEXIF.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractEmailAddresses.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractFilePaths.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractFiles.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractHashes.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractID3.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractIPAddresses.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractLSB.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractMACAddresses.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractRGBA.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ExtractURLs.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FangURL.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FernetDecrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FernetEncrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FileTree.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Filter.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FindReplace.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Fletcher16Checksum.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Fletcher32Checksum.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Fletcher64Checksum.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Fletcher8Checksum.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FlipImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Fork.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FormatMACAddresses.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FrequencyDistribution.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromBCD.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromBase.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromBase32.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromBase45.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromBase58.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromBase62.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromBase64.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromBase85.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromBase92.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromBech32.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromBinary.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromBraille.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromCaseInsensitiveRegex.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromCharcode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromDecimal.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromFloat.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromHTMLEntity.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromHex.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromHexContent.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromHexdump.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromMessagePack.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromModhex.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromMorseCode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromOctal.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromPunycode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromQuotedPrintable.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FromUNIXTimestamp.mjs create mode 100644 plugins/srktoolbox/src/core/operations/FuzzyMatch.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GOSTDecrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GOSTEncrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GOSTHash.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GOSTKeyUnwrap.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GOSTKeyWrap.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GOSTSign.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GOSTVerify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GenerateAllChecksums.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GenerateAllHashes.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GenerateDeBruijnSequence.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GenerateECDSAKeyPair.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GenerateHOTP.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GenerateImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GenerateLoremIpsum.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GeneratePGPKeyPair.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GenerateQRCode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GenerateRSAKeyPair.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GenerateTOTP.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GenerateUUID.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GenericCodeBeautify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GetAllCasings.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GetTime.mjs create mode 100644 plugins/srktoolbox/src/core/operations/GroupIPAddresses.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Gunzip.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Gzip.mjs create mode 100644 plugins/srktoolbox/src/core/operations/HAS160.mjs create mode 100644 plugins/srktoolbox/src/core/operations/HASSHClientFingerprint.mjs create mode 100644 plugins/srktoolbox/src/core/operations/HASSHServerFingerprint.mjs create mode 100644 plugins/srktoolbox/src/core/operations/HMAC.mjs create mode 100644 plugins/srktoolbox/src/core/operations/HTMLToText.mjs create mode 100644 plugins/srktoolbox/src/core/operations/HTTPRequest.mjs create mode 100644 plugins/srktoolbox/src/core/operations/HammingDistance.mjs create mode 100644 plugins/srktoolbox/src/core/operations/HaversineDistance.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Head.mjs create mode 100644 plugins/srktoolbox/src/core/operations/HeatmapChart.mjs create mode 100644 plugins/srktoolbox/src/core/operations/HexDensityChart.mjs create mode 100644 plugins/srktoolbox/src/core/operations/HexToObjectIdentifier.mjs create mode 100644 plugins/srktoolbox/src/core/operations/HexToPEM.mjs create mode 100644 plugins/srktoolbox/src/core/operations/IPv6TransitionAddresses.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ImageBrightnessContrast.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ImageFilter.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ImageHueSaturationLightness.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ImageOpacity.mjs create mode 100644 plugins/srktoolbox/src/core/operations/IndexOfCoincidence.mjs create mode 100644 plugins/srktoolbox/src/core/operations/InvertImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JA3Fingerprint.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JA3SFingerprint.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JA4Fingerprint.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JA4ServerFingerprint.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JPathExpression.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JSONBeautify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JSONMinify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JSONToCSV.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JSONtoYAML.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JWKToPem.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JWTDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JWTSign.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JWTVerify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JavaScriptBeautify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JavaScriptMinify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/JavaScriptParser.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Jq.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Jsonata.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Jump.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Keccak.mjs create mode 100644 plugins/srktoolbox/src/core/operations/LMHash.mjs create mode 100644 plugins/srktoolbox/src/core/operations/LS47Decrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/LS47Encrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/LZ4Compress.mjs create mode 100644 plugins/srktoolbox/src/core/operations/LZ4Decompress.mjs create mode 100644 plugins/srktoolbox/src/core/operations/LZMACompress.mjs create mode 100644 plugins/srktoolbox/src/core/operations/LZMADecompress.mjs create mode 100644 plugins/srktoolbox/src/core/operations/LZNT1Decompress.mjs create mode 100644 plugins/srktoolbox/src/core/operations/LZStringCompress.mjs create mode 100644 plugins/srktoolbox/src/core/operations/LZStringDecompress.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Label.mjs create mode 100644 plugins/srktoolbox/src/core/operations/LevenshteinDistance.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Lorenz.mjs create mode 100644 plugins/srktoolbox/src/core/operations/LuhnChecksum.mjs create mode 100644 plugins/srktoolbox/src/core/operations/MD2.mjs create mode 100644 plugins/srktoolbox/src/core/operations/MD4.mjs create mode 100644 plugins/srktoolbox/src/core/operations/MD5.mjs create mode 100644 plugins/srktoolbox/src/core/operations/MD6.mjs create mode 100644 plugins/srktoolbox/src/core/operations/MIMEDecoding.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Magic.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Mean.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Median.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Merge.mjs create mode 100644 plugins/srktoolbox/src/core/operations/MicrosoftScriptDecoder.mjs create mode 100644 plugins/srktoolbox/src/core/operations/MultipleBombe.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Multiply.mjs create mode 100644 plugins/srktoolbox/src/core/operations/MurmurHash3.mjs create mode 100644 plugins/srktoolbox/src/core/operations/NOT.mjs create mode 100644 plugins/srktoolbox/src/core/operations/NTHash.mjs create mode 100644 plugins/srktoolbox/src/core/operations/NormaliseImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/NormaliseUnicode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Numberwang.mjs create mode 100644 plugins/srktoolbox/src/core/operations/OR.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ObjectIdentifierToHex.mjs create mode 100644 plugins/srktoolbox/src/core/operations/OffsetChecker.mjs create mode 100644 plugins/srktoolbox/src/core/operations/OpticalCharacterRecognition.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PEMToHex.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PEMToJWK.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PGPDecrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PGPDecryptAndVerify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PGPEncrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PGPEncryptAndSign.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PGPVerify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PHPDeserialize.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PHPSerialize.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PLISTViewer.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PadLines.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseASN1HexString.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseCSR.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseColourCode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseDateTime.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseIPRange.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseIPv4Header.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseIPv6Address.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseObjectIDTimestamp.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseQRCode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseSSHHostKey.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseTCP.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseTLSRecord.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseTLV.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseUDP.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseUNIXFilePermissions.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseURI.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseUserAgent.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseX509CRL.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ParseX509Certificate.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PlayMedia.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PowerSet.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ProtobufDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ProtobufEncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PseudoRandomNumberGenerator.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PubKeyFromCert.mjs create mode 100644 plugins/srktoolbox/src/core/operations/PubKeyFromPrivKey.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RAKE.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RC2Decrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RC2Encrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RC4.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RC4Drop.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RIPEMD.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ROT13.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ROT13BruteForce.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ROT47.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ROT47BruteForce.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ROT8000.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RSADecrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RSAEncrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RSASign.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RSAVerify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Rabbit.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RailFenceCipherDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RailFenceCipherEncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RandomizeColourPalette.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RawDeflate.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RawInflate.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Register.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RegularExpression.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RemoveDiacritics.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RemoveEXIF.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RemoveLineNumbers.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RemoveNullBytes.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RemoveWhitespace.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RenderImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RenderMarkdown.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ResizeImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Return.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Reverse.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RisonDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RisonEncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RoarCipherDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RoarCipherEncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RotateImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RotateLeft.mjs create mode 100644 plugins/srktoolbox/src/core/operations/RotateRight.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SHA0.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SHA1.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SHA2.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SHA3.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SIGABA.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SM2Decrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SM2Encrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SM3.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SM4Decrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SM4Encrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SQLBeautify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SQLMinify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SSDEEP.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SUB.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Salsa20.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ScanForEmbeddedFiles.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ScatterChart.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Scrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SeriesChart.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SetDifference.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SetIntersection.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SetUnion.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Shake.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SharpenImage.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ShowBase64Offsets.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ShowOnMap.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Shuffle.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Sleep.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Snefru.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Sort.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Split.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SplitColourChannels.mjs create mode 100644 plugins/srktoolbox/src/core/operations/StandardDeviation.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Streebog.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Strings.mjs create mode 100644 plugins/srktoolbox/src/core/operations/StripHTMLTags.mjs create mode 100644 plugins/srktoolbox/src/core/operations/StripHTTPHeaders.mjs create mode 100644 plugins/srktoolbox/src/core/operations/StripIPv4Header.mjs create mode 100644 plugins/srktoolbox/src/core/operations/StripTCPHeader.mjs create mode 100644 plugins/srktoolbox/src/core/operations/StripUDPHeader.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Subsection.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Substitute.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Subtract.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Sum.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SwapCase.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SwapEndianness.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SymmetricDifference.mjs create mode 100644 plugins/srktoolbox/src/core/operations/SyntaxHighlighter.mjs create mode 100644 plugins/srktoolbox/src/core/operations/TCPIPChecksum.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Tail.mjs create mode 100644 plugins/srktoolbox/src/core/operations/TakeBytes.mjs create mode 100644 plugins/srktoolbox/src/core/operations/TakeNthBytes.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Tar.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Template.mjs create mode 100644 plugins/srktoolbox/src/core/operations/TextEncodingBruteForce.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToBCD.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToBase.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToBase32.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToBase45.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToBase58.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToBase62.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToBase64.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToBase85.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToBase92.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToBech32.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToBinary.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToBraille.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToCNNumberUpperCase.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToCamelCase.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToCaseInsensitiveRegex.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToCharcode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToDecimal.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToFloat.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToHTMLEntity.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToHex.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToHexContent.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToHexdump.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToKebabCase.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToLowerCase.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToMessagePack.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToModhex.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToMorseCode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToOctal.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToPunycode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToQuotedPrintable.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToSnakeCase.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToTable.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToUNIXTimestamp.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ToUpperCase.mjs create mode 100644 plugins/srktoolbox/src/core/operations/TranslateDateTimeFormat.mjs create mode 100644 plugins/srktoolbox/src/core/operations/TripleDESDecrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/TripleDESEncrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Typex.mjs create mode 100644 plugins/srktoolbox/src/core/operations/UNIXTimestampToWindowsFiletime.mjs create mode 100644 plugins/srktoolbox/src/core/operations/URLDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/URLEncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/UnescapeString.mjs create mode 100644 plugins/srktoolbox/src/core/operations/UnescapeUnicodeCharacters.mjs create mode 100644 plugins/srktoolbox/src/core/operations/UnicodeTextFormat.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Unique.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Untar.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Unzip.mjs create mode 100644 plugins/srktoolbox/src/core/operations/VarIntDecode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/VarIntEncode.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ViewBitPlane.mjs create mode 100644 "plugins/srktoolbox/src/core/operations/Vigen\347\214\253reDecode.mjs" create mode 100644 "plugins/srktoolbox/src/core/operations/Vigen\347\214\253reEncode.mjs" create mode 100644 plugins/srktoolbox/src/core/operations/Whirlpool.mjs create mode 100644 plugins/srktoolbox/src/core/operations/WindowsFiletimeToUNIXTimestamp.mjs create mode 100644 plugins/srktoolbox/src/core/operations/XKCDRandomNumber.mjs create mode 100644 plugins/srktoolbox/src/core/operations/XMLBeautify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/XMLMinify.mjs create mode 100644 plugins/srktoolbox/src/core/operations/XOR.mjs create mode 100644 plugins/srktoolbox/src/core/operations/XORBruteForce.mjs create mode 100644 plugins/srktoolbox/src/core/operations/XORChecksum.mjs create mode 100644 plugins/srktoolbox/src/core/operations/XPathExpression.mjs create mode 100644 plugins/srktoolbox/src/core/operations/XSalsa20.mjs create mode 100644 plugins/srktoolbox/src/core/operations/XXTEADecrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/XXTEAEncrypt.mjs create mode 100644 plugins/srktoolbox/src/core/operations/YAMLToJSON.mjs create mode 100644 plugins/srktoolbox/src/core/operations/YARARules.mjs create mode 100644 plugins/srktoolbox/src/core/operations/Zip.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ZlibDeflate.mjs create mode 100644 plugins/srktoolbox/src/core/operations/ZlibInflate.mjs create mode 100644 plugins/srktoolbox/src/core/vendor/DisassembleX86-64.mjs create mode 100644 plugins/srktoolbox/src/core/vendor/gost/gostCipher.mjs create mode 100644 plugins/srktoolbox/src/core/vendor/gost/gostCoding.mjs create mode 100644 plugins/srktoolbox/src/core/vendor/gost/gostCrypto.mjs create mode 100644 plugins/srktoolbox/src/core/vendor/gost/gostDigest.mjs create mode 100644 plugins/srktoolbox/src/core/vendor/gost/gostEngine.mjs create mode 100644 plugins/srktoolbox/src/core/vendor/gost/gostRandom.mjs create mode 100644 plugins/srktoolbox/src/core/vendor/gost/gostSign.mjs create mode 100644 plugins/srktoolbox/src/core/vendor/remove-exif.mjs create mode 100644 plugins/srktoolbox/src/core/vendor/tesseract/lang-data/eng.traineddata.gz create mode 100644 plugins/srktoolbox/src/env.d.ts create mode 100644 plugins/srktoolbox/src/main.css create mode 100644 plugins/srktoolbox/src/main.ts create mode 100644 plugins/srktoolbox/src/node/File.mjs create mode 100644 plugins/srktoolbox/src/node/NodeDish.mjs create mode 100644 plugins/srktoolbox/src/node/NodeRecipe.mjs create mode 100644 plugins/srktoolbox/src/node/api.mjs create mode 100644 plugins/srktoolbox/src/node/apiUtils.mjs create mode 100644 plugins/srktoolbox/src/node/config/excludedOperations.mjs create mode 100644 plugins/srktoolbox/src/node/config/scripts/generateNodeIndex.mjs create mode 100644 plugins/srktoolbox/src/node/repl.mjs create mode 100644 plugins/srktoolbox/src/node/wrapper.js create mode 100644 plugins/srktoolbox/src/web/App.mjs create mode 100644 plugins/srktoolbox/src/web/HTMLCategory.mjs create mode 100644 plugins/srktoolbox/src/web/HTMLIngredient.mjs create mode 100644 plugins/srktoolbox/src/web/HTMLOperation.mjs create mode 100644 plugins/srktoolbox/src/web/Manager.mjs create mode 100644 plugins/srktoolbox/src/web/html/index.html create mode 100644 plugins/srktoolbox/src/web/index.js create mode 100644 plugins/srktoolbox/src/web/static/fonts/MaterialIcons-Regular.ttf create mode 100644 plugins/srktoolbox/src/web/static/fonts/bmfonts/Roboto72White.fnt create mode 100644 plugins/srktoolbox/src/web/static/fonts/bmfonts/Roboto72White.png create mode 100644 plugins/srktoolbox/src/web/static/fonts/bmfonts/RobotoBlack72White.fnt create mode 100644 plugins/srktoolbox/src/web/static/fonts/bmfonts/RobotoBlack72White.png create mode 100644 plugins/srktoolbox/src/web/static/fonts/bmfonts/RobotoMono72White.fnt create mode 100644 plugins/srktoolbox/src/web/static/fonts/bmfonts/RobotoMono72White.png create mode 100644 plugins/srktoolbox/src/web/static/fonts/bmfonts/RobotoSlab72White.fnt create mode 100644 plugins/srktoolbox/src/web/static/fonts/bmfonts/RobotoSlab72White.png create mode 100644 plugins/srktoolbox/src/web/static/ga.html create mode 100644 plugins/srktoolbox/src/web/static/images/IMAGE_LICENCES.md create mode 100644 plugins/srktoolbox/src/web/static/images/bombe.svg create mode 100644 plugins/srktoolbox/src/web/static/images/cook_female-32x32.png create mode 100644 plugins/srktoolbox/src/web/static/images/cook_male-32x32.png create mode 100644 plugins/srktoolbox/src/web/static/images/cyberchef-128x128.png create mode 100644 plugins/srktoolbox/src/web/static/images/cyberchef-256x256.png create mode 100644 plugins/srktoolbox/src/web/static/images/cyberchef-32x32.png create mode 100644 plugins/srktoolbox/src/web/static/images/cyberchef-512x512.png create mode 100644 plugins/srktoolbox/src/web/static/images/cyberchef-64x64.png create mode 100644 plugins/srktoolbox/src/web/static/images/favicon.ico create mode 100644 plugins/srktoolbox/src/web/static/images/favicon.ico.original create mode 100644 plugins/srktoolbox/src/web/static/images/file-128x128.png create mode 100644 plugins/srktoolbox/src/web/static/images/file-32x32.png create mode 100644 plugins/srktoolbox/src/web/static/images/fork_me.png create mode 100644 plugins/srktoolbox/src/web/static/images/gitter-badge.svg create mode 100644 plugins/srktoolbox/src/web/static/images/logo/cyberchef.svg create mode 100644 plugins/srktoolbox/src/web/static/images/logo/cyberchef_512.png create mode 100644 plugins/srktoolbox/src/web/static/images/logo/cyberchef_banner.svg create mode 100644 plugins/srktoolbox/src/web/static/images/logo/cyberchef_banner_1500.png create mode 100644 plugins/srktoolbox/src/web/static/images/logo/cyberchef_hat.svg create mode 100644 plugins/srktoolbox/src/web/static/images/logo/cyberchef_hat_512.png create mode 100644 plugins/srktoolbox/src/web/static/images/logo/cyberchef_hat_text_512.png create mode 100644 plugins/srktoolbox/src/web/static/images/logo/cyberchef_human.svg create mode 100644 plugins/srktoolbox/src/web/static/images/logo/cyberchef_robot.svg create mode 100644 plugins/srktoolbox/src/web/static/images/multitool-32x32.png create mode 100644 plugins/srktoolbox/src/web/static/images/rocket-1.svg create mode 100644 plugins/srktoolbox/src/web/static/images/srk-128x128.png create mode 100644 plugins/srktoolbox/src/web/static/images/srk-32x32.png create mode 100644 plugins/srktoolbox/src/web/static/sitemap.mjs create mode 100644 plugins/srktoolbox/src/web/static/structuredData.json create mode 100644 plugins/srktoolbox/src/web/stylesheets/components/_button.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/components/_list.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/components/_operation.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/components/_pane.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/index.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/index.js create mode 100644 plugins/srktoolbox/src/web/stylesheets/layout/_banner.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/layout/_controls.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/layout/_io.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/layout/_modals.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/layout/_operations.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/layout/_recipe.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/layout/_structure.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/operations/diff.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/operations/json.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/preloader.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/themes/_classic.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/themes/_dark.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/themes/_geocities.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/themes/_solarizedDark.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/themes/_solarizedLight.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/utils/_general.css create mode 100644 plugins/srktoolbox/src/web/stylesheets/utils/_overrides.css create mode 100644 plugins/srktoolbox/src/web/utils/copyOverride.mjs create mode 100644 plugins/srktoolbox/src/web/utils/editorUtils.mjs create mode 100644 plugins/srktoolbox/src/web/utils/fileDetails.mjs create mode 100644 plugins/srktoolbox/src/web/utils/htmlWidget.mjs create mode 100644 plugins/srktoolbox/src/web/utils/sidePanel.mjs create mode 100644 plugins/srktoolbox/src/web/utils/statusBar.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/BackgroundWorkerWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/BindingsWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/ControlsWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/HighlighterWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/InputWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/OperationsWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/OptionsWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/OutputWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/RecipeWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/SeasonalWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/TabWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/TimingWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/WindowWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/waiters/WorkerWaiter.mjs create mode 100644 plugins/srktoolbox/src/web/workers/DishWorker.mjs create mode 100644 plugins/srktoolbox/src/web/workers/InputWorker.mjs create mode 100644 plugins/srktoolbox/src/web/workers/LoaderWorker.js create mode 100644 plugins/srktoolbox/src/web/workers/ZipWorker.mjs create mode 100644 plugins/srktoolbox/tsconfig.json create mode 100644 plugins/srktoolbox/vite.config.js create mode 100644 plugins/srktoolbox/webpack.config.js diff --git a/plugins/srktoolbox/.cspell.json b/plugins/srktoolbox/.cspell.json new file mode 100644 index 00000000..66fca29b --- /dev/null +++ b/plugins/srktoolbox/.cspell.json @@ -0,0 +1,17 @@ +{ + "version": "0.2", + "language": "en,en-gb", + "words": [], + "dictionaries": [ + "npm", + "softwareTerms", + "node", + "html", + "css", + "bash", + "en-gb", + "misc" + ], + "ignorePaths": ["package.json", "package-lock.json", "node_modules"] + } + \ No newline at end of file diff --git a/plugins/srktoolbox/.dockerignore b/plugins/srktoolbox/.dockerignore new file mode 100644 index 00000000..10e91c8e --- /dev/null +++ b/plugins/srktoolbox/.dockerignore @@ -0,0 +1,6 @@ +build/prod/BundleAnalyzerReport.html +build/prod/SRK_Toolbox*.html +node_modules +.github +src +tests \ No newline at end of file diff --git a/plugins/srktoolbox/.editorconfig b/plugins/srktoolbox/.editorconfig new file mode 100644 index 00000000..cef4cab0 --- /dev/null +++ b/plugins/srktoolbox/.editorconfig @@ -0,0 +1,18 @@ +# top-most EditorConfig file +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 4 + +[{package.json,.travis.yml,nightwatch.json}] +indent_style = space +indent_size = 2 + +[.github/**.yml] +indent_style = space +indent_size = 2 diff --git a/plugins/srktoolbox/.gitattributes b/plugins/srktoolbox/.gitattributes new file mode 100644 index 00000000..6313b56c --- /dev/null +++ b/plugins/srktoolbox/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/plugins/srktoolbox/.gitignore b/plugins/srktoolbox/.gitignore new file mode 100644 index 00000000..42923f5d --- /dev/null +++ b/plugins/srktoolbox/.gitignore @@ -0,0 +1,15 @@ +node_modules +npm-debug.log +travis.log +build +.vscode +.idea +.*.swp +src/core/config/modules/* +src/core/config/OperationConfig.json +src/core/operations/index.mjs +src/node/config/OperationConfig.json +src/node/index.mjs +**/*.DS_Store +tests/browser/output/* +.node-version diff --git a/plugins/srktoolbox/.npmignore b/plugins/srktoolbox/.npmignore new file mode 100644 index 00000000..05ab5f52 --- /dev/null +++ b/plugins/srktoolbox/.npmignore @@ -0,0 +1,7 @@ +node_modules +npm-debug.log +travis.log +build/* +!build/node +.vscode +.github diff --git a/plugins/srktoolbox/.nvmrc b/plugins/srktoolbox/.nvmrc new file mode 100644 index 00000000..3c032078 --- /dev/null +++ b/plugins/srktoolbox/.nvmrc @@ -0,0 +1 @@ +18 diff --git a/plugins/srktoolbox/CHANGELOG.md b/plugins/srktoolbox/CHANGELOG.md new file mode 100644 index 00000000..960e922b --- /dev/null +++ b/plugins/srktoolbox/CHANGELOG.md @@ -0,0 +1,1013 @@ +# Changelog + +## Versioning + +CyberChef uses the [semver](https://semver.org/) system to manage versioning: `..`. + +- MAJOR version changes represent a significant change to the fundamental architecture of CyberChef and may (but don't always) make breaking changes that are not backwards compatible. +- MINOR version changes usually mean the addition of new operations or reasonably significant new features. +- PATCH versions are used for bug fixes and any other small tweaks that modify or improve existing capabilities. + +All major and minor version changes will be documented in this file. Details of patch-level version changes can be found in [commit messages](https://github.com/gchq/CyberChef/commits/master). + + +## Details + +### [10.22.0] - 2026-02-11 +- Separate npm publish out into separate job and run with Node 24.5 [@GCHQDeveloper581] | [#2188] +- Fixed Percent delimiter for hex encoding [@beneri] [@C85297] | [#2137] +- Added the ability to paste one or more Images from the Clipboard [@t-martine] [@a3957273] [@C85297] | [#1876] +- Quoted Printable - consistent reference to 'email' [@wesinator] | [#2186] +- Fix freeze when output text decoding fails [@Raka-loah] | [#1573] +- Update Browserslist DB [@C85297] | [#2183] +- Add contents write permission to releases workflow [@C85297] | [#2182] +- Fix release workflow permissions [@C85297] | [#2181] + +### [10.21.0] - 2026-02-05 +- Fix import operations with special chars in them [@d98762625] [@jg42526] | [#1040] +- Remove custom CodeQL workflow [@C85297] | [#2176] +- Fix code scanning warnings in workflows [@GCHQDeveloper581] | [#2177] +- Use NPM trusted publishing [@C85297] [@GCHQDeveloper581] | [#2174] +- Fix: Correctly parse xxd odd byte hexdumps [@ThomasNotTom] [@GCHQDeveloper581] | [#2058] +- Update Sitemap URLs to Use Valid Paths in sitemap.mjs [@rbpi] [@C85297] | [#1861] +- Use recommended GitHub Actions to build image [@AlexGustafsson] [@C85297] | [#2055] +- Remove version 10 message from banner [@C85297] | [#2169] +- Bump form-data from 4.0.1 to 4.0.5 | [#2175] +- Bump node-forge from 1.3.1 to 1.3.3 | [#2173] +- Update crypto browserify [@C85297] | [#2172] +- Update kbpgp package (resolves #2135) [@GCHQDeveloper581] | [#2136] +- Fix the processing of ALPNs for JA4 to align with new specification update [@tuliperis] | [#2165] +- Add Bech32 and Bech32m encoding/decoding operations [@thomasxm] | [#2159] +- Exclude Delete character from hex dump output [@mikecat] [@C85297] | [#2086] +- Tiny typo fix in "To Base85" operation [@twostraws] | [#2118] +- Bump jsonpath-plus [@C85297] | [#2166] + +### [10.20.0] - 2026-01-28 +- Fixed Optical Character Recognition and added tests [@n1474335] | [ab37c1e] +- Fixed JA4 version fallback value [@n1474335] | [7a5225c] +- Updated chromedriver [@n1474335] | [0e82e4b] +- Fixed RSA Sign and Verify character encodings [@n1474335] | [895a929] +- Updated chromedriver [@n1474335] | [d3adfc7] +- Added message format arg to RSA Verify operation [@n1474335] | [47c85a1] +- Add operation for parsing X.509 CRLs [@robinsandhu] | [#1887] +- Fix typo in description of JWT Sign recipe [@GuilhermoReadonly] | [#1961] +- Corrected path to generateNodeIndex.mjs [@simonarnell] | [#1959] +- Add 'header' ingredient to JWT Sign operation [@RandomByte] | [#1957] +- Add Parse TLS record operation [@c65722] | [#1936] +- Automatically detect chrome driver version [@gchq] | [#1972] +- Add Strip UDP header operation [@c65722] | [#1900] +- Add Strip TCP header operation [@c65722] | [#1898] +- Webpack compress with gzip and brotli [@max0x53] | [#1955] +- add offset field to 'Add Line Numbers' operation [@Adamkadaban] | [#1866] +- Disable flakey URL test [@a3957273] | [#1973] +- Add Strip IPv4 header operation [@c65722] | [#1899] +- IPv6 Transition Operation [@jb30795] | [#1780] +- fix: Blowfish - ignore IV length in ECB mode [@FranciscoPombal] | [#1902] +- Add 'Drop nth bytes' operation [@Oshawk] | [#1914] +- Add 'Take nth bytes' operation [@Oshawk] | [#1915] +- Add Leet Speak [@bartblaze] | [#1971] +- Fix Generate TOTP & HOPT [@exactlyaron] | [#1966] +- Updated luhn checksum operation to work with different bases [@k3ach] | [#1933] +- automatically theme mode based on user preference [@vs4vijay] | [#1921] +- fix: DES/Triple DES - misleading error messages [@FranciscoPombal] | [#1904] +- fix: ROT13 - shifting numbers by negative amounts [@FranciscoPombal] | [#1903] +- Introduce Yubico's Modhex for Conversion [@linuxgemini] | [#1105] +- Feature: MIME RFC2047 Decoding [@MShwed] | [#630] +- CC-1889 add _ option [@depperm] | [#1977] +- chore(root): add cspell [@evenstensberg] | [#1976] +- Preserve uppercase for Leet Speak [@bartblaze] | [#1981] +- Load the user's preferred color scheme if the URL contains an invalid theme [@0xh3xa] | [#2007] +- Add SM2 Encrypt and Decrypt Operations [@flakjacket95] | [#1909] +- Support jq as an operation. [@zhzy0077] | [#1604] +- Add fingerprints to the 'Parse X.509 certificate' operation [@JSCU-CNI] | [#1863] +- Added a JSON to YAML and a YAML to JSON operation [@ccarpo] | [#1286] +- Add CRC Operation [@r4mos] | [#1993] +- Bug Fix: selected theme not loading when refreshing [@0xh3xa] | [#2006] +- Fix(RecipeWaiter): sanitize user input in addOperation to prevent XSS [@0xh3xa] | [#2014] +- Docker multiplatform build support [@PathToLife] | [#1974] +- Add Base32 Hex Extended Alphabet and Base32 Tests. [@peterc-s] | [#1991] +- Add ECB/NoPadding and CBC/NoPadding support to AES encryption [@plvie] | [#2013] +- Add new operation: PHP Serialize [@brun0ne] | [#1548] +- Push input through postmessage [@kenduguay1] | [#1992] +- Add jsonata query operation [@jonking-ajar] | [#1587] +- Re-enable Npm Release in github workflows [@PathToLife] | [#2031] +- Add to ECDSA Verify the message format [@r4mos] | [#2027] +- Added alternating caps functionality [@sw5678] | [#1897] +- XOR Checksum operation added [@jg42526] | [#2035] +- Add GenerateAllChecksums operation * Remove checksums from GenerateAllHashes operation [@es45411] | [66d445c] +- Update GenerateAllChecksums infoURL [@es45411] | [#2037] +- Add toggle "+" character to URLDecode operation [@es45411] | [#2040] +- Workaround for Safari load bug [@GCHQDeveloper94872] | [#2038] +- Updated Dockerfile to correctly build on ARM64 platforms [@Sma-Das] | [#2042] +- Addresses bug report #2008 Added explicit support for octal IP addresses. Changed approach to IPv4 regex to be string manipulation generated. Added some unit tests for IP address parsing - probably not full coverage. Added lookahead and lookbehind tricks to resolve warned issue that 1.2.3.256 would still be extracted as 1.2.3.25. Now only accepts valid IP addresses. Warning replaced with clause about infinite length dotted decimal forms. [@gchqdev364] | [#2041] +- Remove trim from rail fence [@Odyhibit] | [#1986] +- Fix email regex [@ericli-splunk] | [#2025] +- Add Blake3 hashing [@xumptex] | [#2023] +- Use defaultIndex instead of 0 in transformArgs [@bartvanandel] | [#2015] +- Add "Generate UUID" and "Analyse UUID" operations [@bartvanandel] | [#2011] +- Add new operation: Template [@kendallgoto] | [#2021] +- Add more clear build instructions [@remingtr] | [#1873] +- Show On Map updated to use leaflet over WikiMedia [@0xff1ce] | [#1884] +- Fixed ToDecimal signed logic [@starplanet] | [#1545] +- Use BigInt for encoding/decoding VarInt [@mikecat] | [#1978] + +### [10.19.0] - 2024-06-21 +- Add support for ECDSA and DSA in 'Parse CSR' [@robinsandhu] | [#1828] +- Fix typos in SIGABA.mjs [@eltociear] | [#1834] + +### [10.18.0] - 2024-04-24 +- Added 'XXTEA Encrypt' and 'XXTEA Decrypt' operations [@n1474335] | [0a353ee] + +### [10.17.0] - 2024-04-13 +- Fix unit test 'expectOutput' implementation [@zb3] | [#1783] +- Add accessibility labels for icons [@e218736] | [#1743] +- Add focus styling for keyboard navigation [@e218736] | [#1739] +- Add support for operation option hiding [@TheZ3ro] | [#541] +- Improve efficiency of RAKE implementation [@sw5678] | [#1751] +- Require (a, 26) to be coprime in 'Affine Encode' [@EvieHarv] | [#1788] +- Added 'JWK to PEM' operation [@cplussharp] | [#1277] +- Added 'PEM to JWK' operation [@cplussharp] | [#1277] +- Added 'Public Key from Certificate' operation [@cplussharp] | [#1642] +- Added 'Public Key from Private Key' operation [@cplussharp] | [#1642] + +### [10.16.0] - 2024-04-12 +- Added 'JA4Server Fingerprint' operation [@n1474335] | [#1789] + +### [10.15.0] - 2024-04-02 +- Fix Ciphersaber2 key concatenation [@zb3] | [#1765] +- Fix DeriveEVPKey's array parsing [@zb3] | [#1767] +- Fix JWT operations [@a3957273] | [#1769] +- Added 'Parse Certificate Signing Request' operation [@jkataja] | [#1504] +- Added 'Extract Hash Values' operation [@MShwed] | [#512] +- Added 'DateTime Delta' operation [@tomgond] | [#1732] + +### [10.14.0] - 2024-03-31 +- Added 'To Float' and 'From Float' operations [@tcode2k16] | [#1762] +- Fix ChaCha raw export option [@joostrijneveld] | [#1606] +- Update x86 disassembler vendor library [@evanreichard] | [#1197] +- Allow variable Blowfish key sizes [@cbeuw] | [#933] +- Added 'XXTEA' operation [@devcydo] | [#1361] + +### [10.13.0] - 2024-03-30 +- Added 'FangURL' operation [@breakersall] [@arnydo] | [#1591] [#654] + +### [10.12.0] - 2024-03-29 +- Added 'Salsa20' and 'XSalsa20' operation [@joostrijneveld] | [#1750] + +### [10.11.0] - 2024-03-29 +- Add HEIC/HEIF file signatures [@simonw] | [#1757] +- Update xmldom to fix medium security vulnerability [@chriswhite199] | [#1752] +- Update JSONWebToken to fix medium security vulnerability [@chriswhite199] | [#1753] + +### [10.10.0] - 2024-03-27 +- Added 'JA4 Fingerprint' operation [@n1474335] | [#1759] + +### [10.9.0] - 2024-03-26 +- Line ending sequences and UTF-8 character encoding are now detected automatically [@n1474335] | [65ffd8d] + +### [10.8.0] - 2024-02-13 +- Add official Docker images [@AshCorr] | [#1699] + +### [10.7.0] - 2024-02-09 +- Added 'File Tree' operation [@sw5678] | [#1667] +- Added 'RISON' operation [@sg5506844] | [#1555] +- Added 'MurmurHash3' operation [@AliceGrey] | [#1694] + +### [10.6.0] - 2024-02-03 +- Updated 'Forensics Wiki' URLs to new domain [@a3957273] | [#1703] +- Added 'LZNT1 Decompress' operation [@0xThiebaut] | [#1675] +- Updated 'Regex Expression' UUID matcher [@cnotin] | [#1678] +- Removed duplicate 'hover' message within baking info [@KevinSJ] | [#1541] + +### [10.5.0] - 2023-07-14 +- Added GOST Encrypt, Decrypt, Sign, Verify, Key Wrap, and Key Unwrap operations [@n1474335] | [#592] + +### [10.4.0] - 2023-03-24 +- Added 'Generate De Bruijn Sequence' operation [@gchq77703] | [#493] + +### [10.3.0] - 2023-03-24 +- Added 'Argon2' and 'Argon2 compare' operations [@Xenonym] | [#661] + +### [10.2.0] - 2023-03-23 +- Added 'Derive HKDF key' operation [@mikecat] | [#1528] + +### [10.1.0] - 2023-03-23 +- Added 'Levenshtein Distance' operation [@mikecat] | [#1498] +- Added 'Swap case' operation [@mikecat] | [#1499] + +## [10.0.0] - 2023-03-22 +- [Full details explained here](https://github.com/gchq/CyberChef/wiki/Character-encoding,-EOL-separators,-and-editor-features) +- Status bars added to the Input and Output [@n1474335] | [#1405] +- Character encoding selection added to the Input and Output [@n1474335] | [#1405] +- End of line separator selection added to the Input and Output [@n1474335] | [#1405] +- Non-printable characters are rendered as control character pictures [@n1474335] | [#1405] +- Loaded files can now be edited in the Input [@n1474335] | [#1405] +- Various editor features added such as multiple selections and bracket matching [@n1474335] | [#1405] +- Contextual help added, activated by pressing F1 while hovering over features [@n1474335] | [#1405] +- Many, many UI tests added for I/O features and operations [@n1474335] | [#1405] + +
+ Click to expand v9 minor versions + +### [9.55.0] - 2022-12-09 +- Added 'AMF Encode' and 'AMF Decode' operations [@n1474335] | [760eff4] + +### [9.54.0] - 2022-11-25 +- Added 'Rabbit' operation [@mikecat] | [#1450] + +### [9.53.0] - 2022-11-25 +- Added 'AES Key Wrap' and 'AES Key Unwrap' operations [@mikecat] | [#1456] + +### [9.52.0] - 2022-11-25 +- Added 'ChaCha' operation [@joostrijneveld] | [#1466] + +### [9.51.0] - 2022-11-25 +- Added 'CMAC' operation [@mikecat] | [#1457] + +### [9.50.0] - 2022-11-25 +- Added 'Shuffle' operation [@mikecat] | [#1472] + +### [9.49.0] - 2022-11-11 +- Added 'LZ4 Compress' and 'LZ4 Decompress' operations [@n1474335] | [31a7f83] + +### [9.48.0] - 2022-10-14 +- Added 'LM Hash' and 'NT Hash' operations [@n1474335] [@brun0ne] | [#1427] + +### [9.47.0] - 2022-10-14 +- Added 'LZMA Decompress' and 'LZMA Compress' operations [@mattnotmitt] | [#1421] + +### [9.46.0] - 2022-07-08 +- Added 'Cetacean Cipher Encode' and 'Cetacean Cipher Decode' operations [@valdelaseras] | [#1308] + +### [9.45.0] - 2022-07-08 +- Added 'ROT8000' operation [@thomasleplus] | [#1250] + +### [9.44.0] - 2022-07-08 +- Added 'LZString Compress' and 'LZString Decompress' operations [@crespyl] | [#1266] + +### [9.43.0] - 2022-07-08 +- Added 'ROT13 Brute Force' and 'ROT47 Brute Force' operations [@mikecat] | [#1264] + +### [9.42.0] - 2022-07-08 +- Added 'LS47 Encrypt' and 'LS47 Decrypt' operations [@n1073645] | [#951] + +### [9.41.0] - 2022-07-08 +- Added 'Caesar Box Cipher' operation [@n1073645] | [#1066] + +### [9.40.0] - 2022-07-08 +- Added 'P-list Viewer' operation [@n1073645] | [#906] + +### [9.39.0] - 2022-06-09 +- Added 'ELF Info' operation [@n1073645] | [#1364] + +### [9.38.0] - 2022-05-30 +- Added 'Parse TCP' operation [@n1474335] | [a895d1d] + +### [9.37.0] - 2022-03-29 +- 'SM4 Encrypt' and 'SM4 Decrypt' operations added [@swesven] | [#1189] +- NoPadding options added for CBC and ECB modes in AES, DES and Triple DES Decrypt operations [@swesven] | [#1189] + +### [9.36.0] - 2022-03-29 +- 'SIGABA' operation added [@hettysymes] | [#934] + +### [9.35.0] - 2022-03-28 +- 'To Base45' and 'From Base45' operations added [@t-8ch] | [#1242] + +### [9.34.0] - 2022-03-28 +- 'Get All Casings' operation added [@n1073645] | [#1065] + +### [9.33.0] - 2022-03-25 +- Updated to support Node 17 [@n1474335] [@john19696] [@t-8ch] | [[#1326] [#1313] [#1244] +- Improved CJS and ESM module support [@d98762625] | [#1037] + +### [9.32.0] - 2021-08-18 +- 'Protobuf Encode' operation added and decode operation modified to allow decoding with full and partial schemas [@n1474335] | [dd18e52] + +### [9.31.0] - 2021-08-10 +- 'HASSH Client Fingerprint' and 'HASSH Server Fingerprint' operations added [@n1474335] | [e9ca4dc] + +### [9.30.0] - 2021-08-10 +- 'JA3S Fingerprint' operation added [@n1474335] | [289a417] + +### [9.29.0] - 2021-07-28 +- 'JA3 Fingerprint' operation added [@n1474335] | [9a33498] + +### [9.28.0] - 2021-03-26 +- 'CBOR Encode' and 'CBOR Decode' operations added [@Danh4] | [#999] + +### [9.27.0] - 2021-02-12 +- 'Fuzzy Match' operation added [@n1474335] | [8ad18b] + +### [9.26.0] - 2021-02-11 +- 'Get Time' operation added [@n1073645] [@n1474335] | [#1045] + +### [9.25.0] - 2021-02-11 +- 'Extract ID3' operation added [@n1073645] [@n1474335] | [#1006] + +### [9.24.0] - 2021-02-02 +- 'SM3' hashing function added along with more configuration options for other hashing operations [@n1073645] [@n1474335] | [#1022] + +### [9.23.0] - 2021-02-01 +- Various RSA operations added to encrypt, decrypt, sign, verify and generate keys [@mattnotmitt] [@GCHQ77703] | [#652] + +### [9.22.0] - 2021-02-01 +- 'Unicode Text Format' operation added [@mattnotmitt] | [#1083] + +### [9.21.0] - 2020-06-12 +- Node API now exports `magic` operation [@d98762625] | [#1049] + +### [9.20.0] - 2020-03-27 +- 'Parse ObjectID Timestamp' operation added [@dmfj] | [#987] + +### [9.19.0] - 2020-03-24 +- Improvements to the 'Magic' operation, allowing it to recognise more data formats and provide more accurate results [@n1073645] [@n1474335] | [#966] [b765534b](https://github.com/gchq/CyberChef/commit/b765534b8b2a0454a5132a0a52d1d8844bcbdaaa) + +### [9.18.0] - 2020-03-13 +- 'Convert to NATO alphabet' operation added [@MarvinJWendt] | [#674] + +### [9.17.0] - 2020-03-13 +- 'Generate Image' operation added [@pointhi] | [#683] + +### [9.16.0] - 2020-03-06 +- 'Colossus' operation added [@VirtualColossus] | [#917] + +### [9.15.0] - 2020-03-05 +- 'CipherSaber2 Encrypt' and 'CipherSaber2 Decrypt' operations added [@n1073645] | [#952] + +### [9.14.0] - 2020-03-05 +- 'Luhn Checksum' operation added [@n1073645] | [#965] + +### [9.13.0] - 2020-02-13 +- 'Rail Fence Cipher Encode' and 'Rail Fence Cipher Decode' operations added [@Flavsditz] | [#948] + +### [9.12.0] - 2019-12-20 +- 'Normalise Unicode' operation added [@matthieuxyz] | [#912] + +### [9.11.0] - 2019-11-06 +- Implemented CFB, OFB, and CTR modes for Blowfish operations [@cbeuw] | [#653] + +### [9.10.0] - 2019-11-06 +- 'Lorenz' operation added [@VirtualColossus] | [#528] + +### [9.9.0] - 2019-11-01 +- Added support for 109 more character encodings [@n1474335] + +### [9.8.0] - 2019-10-31 +- 'Avro to JSON' operation added [@jarrodconnolly] | [#865] + +### [9.7.0] - 2019-09-13 +- 'Optical Character Recognition' operation added [@MShwed] [@n1474335] | [#632] + +### [9.6.0] - 2019-09-04 +- 'Bacon Cipher Encode' and 'Bacon Cipher Decode' operations added [@kassi] | [#500] + +### [9.5.0] - 2019-09-04 +- Various Steganography operations added: 'Extract LSB', 'Extract RGBA', 'Randomize Colour Palette', and 'View Bit Plane' [@Ge0rg3] | [#625] + +### [9.4.0] - 2019-08-30 +- 'Render Markdown' operation added [@j433866] | [#627] + +### [9.3.0] - 2019-08-30 +- 'Show on map' operation added [@j433866] | [#477] + +### [9.2.0] - 2019-08-23 +- 'Parse UDP' operation added [@h345983745] | [#614] + +### [9.1.0] - 2019-08-22 +- 'Parse SSH Host Key' operation added [@j433866] | [#595] +- 'Defang IP Addresses' operation added [@h345983745] | [#556] + +
+ +## [9.0.0] - 2019-07-09 +- [Multiple inputs](https://github.com/gchq/CyberChef/wiki/Multiple-Inputs) are now supported in the main web UI, allowing you to upload and process multiple files at once [@j433866] | [#566] +- A [Node.js API](https://github.com/gchq/CyberChef/wiki/Node-API) has been implemented, meaning that CyberChef can now be used as a library, either to provide specific operations, or an entire baking environment [@d98762625] | [#291] +- A [read-eval-print loop (REPL)](https://github.com/gchq/CyberChef/wiki/Node-API#repl) is also included to enable prototyping and experimentation with the API [@d98762625] | [#291] +- Light and dark Solarized themes added [@j433866] | [#566] + +
+ Click to expand v8 minor versions + +### [8.38.0] - 2019-07-03 +- 'Streebog' and 'GOST hash' operations added [@MShwed] [@n1474335] | [#530] + +### [8.37.0] - 2019-07-03 +- 'CRC-8 Checksum' operation added [@MShwed] | [#591] + +### [8.36.0] - 2019-07-03 +- 'PGP Verify' operation added [@artemisbot] | [#585] + +### [8.35.0] - 2019-07-03 +- 'Sharpen Image', 'Convert Image Format' and 'Add Text To Image' operations added [@j433866] | [#515] + +### [8.34.0] - 2019-06-28 +- Various new visualisations added to the 'Entropy' operation [@MShwed] | [#535] +- Efficiency improvements made to the 'Entropy' operation for large file support [@n1474335] + +### [8.33.0] - 2019-06-27 +- 'Bzip2 Compress' operation added and 'Bzip2 Decompress' operation greatly improved [@artemisbot] | [#531] + +### [8.32.0] - 2019-06-27 +- 'Index of Coincidence' operation added [@Ge0rg3] | [#571] + +### [8.31.0] - 2019-04-12 +- The downloadable version of CyberChef is now a .zip file containing separate modules rather than a single .htm file. It is still completely standalone and will not make any external network requests. This change reduces the complexity of the build process significantly. [@n1474335] + +### [8.30.0] - 2019-04-12 +- 'Decode Protobuf' operation added [@n1474335] | [#533] + +### [8.29.0] - 2019-03-31 +- 'BLAKE2s' and 'BLAKE2b' hashing operations added [@h345983745] | [#525] + +### [8.28.0] - 2019-03-31 +- 'Heatmap Chart', 'Hex Density Chart', 'Scatter Chart' and 'Series Chart' operation added [@artemisbot] [@tlwr] | [#496] [#143] + +### [8.27.0] - 2019-03-14 +- 'Enigma', 'Typex', 'Bombe' and 'Multiple Bombe' operations added [@s2224834] | [#516] +- See [this wiki article](https://github.com/gchq/CyberChef/wiki/Enigma,-the-Bombe,-and-Typex) for a full explanation of these operations. +- New Bombe-style loading animation added for long-running operations [@n1474335] +- New operation argument types added: `populateMultiOption` and `argSelector` [@n1474335] + +### [8.26.0] - 2019-03-09 +- Various image manipulation operations added [@j433866] | [#506] + +### [8.25.0] - 2019-03-09 +- 'Extract Files' operation added and more file formats supported [@n1474335] | [#440] + +### [8.24.0] - 2019-02-08 +- 'DNS over HTTPS' operation added [@h345983745] | [#489] + +### [8.23.1] - 2019-01-18 +- 'Convert co-ordinate format' operation added [@j433866] | [#476] + +### [8.23.0] - 2019-01-18 +- 'YARA Rules' operation added [@artemisbot] | [#468] + +### [8.22.0] - 2019-01-10 +- 'Subsection' operation added [@j433866] | [#467] + +### [8.21.0] - 2019-01-10 +- 'To Case Insensitive Regex' and 'From Case Insensitive Regex' operations added [@masq] | [#461] + +### [8.20.0] - 2019-01-09 +- 'Generate Lorem Ipsum' operation added [@klaxon1] | [#455] + +### [8.19.0] - 2018-12-30 +- UI test suite added to confirm that the app loads correctly in a reasonable time and that various operations from each module can be run [@n1474335] | [#458] + +### [8.18.0] - 2018-12-26 +- 'Split Colour Channels' operation added [@artemisbot] | [#449] + +### [8.17.0] - 2018-12-25 +- 'Generate QR Code' and 'Parse QR Code' operations added [@j433866] | [#448] + +### [8.16.0] - 2018-12-19 +- 'Play Media' operation added [@anthony-arnold] | [#446] + +### [8.15.0] - 2018-12-18 +- 'Text Encoding Brute Force' operation added [@Cynser] | [#439] + +### [8.14.0] - 2018-12-18 +- 'To Base62' and 'From Base62' operations added [@tcode2k16] | [#443] + +### [8.13.0] - 2018-12-15 +- 'A1Z26 Cipher Encode' and 'A1Z26 Cipher Decode' operations added [@jarmovanlenthe] | [#441] + +### [8.12.0] - 2018-11-21 +- 'Citrix CTX1 Encode' and 'Citrix CTX1 Decode' operations added [@bwhitn] | [#428] + +### [8.11.0] - 2018-11-13 +- 'CSV to JSON' and 'JSON to CSV' operations added [@n1474335] | [#277] + +### [8.10.0] - 2018-11-07 +- 'Remove Diacritics' operation added [@klaxon1] | [#387] + +### [8.9.0] - 2018-11-07 +- 'Defang URL' operation added [@arnydo] | [#394] + +### [8.8.0] - 2018-10-10 +- 'Parse TLV' operation added [@GCHQ77703] | [#351] + +### [8.7.0] - 2018-08-31 +- 'JWT Sign', 'JWT Verify' and 'JWT Decode' operations added [@GCHQ77703] | [#348] + +### [8.6.0] - 2018-08-29 +- 'To Geohash' and 'From Geohash' operations added [@GCHQ77703] | [#344] + +### [8.5.0] - 2018-08-23 +- 'To Braille' and 'From Braille' operations added [@n1474335] | [#255] + +### [8.4.0] - 2018-08-23 +- 'To Base85' and 'From Base85' operations added [@PenguinGeorge] | [#340] + +### [8.3.0] - 2018-08-21 +- 'To MessagePack' and 'From MessagePack' operations added [@artemisbot] | [#338] + +### [8.2.0] - 2018-08-21 +- Information links added to most operations, accessible in the description popover [@PenguinGeorge] | [#298] + +### [8.1.0] - 2018-08-19 +- 'Dechunk HTTP response' operation added [@sevzero] | [#311] + +
+ +## [8.0.0] - 2018-08-05 +- Codebase rewritten using [ES modules](https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/) and [classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) [@n1474335] [@d98762625] [@artemisbot] [@picapi] | [#284] +- Operation architecture restructured to make adding new operations a lot simpler [@n1474335] | [#284] +- A script has been added to aid in the creation of new operations by running `npm run newop` [@n1474335] | [#284] +- 'Magic' operation added - [automated detection of encoded data](https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic) [@n1474335] | [#239] +- UI updated to use [Bootstrap Material Design](https://fezvrasta.github.io/bootstrap-material-design/) [@n1474335] | [#248] +- `JSON`, `File` and `List` Dish types added [@n1474335] | [#284] +- `OperationError` type added for better handling of errors thrown by operations [@d98762625] | [#296] +- A `present()` method has been added, allowing operations to pass machine-friendly data to subsequent operations whilst presenting human-friendly data to the user [@n1474335] | [#284] +- Set operations added [@d98762625] | [#281] +- 'To Table' operation added [@JustAnotherMark] | [#294] +- 'Haversine distance' operation added [@Dachande663] | [#325] +- Started keeping a changelog [@n1474335] + +## [7.0.0] - 2017-12-28 +- Added support for loading, processing and downloading files up to 500MB [@n1474335] | [#224] + +## [6.0.0] - 2017-09-19 +- Threading support added. All recipe processing moved into a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) to increase performance and to allow long-running operations to be cancelled [@n1474335] | [#173] +- Module system created so that operations relying on large libraries can be downloaded separately as required, reducing the initial loading time for the app [@n1474335] | [#173] + +## [5.0.0] - 2017-03-30 +- Webpack build process configured with Babel transpilation and ES6 imports and exports [@n1474335] | [#95] + +## [4.0.0] - 2016-11-28 +- Initial open source commit [@n1474335] | [b1d73a72](https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306) + +[10.22.0]: https://github.com/gchq/CyberChef/releases/tag/v10.22.0 +[10.21.0]: https://github.com/gchq/CyberChef/releases/tag/v10.21.0 +[10.20.0]: https://github.com/gchq/CyberChef/releases/tag/v10.20.0 +[10.19.0]: https://github.com/gchq/CyberChef/releases/tag/v10.19.0 +[10.18.0]: https://github.com/gchq/CyberChef/releases/tag/v10.18.0 +[10.17.0]: https://github.com/gchq/CyberChef/releases/tag/v10.17.0 +[10.16.0]: https://github.com/gchq/CyberChef/releases/tag/v10.16.0 +[10.15.0]: https://github.com/gchq/CyberChef/releases/tag/v10.15.0 +[10.14.0]: https://github.com/gchq/CyberChef/releases/tag/v10.14.0 +[10.13.0]: https://github.com/gchq/CyberChef/releases/tag/v10.13.0 +[10.12.0]: https://github.com/gchq/CyberChef/releases/tag/v10.12.0 +[10.11.0]: https://github.com/gchq/CyberChef/releases/tag/v10.11.0 +[10.10.0]: https://github.com/gchq/CyberChef/releases/tag/v10.10.0 +[10.9.0]: https://github.com/gchq/CyberChef/releases/tag/v10.9.0 +[10.8.0]: https://github.com/gchq/CyberChef/releases/tag/v10.7.0 +[10.7.0]: https://github.com/gchq/CyberChef/releases/tag/v10.7.0 +[10.6.0]: https://github.com/gchq/CyberChef/releases/tag/v10.6.0 +[10.5.0]: https://github.com/gchq/CyberChef/releases/tag/v10.5.0 +[10.4.0]: https://github.com/gchq/CyberChef/releases/tag/v10.4.0 +[10.3.0]: https://github.com/gchq/CyberChef/releases/tag/v10.3.0 +[10.2.0]: https://github.com/gchq/CyberChef/releases/tag/v10.2.0 +[10.1.0]: https://github.com/gchq/CyberChef/releases/tag/v10.1.0 +[10.0.0]: https://github.com/gchq/CyberChef/releases/tag/v10.0.0 +[9.55.0]: https://github.com/gchq/CyberChef/releases/tag/v9.55.0 +[9.54.0]: https://github.com/gchq/CyberChef/releases/tag/v9.54.0 +[9.53.0]: https://github.com/gchq/CyberChef/releases/tag/v9.53.0 +[9.52.0]: https://github.com/gchq/CyberChef/releases/tag/v9.52.0 +[9.51.0]: https://github.com/gchq/CyberChef/releases/tag/v9.51.0 +[9.50.0]: https://github.com/gchq/CyberChef/releases/tag/v9.50.0 +[9.49.0]: https://github.com/gchq/CyberChef/releases/tag/v9.49.0 +[9.48.0]: https://github.com/gchq/CyberChef/releases/tag/v9.48.0 +[9.47.0]: https://github.com/gchq/CyberChef/releases/tag/v9.47.0 +[9.46.0]: https://github.com/gchq/CyberChef/releases/tag/v9.46.0 +[9.45.0]: https://github.com/gchq/CyberChef/releases/tag/v9.45.0 +[9.44.0]: https://github.com/gchq/CyberChef/releases/tag/v9.44.0 +[9.43.0]: https://github.com/gchq/CyberChef/releases/tag/v9.43.0 +[9.42.0]: https://github.com/gchq/CyberChef/releases/tag/v9.42.0 +[9.41.0]: https://github.com/gchq/CyberChef/releases/tag/v9.41.0 +[9.40.0]: https://github.com/gchq/CyberChef/releases/tag/v9.40.0 +[9.39.0]: https://github.com/gchq/CyberChef/releases/tag/v9.39.0 +[9.38.0]: https://github.com/gchq/CyberChef/releases/tag/v9.38.0 +[9.37.0]: https://github.com/gchq/CyberChef/releases/tag/v9.37.0 +[9.36.0]: https://github.com/gchq/CyberChef/releases/tag/v9.36.0 +[9.35.0]: https://github.com/gchq/CyberChef/releases/tag/v9.35.0 +[9.34.0]: https://github.com/gchq/CyberChef/releases/tag/v9.34.0 +[9.33.0]: https://github.com/gchq/CyberChef/releases/tag/v9.33.0 +[9.32.0]: https://github.com/gchq/CyberChef/releases/tag/v9.32.0 +[9.31.0]: https://github.com/gchq/CyberChef/releases/tag/v9.31.0 +[9.30.0]: https://github.com/gchq/CyberChef/releases/tag/v9.30.0 +[9.29.0]: https://github.com/gchq/CyberChef/releases/tag/v9.29.0 +[9.28.0]: https://github.com/gchq/CyberChef/releases/tag/v9.28.0 +[9.27.0]: https://github.com/gchq/CyberChef/releases/tag/v9.27.0 +[9.26.0]: https://github.com/gchq/CyberChef/releases/tag/v9.26.0 +[9.25.0]: https://github.com/gchq/CyberChef/releases/tag/v9.25.0 +[9.24.0]: https://github.com/gchq/CyberChef/releases/tag/v9.24.0 +[9.23.0]: https://github.com/gchq/CyberChef/releases/tag/v9.23.0 +[9.22.0]: https://github.com/gchq/CyberChef/releases/tag/v9.22.0 +[9.21.0]: https://github.com/gchq/CyberChef/releases/tag/v9.21.0 +[9.20.0]: https://github.com/gchq/CyberChef/releases/tag/v9.20.0 +[9.19.0]: https://github.com/gchq/CyberChef/releases/tag/v9.19.0 +[9.18.0]: https://github.com/gchq/CyberChef/releases/tag/v9.18.0 +[9.17.0]: https://github.com/gchq/CyberChef/releases/tag/v9.17.0 +[9.16.0]: https://github.com/gchq/CyberChef/releases/tag/v9.16.0 +[9.15.0]: https://github.com/gchq/CyberChef/releases/tag/v9.15.0 +[9.14.0]: https://github.com/gchq/CyberChef/releases/tag/v9.14.0 +[9.13.0]: https://github.com/gchq/CyberChef/releases/tag/v9.13.0 +[9.12.0]: https://github.com/gchq/CyberChef/releases/tag/v9.12.0 +[9.11.0]: https://github.com/gchq/CyberChef/releases/tag/v9.11.0 +[9.10.0]: https://github.com/gchq/CyberChef/releases/tag/v9.10.0 +[9.9.0]: https://github.com/gchq/CyberChef/releases/tag/v9.9.0 +[9.8.0]: https://github.com/gchq/CyberChef/releases/tag/v9.8.0 +[9.7.0]: https://github.com/gchq/CyberChef/releases/tag/v9.7.0 +[9.6.0]: https://github.com/gchq/CyberChef/releases/tag/v9.6.0 +[9.5.0]: https://github.com/gchq/CyberChef/releases/tag/v9.5.0 +[9.4.0]: https://github.com/gchq/CyberChef/releases/tag/v9.4.0 +[9.3.0]: https://github.com/gchq/CyberChef/releases/tag/v9.3.0 +[9.2.0]: https://github.com/gchq/CyberChef/releases/tag/v9.2.0 +[9.1.0]: https://github.com/gchq/CyberChef/releases/tag/v9.1.0 +[9.0.0]: https://github.com/gchq/CyberChef/releases/tag/v9.0.0 +[8.38.0]: https://github.com/gchq/CyberChef/releases/tag/v8.38.0 +[8.37.0]: https://github.com/gchq/CyberChef/releases/tag/v8.37.0 +[8.36.0]: https://github.com/gchq/CyberChef/releases/tag/v8.36.0 +[8.35.0]: https://github.com/gchq/CyberChef/releases/tag/v8.35.0 +[8.34.0]: https://github.com/gchq/CyberChef/releases/tag/v8.34.0 +[8.33.0]: https://github.com/gchq/CyberChef/releases/tag/v8.33.0 +[8.32.0]: https://github.com/gchq/CyberChef/releases/tag/v8.32.0 +[8.31.0]: https://github.com/gchq/CyberChef/releases/tag/v8.31.0 +[8.30.0]: https://github.com/gchq/CyberChef/releases/tag/v8.30.0 +[8.29.0]: https://github.com/gchq/CyberChef/releases/tag/v8.29.0 +[8.28.0]: https://github.com/gchq/CyberChef/releases/tag/v8.28.0 +[8.27.0]: https://github.com/gchq/CyberChef/releases/tag/v8.27.0 +[8.26.0]: https://github.com/gchq/CyberChef/releases/tag/v8.26.0 +[8.25.0]: https://github.com/gchq/CyberChef/releases/tag/v8.25.0 +[8.24.0]: https://github.com/gchq/CyberChef/releases/tag/v8.24.0 +[8.23.1]: https://github.com/gchq/CyberChef/releases/tag/v8.23.1 +[8.23.0]: https://github.com/gchq/CyberChef/releases/tag/v8.23.0 +[8.22.0]: https://github.com/gchq/CyberChef/releases/tag/v8.22.0 +[8.21.0]: https://github.com/gchq/CyberChef/releases/tag/v8.21.0 +[8.20.0]: https://github.com/gchq/CyberChef/releases/tag/v8.20.0 +[8.19.0]: https://github.com/gchq/CyberChef/releases/tag/v8.19.0 +[8.18.0]: https://github.com/gchq/CyberChef/releases/tag/v8.18.0 +[8.17.0]: https://github.com/gchq/CyberChef/releases/tag/v8.17.0 +[8.16.0]: https://github.com/gchq/CyberChef/releases/tag/v8.16.0 +[8.15.0]: https://github.com/gchq/CyberChef/releases/tag/v8.15.0 +[8.14.0]: https://github.com/gchq/CyberChef/releases/tag/v8.14.0 +[8.13.0]: https://github.com/gchq/CyberChef/releases/tag/v8.13.0 +[8.12.0]: https://github.com/gchq/CyberChef/releases/tag/v8.12.0 +[8.11.0]: https://github.com/gchq/CyberChef/releases/tag/v8.11.0 +[8.10.0]: https://github.com/gchq/CyberChef/releases/tag/v8.10.0 +[8.9.0]: https://github.com/gchq/CyberChef/releases/tag/v8.9.0 +[8.8.0]: https://github.com/gchq/CyberChef/releases/tag/v8.8.0 +[8.7.0]: https://github.com/gchq/CyberChef/releases/tag/v8.7.0 +[8.6.0]: https://github.com/gchq/CyberChef/releases/tag/v8.6.0 +[8.5.0]: https://github.com/gchq/CyberChef/releases/tag/v8.5.0 +[8.4.0]: https://github.com/gchq/CyberChef/releases/tag/v8.4.0 +[8.3.0]: https://github.com/gchq/CyberChef/releases/tag/v8.3.0 +[8.2.0]: https://github.com/gchq/CyberChef/releases/tag/v8.2.0 +[8.1.0]: https://github.com/gchq/CyberChef/releases/tag/v8.1.0 +[8.0.0]: https://github.com/gchq/CyberChef/releases/tag/v8.0.0 +[7.0.0]: https://github.com/gchq/CyberChef/releases/tag/v7.0.0 +[6.0.0]: https://github.com/gchq/CyberChef/releases/tag/v6.0.0 +[5.0.0]: https://github.com/gchq/CyberChef/releases/tag/v5.0.0 +[4.0.0]: https://github.com/gchq/CyberChef/commit/b1d73a725dc7ab9fb7eb789296efd2b7e4b08306 + +[@n1474335]: https://github.com/n1474335 +[@d98762625]: https://github.com/d98762625 +[@j433866]: https://github.com/j433866 +[@n1073645]: https://github.com/n1073645 +[@GCHQ77703]: https://github.com/GCHQ77703 +[@h345983745]: https://github.com/h345983745 +[@s2224834]: https://github.com/s2224834 +[@artemisbot]: https://github.com/artemisbot +[@tlwr]: https://github.com/tlwr +[@picapi]: https://github.com/picapi +[@Dachande663]: https://github.com/Dachande663 +[@JustAnotherMark]: https://github.com/JustAnotherMark +[@sevzero]: https://github.com/sevzero +[@PenguinGeorge]: https://github.com/PenguinGeorge +[@arnydo]: https://github.com/arnydo +[@klaxon1]: https://github.com/klaxon1 +[@bwhitn]: https://github.com/bwhitn +[@jarmovanlenthe]: https://github.com/jarmovanlenthe +[@tcode2k16]: https://github.com/tcode2k16 +[@Cynser]: https://github.com/Cynser +[@anthony-arnold]: https://github.com/anthony-arnold +[@masq]: https://github.com/masq +[@Ge0rg3]: https://github.com/Ge0rg3 +[@MShwed]: https://github.com/MShwed +[@kassi]: https://github.com/kassi +[@jarrodconnolly]: https://github.com/jarrodconnolly +[@VirtualColossus]: https://github.com/VirtualColossus +[@cbeuw]: https://github.com/cbeuw +[@matthieuxyz]: https://github.com/matthieuxyz +[@Flavsditz]: https://github.com/Flavsditz +[@pointhi]: https://github.com/pointhi +[@MarvinJWendt]: https://github.com/MarvinJWendt +[@dmfj]: https://github.com/dmfj +[@mattnotmitt]: https://github.com/mattnotmitt +[@Danh4]: https://github.com/Danh4 +[@john19696]: https://github.com/john19696 +[@t-8ch]: https://github.com/t-8ch +[@hettysymes]: https://github.com/hettysymes +[@swesven]: https://github.com/swesven +[@mikecat]: https://github.com/mikecat +[@crespyl]: https://github.com/crespyl +[@thomasleplus]: https://github.com/thomasleplus +[@valdelaseras]: https://github.com/valdelaseras +[@brun0ne]: https://github.com/brun0ne +[@joostrijneveld]: https://github.com/joostrijneveld +[@Xenonym]: https://github.com/Xenonym +[@gchq77703]: https://github.com/gchq77703 +[@a3957273]: https://github.com/a3957273 +[@0xThiebaut]: https://github.com/0xThiebaut +[@cnotin]: https://github.com/cnotin +[@KevinSJ]: https://github.com/KevinSJ +[@sw5678]: https://github.com/sw5678 +[@sg5506844]: https://github.com/sg5506844 +[@AliceGrey]: https://github.com/AliceGrey +[@AshCorr]: https://github.com/AshCorr +[@simonw]: https://github.com/simonw +[@chriswhite199]: https://github.com/chriswhite199 +[@breakersall]: https://github.com/breakersall +[@evanreichard]: https://github.com/evanreichard +[@devcydo]: https://github.com/devcydo +[@zb3]: https://github.com/zb3 +[@jkataja]: https://github.com/jkataja +[@tomgond]: https://github.com/tomgond +[@e218736]: https://github.com/e218736 +[@TheZ3ro]: https://github.com/TheZ3ro +[@EvieHarv]: https://github.com/EvieHarv +[@cplussharp]: https://github.com/cplussharp +[@robinsandhu]: https://github.com/robinsandhu +[@eltociear]: https://github.com/eltociear +[@GuilhermoReadonly]: https://github.com/GuilhermoReadonly +[@simonarnell]: https://github.com/simonarnell +[@RandomByte]: https://github.com/RandomByte +[@c65722]: https://github.com/c65722 +[@c65722]: https://github.com/c65722 +[@c65722]: https://github.com/c65722 +[@max0x53]: https://github.com/max0x53 +[@Adamkadaban]: https://github.com/Adamkadaban +[@c65722]: https://github.com/c65722 +[@jb30795]: https://github.com/jb30795 +[@FranciscoPombal]: https://github.com/FranciscoPombal +[@Oshawk]: https://github.com/Oshawk +[@Oshawk]: https://github.com/Oshawk +[@bartblaze]: https://github.com/bartblaze +[@exactlyaron]: https://github.com/exactlyaron +[@k3ach]: https://github.com/k3ach +[@vs4vijay]: https://github.com/vs4vijay +[@FranciscoPombal]: https://github.com/FranciscoPombal +[@FranciscoPombal]: https://github.com/FranciscoPombal +[@linuxgemini]: https://github.com/linuxgemini +[@depperm]: https://github.com/depperm +[@evenstensberg]: https://github.com/evenstensberg +[@bartblaze]: https://github.com/bartblaze +[@0xh3xa]: https://github.com/0xh3xa +[@flakjacket95]: https://github.com/flakjacket95 +[@zhzy0077]: https://github.com/zhzy0077 +[@JSCU-CNI]: https://github.com/JSCU-CNI +[@ccarpo]: https://github.com/ccarpo +[@r4mos]: https://github.com/r4mos +[@0xh3xa]: https://github.com/0xh3xa +[@0xh3xa]: https://github.com/0xh3xa +[@PathToLife]: https://github.com/PathToLife +[@peterc-s]: https://github.com/peterc-s +[@plvie]: https://github.com/plvie +[@kenduguay1]: https://github.com/kenduguay1 +[@jonking-ajar]: https://github.com/jonking-ajar +[@PathToLife]: https://github.com/PathToLife +[@r4mos]: https://github.com/r4mos +[@jg42526]: https://github.com/jg42526 +[@es45411]: https://github.com/es45411 +[@gchq]: https://github.com/gchq +[@gchqdev364]: https://github.com/gchqdev364 +[@GCHQDeveloper94872]: https://github.com/GCHQDeveloper94872 +[@Sma-Das]: https://github.com/Sma-Das +[@gchq]: https://github.com/gchq +[@Odyhibit]: https://github.com/Odyhibit +[@ericli-splunk]: https://github.com/ericli-splunk +[@xumptex]: https://github.com/xumptex +[@bartvanandel]: https://github.com/bartvanandel +[@bartvanandel]: https://github.com/bartvanandel +[@kendallgoto]: https://github.com/kendallgoto +[@remingtr]: https://github.com/remingtr +[@0xff1ce]: https://github.com/0xff1ce +[@starplanet]: https://github.com/starplanet +[@C85297]: https://github.com/C85297 +[@GCHQDeveloper581]: https://github.com/GCHQDeveloper581 +[@ThomasNotTom]: https://github.com/ThomasNotTom +[@rbpi]: https://github.com/rbpi +[@AlexGustafsson]: https://github.com/AlexGustafsson +[@tuliperis]: https://github.com/tuliperis +[@thomasxm]: https://github.com/thomasxm +[@twostraws]: https://github.com/twostraws +[@beneri]: https://github.com/beneri +[@t-martine]: https://github.com/t-martine +[@wesinator]: https://github.com/wesinator +[@Raka-loah]: https://github.com/Raka-loah + + +[8ad18b]: https://github.com/gchq/CyberChef/commit/8ad18bc7db6d9ff184ba3518686293a7685bf7b7 +[9a33498]: https://github.com/gchq/CyberChef/commit/9a33498fed26a8df9c9f35f39a78a174bf50a513 +[289a417]: https://github.com/gchq/CyberChef/commit/289a417dfb5923de5e1694354ec42a08d9395bfe +[e9ca4dc]: https://github.com/gchq/CyberChef/commit/e9ca4dc9caf98f33fd986431cd400c88082a42b8 +[dd18e52]: https://github.com/gchq/CyberChef/commit/dd18e529939078b89867297b181a584e8b2cc7da +[a895d1d]: https://github.com/gchq/CyberChef/commit/a895d1d82a2f92d440a0c5eca2bc7c898107b737 +[31a7f83]: https://github.com/gchq/CyberChef/commit/31a7f83b82e78927f89689f323fcb9185144d6ff +[760eff4]: https://github.com/gchq/CyberChef/commit/760eff49b5307aaa3104c5e5b437ffe62299acd1 +[65ffd8d]: https://github.com/gchq/CyberChef/commit/65ffd8d65d88eb369f6f61a5d1d0f807179bffb7 +[0a353ee]: https://github.com/gchq/CyberChef/commit/0a353eeb378b9ca5d49e23c7dfc175ae07107b08 +[66d445c]: https://github.com/gchq/CyberChef/commit/66d445c5ef4e8bd896fd15396e3ce2d660d8ace1 +[ab37c1e]: https://github.com/gchq/CyberChef/commit/ab37c1e562dbee0495ed32876ecbb8225282af25 +[965570d]: https://github.com/gchq/CyberChef/commit/965570d2504c17ee1f96211a1dc10ed40cd2b332 +[a477f47]: https://github.com/gchq/CyberChef/commit/a477f47aecd01d78b11fe186ed4b20d9c487cfac +[7a5225c]: https://github.com/gchq/CyberChef/commit/7a5225c961a5e0d192b03152117cd10a761f73d6 +[5f88ae4]: https://github.com/gchq/CyberChef/commit/5f88ae44ec77228d9bed8f11e8cc8e7dcfb36914 +[0e82e4b]: https://github.com/gchq/CyberChef/commit/0e82e4b7c6c77cadb8be61cb145e081d6ecfdc88 +[d635cca]: https://github.com/gchq/CyberChef/commit/d635cca2106aae2a59caf0e5d7e3633ee1ea3155 +[895a929]: https://github.com/gchq/CyberChef/commit/895a9299255525cb57886deb9d9fd4ba17ae9548 +[270a333]: https://github.com/gchq/CyberChef/commit/270a33317944612d27ea1cc15275ad6b0ed097e5 +[d3adfc7]: https://github.com/gchq/CyberChef/commit/d3adfc7c3e5719279524356bce5261bd8350c0f8 +[47c85a1]: https://github.com/gchq/CyberChef/commit/47c85a105ddbdd4cabfa44ddddbc56e3907a8c33 +[3822c6c]: https://github.com/gchq/CyberChef/commit/3822c6c520a0b4200abc675c33f46082f5b9efc6 +[66d445c]: https://github.com/gchq/CyberChef/commit/66d445c5ef4e8bd896fd15396e3ce2d660d8ace1 +[ab37c1e]: https://github.com/gchq/CyberChef/commit/ab37c1e562dbee0495ed32876ecbb8225282af25 +[965570d]: https://github.com/gchq/CyberChef/commit/965570d2504c17ee1f96211a1dc10ed40cd2b332 +[a477f47]: https://github.com/gchq/CyberChef/commit/a477f47aecd01d78b11fe186ed4b20d9c487cfac +[7a5225c]: https://github.com/gchq/CyberChef/commit/7a5225c961a5e0d192b03152117cd10a761f73d6 +[5f88ae4]: https://github.com/gchq/CyberChef/commit/5f88ae44ec77228d9bed8f11e8cc8e7dcfb36914 +[0e82e4b]: https://github.com/gchq/CyberChef/commit/0e82e4b7c6c77cadb8be61cb145e081d6ecfdc88 +[d635cca]: https://github.com/gchq/CyberChef/commit/d635cca2106aae2a59caf0e5d7e3633ee1ea3155 +[895a929]: https://github.com/gchq/CyberChef/commit/895a9299255525cb57886deb9d9fd4ba17ae9548 +[270a333]: https://github.com/gchq/CyberChef/commit/270a33317944612d27ea1cc15275ad6b0ed097e5 +[d3adfc7]: https://github.com/gchq/CyberChef/commit/d3adfc7c3e5719279524356bce5261bd8350c0f8 +[47c85a1]: https://github.com/gchq/CyberChef/commit/47c85a105ddbdd4cabfa44ddddbc56e3907a8c33 +[3822c6c]: https://github.com/gchq/CyberChef/commit/3822c6c520a0b4200abc675c33f46082f5b9efc6 +[66d445c]: https://github.com/gchq/CyberChef/commit/66d445c5ef4e8bd896fd15396e3ce2d660d8ace1 +[ab37c1e]: https://github.com/gchq/CyberChef/commit/ab37c1e562dbee0495ed32876ecbb8225282af25 +[965570d]: https://github.com/gchq/CyberChef/commit/965570d2504c17ee1f96211a1dc10ed40cd2b332 +[a477f47]: https://github.com/gchq/CyberChef/commit/a477f47aecd01d78b11fe186ed4b20d9c487cfac +[7a5225c]: https://github.com/gchq/CyberChef/commit/7a5225c961a5e0d192b03152117cd10a761f73d6 +[5f88ae4]: https://github.com/gchq/CyberChef/commit/5f88ae44ec77228d9bed8f11e8cc8e7dcfb36914 +[0e82e4b]: https://github.com/gchq/CyberChef/commit/0e82e4b7c6c77cadb8be61cb145e081d6ecfdc88 +[d635cca]: https://github.com/gchq/CyberChef/commit/d635cca2106aae2a59caf0e5d7e3633ee1ea3155 +[895a929]: https://github.com/gchq/CyberChef/commit/895a9299255525cb57886deb9d9fd4ba17ae9548 +[270a333]: https://github.com/gchq/CyberChef/commit/270a33317944612d27ea1cc15275ad6b0ed097e5 +[d3adfc7]: https://github.com/gchq/CyberChef/commit/d3adfc7c3e5719279524356bce5261bd8350c0f8 +[47c85a1]: https://github.com/gchq/CyberChef/commit/47c85a105ddbdd4cabfa44ddddbc56e3907a8c33 +[3822c6c]: https://github.com/gchq/CyberChef/commit/3822c6c520a0b4200abc675c33f46082f5b9efc6 +[66d445c]: https://github.com/gchq/CyberChef/commit/66d445c5ef4e8bd896fd15396e3ce2d660d8ace1 + +[#95]: https://github.com/gchq/CyberChef/pull/299 +[#173]: https://github.com/gchq/CyberChef/pull/173 +[#143]: https://github.com/gchq/CyberChef/pull/143 +[#224]: https://github.com/gchq/CyberChef/pull/224 +[#239]: https://github.com/gchq/CyberChef/pull/239 +[#248]: https://github.com/gchq/CyberChef/pull/248 +[#255]: https://github.com/gchq/CyberChef/issues/255 +[#277]: https://github.com/gchq/CyberChef/issues/277 +[#281]: https://github.com/gchq/CyberChef/pull/281 +[#284]: https://github.com/gchq/CyberChef/pull/284 +[#291]: https://github.com/gchq/CyberChef/pull/291 +[#294]: https://github.com/gchq/CyberChef/pull/294 +[#296]: https://github.com/gchq/CyberChef/pull/296 +[#298]: https://github.com/gchq/CyberChef/pull/298 +[#311]: https://github.com/gchq/CyberChef/pull/311 +[#325]: https://github.com/gchq/CyberChef/pull/325 +[#338]: https://github.com/gchq/CyberChef/pull/338 +[#340]: https://github.com/gchq/CyberChef/pull/340 +[#344]: https://github.com/gchq/CyberChef/pull/344 +[#348]: https://github.com/gchq/CyberChef/pull/348 +[#351]: https://github.com/gchq/CyberChef/pull/351 +[#387]: https://github.com/gchq/CyberChef/pull/387 +[#394]: https://github.com/gchq/CyberChef/pull/394 +[#428]: https://github.com/gchq/CyberChef/pull/428 +[#439]: https://github.com/gchq/CyberChef/pull/439 +[#440]: https://github.com/gchq/CyberChef/pull/440 +[#441]: https://github.com/gchq/CyberChef/pull/441 +[#443]: https://github.com/gchq/CyberChef/pull/443 +[#446]: https://github.com/gchq/CyberChef/pull/446 +[#448]: https://github.com/gchq/CyberChef/pull/448 +[#449]: https://github.com/gchq/CyberChef/pull/449 +[#455]: https://github.com/gchq/CyberChef/pull/455 +[#458]: https://github.com/gchq/CyberChef/pull/458 +[#461]: https://github.com/gchq/CyberChef/pull/461 +[#467]: https://github.com/gchq/CyberChef/pull/467 +[#468]: https://github.com/gchq/CyberChef/pull/468 +[#476]: https://github.com/gchq/CyberChef/pull/476 +[#477]: https://github.com/gchq/CyberChef/pull/477 +[#489]: https://github.com/gchq/CyberChef/pull/489 +[#496]: https://github.com/gchq/CyberChef/pull/496 +[#500]: https://github.com/gchq/CyberChef/pull/500 +[#506]: https://github.com/gchq/CyberChef/pull/506 +[#515]: https://github.com/gchq/CyberChef/pull/515 +[#516]: https://github.com/gchq/CyberChef/pull/516 +[#525]: https://github.com/gchq/CyberChef/pull/525 +[#528]: https://github.com/gchq/CyberChef/pull/528 +[#530]: https://github.com/gchq/CyberChef/pull/530 +[#531]: https://github.com/gchq/CyberChef/pull/531 +[#533]: https://github.com/gchq/CyberChef/pull/533 +[#535]: https://github.com/gchq/CyberChef/pull/535 +[#556]: https://github.com/gchq/CyberChef/pull/556 +[#566]: https://github.com/gchq/CyberChef/pull/566 +[#571]: https://github.com/gchq/CyberChef/pull/571 +[#585]: https://github.com/gchq/CyberChef/pull/585 +[#591]: https://github.com/gchq/CyberChef/pull/591 +[#595]: https://github.com/gchq/CyberChef/pull/595 +[#614]: https://github.com/gchq/CyberChef/pull/614 +[#625]: https://github.com/gchq/CyberChef/pull/625 +[#627]: https://github.com/gchq/CyberChef/pull/627 +[#632]: https://github.com/gchq/CyberChef/pull/632 +[#652]: https://github.com/gchq/CyberChef/pull/652 +[#653]: https://github.com/gchq/CyberChef/pull/653 +[#674]: https://github.com/gchq/CyberChef/pull/674 +[#683]: https://github.com/gchq/CyberChef/pull/683 +[#865]: https://github.com/gchq/CyberChef/pull/865 +[#906]: https://github.com/gchq/CyberChef/pull/906 +[#912]: https://github.com/gchq/CyberChef/pull/912 +[#917]: https://github.com/gchq/CyberChef/pull/917 +[#934]: https://github.com/gchq/CyberChef/pull/934 +[#948]: https://github.com/gchq/CyberChef/pull/948 +[#951]: https://github.com/gchq/CyberChef/pull/951 +[#952]: https://github.com/gchq/CyberChef/pull/952 +[#965]: https://github.com/gchq/CyberChef/pull/965 +[#966]: https://github.com/gchq/CyberChef/pull/966 +[#987]: https://github.com/gchq/CyberChef/pull/987 +[#999]: https://github.com/gchq/CyberChef/pull/999 +[#1006]: https://github.com/gchq/CyberChef/pull/1006 +[#1022]: https://github.com/gchq/CyberChef/pull/1022 +[#1037]: https://github.com/gchq/CyberChef/pull/1037 +[#1045]: https://github.com/gchq/CyberChef/pull/1045 +[#1049]: https://github.com/gchq/CyberChef/pull/1049 +[#1065]: https://github.com/gchq/CyberChef/pull/1065 +[#1066]: https://github.com/gchq/CyberChef/pull/1066 +[#1083]: https://github.com/gchq/CyberChef/pull/1083 +[#1189]: https://github.com/gchq/CyberChef/pull/1189 +[#1242]: https://github.com/gchq/CyberChef/pull/1242 +[#1244]: https://github.com/gchq/CyberChef/pull/1244 +[#1313]: https://github.com/gchq/CyberChef/pull/1313 +[#1326]: https://github.com/gchq/CyberChef/pull/1326 +[#1364]: https://github.com/gchq/CyberChef/pull/1364 +[#1264]: https://github.com/gchq/CyberChef/pull/1264 +[#1266]: https://github.com/gchq/CyberChef/pull/1266 +[#1250]: https://github.com/gchq/CyberChef/pull/1250 +[#1308]: https://github.com/gchq/CyberChef/pull/1308 +[#1405]: https://github.com/gchq/CyberChef/pull/1405 +[#1421]: https://github.com/gchq/CyberChef/pull/1421 +[#1427]: https://github.com/gchq/CyberChef/pull/1427 +[#1472]: https://github.com/gchq/CyberChef/pull/1472 +[#1457]: https://github.com/gchq/CyberChef/pull/1457 +[#1466]: https://github.com/gchq/CyberChef/pull/1466 +[#1456]: https://github.com/gchq/CyberChef/pull/1456 +[#1450]: https://github.com/gchq/CyberChef/pull/1450 +[#1498]: https://github.com/gchq/CyberChef/pull/1498 +[#1499]: https://github.com/gchq/CyberChef/pull/1499 +[#1528]: https://github.com/gchq/CyberChef/pull/1528 +[#661]: https://github.com/gchq/CyberChef/pull/661 +[#493]: https://github.com/gchq/CyberChef/pull/493 +[#592]: https://github.com/gchq/CyberChef/issues/592 +[#1703]: https://github.com/gchq/CyberChef/issues/1703 +[#1675]: https://github.com/gchq/CyberChef/issues/1675 +[#1678]: https://github.com/gchq/CyberChef/issues/1678 +[#1541]: https://github.com/gchq/CyberChef/issues/1541 +[#1667]: https://github.com/gchq/CyberChef/issues/1667 +[#1555]: https://github.com/gchq/CyberChef/issues/1555 +[#1694]: https://github.com/gchq/CyberChef/issues/1694 +[#1699]: https://github.com/gchq/CyberChef/issues/1699 +[#1757]: https://github.com/gchq/CyberChef/issues/1757 +[#1752]: https://github.com/gchq/CyberChef/issues/1752 +[#1753]: https://github.com/gchq/CyberChef/issues/1753 +[#1750]: https://github.com/gchq/CyberChef/issues/1750 +[#1591]: https://github.com/gchq/CyberChef/issues/1591 +[#654]: https://github.com/gchq/CyberChef/issues/654 +[#1762]: https://github.com/gchq/CyberChef/issues/1762 +[#1606]: https://github.com/gchq/CyberChef/issues/1606 +[#1197]: https://github.com/gchq/CyberChef/issues/1197 +[#933]: https://github.com/gchq/CyberChef/issues/933 +[#1361]: https://github.com/gchq/CyberChef/issues/1361 +[#1765]: https://github.com/gchq/CyberChef/issues/1765 +[#1767]: https://github.com/gchq/CyberChef/issues/1767 +[#1769]: https://github.com/gchq/CyberChef/issues/1769 +[#1759]: https://github.com/gchq/CyberChef/issues/1759 +[#1504]: https://github.com/gchq/CyberChef/issues/1504 +[#512]: https://github.com/gchq/CyberChef/issues/512 +[#1732]: https://github.com/gchq/CyberChef/issues/1732 +[#1789]: https://github.com/gchq/CyberChef/issues/1789 +[#1040]: https://github.com/gchq/CyberChef/pull/1040 +[#2176]: https://github.com/gchq/CyberChef/pull/2176 +[#2177]: https://github.com/gchq/CyberChef/pull/2177 +[#2174]: https://github.com/gchq/CyberChef/pull/2174 +[#2058]: https://github.com/gchq/CyberChef/pull/2058 +[#1861]: https://github.com/gchq/CyberChef/pull/1861 +[#2055]: https://github.com/gchq/CyberChef/pull/2055 +[#2169]: https://github.com/gchq/CyberChef/pull/2169 +[#2175]: https://github.com/gchq/CyberChef/pull/2175 +[#2173]: https://github.com/gchq/CyberChef/pull/2173 +[#2172]: https://github.com/gchq/CyberChef/pull/2172 +[#2136]: https://github.com/gchq/CyberChef/pull/2136 +[#2165]: https://github.com/gchq/CyberChef/pull/2165 +[#2159]: https://github.com/gchq/CyberChef/pull/2159 +[#2086]: https://github.com/gchq/CyberChef/pull/2086 +[#2118]: https://github.com/gchq/CyberChef/pull/2118 +[#2166]: https://github.com/gchq/CyberChef/pull/2166 +[#2188]: https://github.com/gchq/CyberChef/pull/2188 +[#2137]: https://github.com/gchq/CyberChef/pull/2137 +[#1876]: https://github.com/gchq/CyberChef/pull/1876 +[#2186]: https://github.com/gchq/CyberChef/pull/2186 +[#1573]: https://github.com/gchq/CyberChef/pull/1573 +[#2183]: https://github.com/gchq/CyberChef/pull/2183 +[#2182]: https://github.com/gchq/CyberChef/pull/2182 +[#2181]: https://github.com/gchq/CyberChef/pull/2181 + diff --git a/plugins/srktoolbox/CHANGELOG_SRKTOOLBOX.md b/plugins/srktoolbox/CHANGELOG_SRKTOOLBOX.md new file mode 100644 index 00000000..1aec8663 --- /dev/null +++ b/plugins/srktoolbox/CHANGELOG_SRKTOOLBOX.md @@ -0,0 +1,33 @@ +# SRK Toolbox 改动记录 + +## 版本命名 + +SRK Toolbox沿用CyberChef版本命名方式,此处记录和官方版本不同的版本号与改动记录,未记载此处的版本内容改动同[CyberChef原版改动](https://github.com/gchq/CyberChef/blob/master/CHANGELOG.md)。 + +## 详细信息 +### [10.19.5] - 2026-01-15 +- 前一个版本和官方版本同步发生问题导致版本内容不一致,此版本暂时追至原版最新代码以修复bug。 + +### [10.15.2] - 2024-04-08 +- 大意了,合并冲突的时候不小心删了一些东西得补回来。 +- 因为官方加入了自动检测输出字符编码的功能,所以删除“输出默认使用UTF8编码”的选项。 + +### [10.4.1] - 2023-05-09 +- 汉化之前漏掉的一小部分说明文字(主要是F1帮助)。 +- 增加“输出默认使用UTF8编码”的选项,因为“显示原始字节”不能显示中文,导致汉化后的模块输出看起来是乱码,默认关闭,需要在设置里手动打开。 +- 修复选择GB18030解码有时会卡死的问题。 + +### [9.54.1] - 2022-12-05 +- 彻底汉化单元测试并修复对应操作的bug,此后发布的版本均进行全部单元测试。(备注:经核对前期版本中少量操作存在数据部分丢失或汉化疏漏,但不存在数据错误,可放心使用) +- 将Package名称修改为`srktoolbox`与原版进行区分。 +- Toastr的一处显示bug修复。 + +### [9.49.1] - 2022-11-23 +- 启用Github Actions作为CI,添加docker镜像。 +- 替换SnackbarJS为Toastr。 + +[10.19.5]: https://github.com/Raka-loah/SRK-Toolbox/releases/tag/v10.15.2 +[10.15.2]: https://github.com/Raka-loah/SRK-Toolbox/releases/tag/v10.15.2 +[10.4.1]: https://github.com/Raka-loah/SRK-Toolbox/releases/tag/v10.4.1 +[9.54.1]: https://github.com/Raka-loah/SRK-Toolbox/releases/tag/v9.54.1 +[9.49.1]: https://github.com/Raka-loah/SRK-Toolbox/releases/tag/v9.49.1 \ No newline at end of file diff --git a/plugins/srktoolbox/CODE_OF_CONDUCT.md b/plugins/srktoolbox/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..1fadd9c4 --- /dev/null +++ b/plugins/srktoolbox/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at oss@gchq.gov.uk. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/plugins/srktoolbox/Dockerfile b/plugins/srktoolbox/Dockerfile new file mode 100644 index 00000000..0d634369 --- /dev/null +++ b/plugins/srktoolbox/Dockerfile @@ -0,0 +1,2 @@ +FROM lipanski/docker-static-website:latest +COPY /build/prod . \ No newline at end of file diff --git a/plugins/srktoolbox/Gruntfile.js b/plugins/srktoolbox/Gruntfile.js new file mode 100644 index 00000000..02994d7b --- /dev/null +++ b/plugins/srktoolbox/Gruntfile.js @@ -0,0 +1,440 @@ +"use strict"; + +const webpack = require("webpack"); +const HtmlWebpackPlugin = require("html-webpack-plugin"); +const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin; +const glob = require("glob"); +const path = require("path"); + +const nodeFlags = "--experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-warnings --no-deprecation"; + +/** + * Grunt configuration for building the app in various formats. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +module.exports = function (grunt) { + grunt.file.defaultEncoding = "utf8"; + grunt.file.preserveBOM = false; + + // Tasks + grunt.registerTask("dev", + "A persistent task which creates a development build whenever source files are modified.", + ["clean:dev", "clean:config", "exec:generateConfig", "concurrent:dev"]); + + grunt.registerTask("prod", + "Creates a production-ready build. Use the --msg flag to add a compile message.", + [ + "eslint", "clean:prod", "clean:config", "exec:generateConfig", "findModules", "webpack:web", + "copy:standalone", "zip:standalone", "clean:standalone", "exec:calcDownloadHash", "chmod" + ]); + + grunt.registerTask("node", + "Compiles CyberChef into a single NodeJS module.", + [ + "clean:node", "clean:config", "clean:nodeConfig", "exec:generateConfig", "exec:generateNodeIndex" + ]); + + grunt.registerTask("configTests", + "A task which configures config files in preparation for tests to be run. Use `npm test` to run tests.", + [ + "clean:config", "clean:nodeConfig", "exec:generateConfig", "exec:generateNodeIndex" + ]); + + grunt.registerTask("testui", + "A task which runs all the UI tests in the tests directory. The prod task must already have been run.", + ["connect:prod", "exec:browserTests"]); + + grunt.registerTask("testnodeconsumer", + "A task which checks whether consuming CJS and ESM apps work with the CyberChef build", + ["exec:setupNodeConsumers", "exec:testCJSNodeConsumer", "exec:testESMNodeConsumer", "exec:teardownNodeConsumers"]); + + grunt.registerTask("default", + "Lints the code base", + ["eslint", "exec:repoSize"]); + + grunt.registerTask("lint", "eslint"); + + grunt.registerTask("findModules", + "Finds all generated modules and updates the entry point list for Webpack", + function(arg1, arg2) { + const moduleEntryPoints = listEntryModules(); + + grunt.log.writeln(`Found ${Object.keys(moduleEntryPoints).length} modules.`); + + grunt.config.set("webpack.web.entry", + Object.assign({ + main: "./src/web/index.js" + }, moduleEntryPoints)); + }); + + + // Load tasks provided by each plugin + grunt.loadNpmTasks("grunt-eslint"); + grunt.loadNpmTasks("grunt-webpack"); + grunt.loadNpmTasks("grunt-contrib-clean"); + grunt.loadNpmTasks("grunt-contrib-copy"); + grunt.loadNpmTasks("grunt-contrib-watch"); + grunt.loadNpmTasks("grunt-chmod"); + grunt.loadNpmTasks("grunt-exec"); + grunt.loadNpmTasks("grunt-concurrent"); + grunt.loadNpmTasks("grunt-contrib-connect"); + grunt.loadNpmTasks("grunt-zip"); + + + // Project configuration + const compileYear = grunt.template.today("UTC:yyyy"), + compileTime = grunt.template.today("UTC:dd/mm/yyyy HH:MM:ss") + " UTC", + pkg = grunt.file.readJSON("package.json"), + webpackConfig = require("./webpack.config.js"), + BUILD_CONSTANTS = { + COMPILE_YEAR: JSON.stringify(compileYear), + COMPILE_TIME: JSON.stringify(compileTime), + COMPILE_MSG: JSON.stringify(grunt.option("compile-msg") || grunt.option("msg") || ""), + PKG_VERSION: JSON.stringify(pkg.version), + }, + moduleEntryPoints = listEntryModules(), + nodeConsumerTestPath = "~/tmp-srktoolbox", + /** + * Configuration for Webpack production build. Defined as a function so that it + * can be recalculated when new modules are generated. + */ + webpackProdConf = () => { + return { + mode: "production", + target: "web", + entry: Object.assign({ + main: "./src/web/index.js" + }, moduleEntryPoints), + output: { + path: __dirname + "/build/prod", + filename: chunkData => { + return chunkData.chunk.name === "main" ? "assets/[name].js": "[name].js"; + }, + globalObject: "this" + }, + resolve: { + alias: { + "./config/modules/OpModules.mjs": "./config/modules/Default.mjs" + } + }, + plugins: [ + new webpack.DefinePlugin(BUILD_CONSTANTS), + new HtmlWebpackPlugin({ + filename: "index.html", + template: "./src/web/html/index.html", + chunks: ["main"], + compileYear: compileYear, + compileTime: compileTime, + version: pkg.version, + minify: { + removeComments: true, + collapseWhitespace: true, + minifyJS: true, + minifyCSS: true + } + }), + new BundleAnalyzerPlugin({ + analyzerMode: "static", + reportFilename: "BundleAnalyzerReport.html", + openAnalyzer: false + }), + ] + }; + }; + + + /** + * Generates an entry list for all the modules. + */ + function listEntryModules() { + const entryModules = {}; + + glob.sync("./src/core/config/modules/*.mjs").forEach(file => { + const basename = path.basename(file); + if (basename !== "Default.mjs" && basename !== "OpModules.mjs") + entryModules["modules/" + basename.split(".mjs")[0]] = path.resolve(file); + }); + + return entryModules; + } + + /** + * Detects the correct delimiter to use to chain shell commands together + * based on the current OS. + * + * @param {string[]} cmds + * @returns {string} + */ + function chainCommands(cmds) { + const win = process.platform === "win32"; + if (!win) { + return cmds.join(";"); + } + return cmds + // && means that subsequent commands will not be executed if the + // previous one fails. & would coninue on a fail + .join("&&") + // Windows does not support \n properly + .replace(/\n/g, "\\n"); + } + + grunt.initConfig({ + clean: { + dev: ["build/dev/*"], + prod: ["build/prod/*"], + node: ["build/node/*"], + config: ["src/core/config/OperationConfig.json", "src/core/config/modules/*", "src/code/operations/index.mjs"], + nodeConfig: ["src/node/index.mjs", "src/node/config/OperationConfig.json"], + standalone: ["build/prod/CyberChef*.html"] + }, + eslint: { + configs: ["*.{js,mjs}"], + core: ["src/core/**/*.{js,mjs}", "!src/core/vendor/**/*", "!src/core/operations/legacy/**/*"], + web: ["src/web/**/*.{js,mjs}", "!src/web/static/**/*"], + node: ["src/node/**/*.{js,mjs}"], + tests: ["tests/**/*.{js,mjs}"], + }, + webpack: { + options: webpackConfig, + myConfig: webpackConfig, + web: webpackProdConf(), + }, + "webpack-dev-server": { + options: webpackConfig, + start: { + mode: "development", + target: "web", + entry: Object.assign({ + main: "./src/web/index.js" + }, moduleEntryPoints), + resolve: { + alias: { + "./config/modules/OpModules.mjs": "./config/modules/Default.mjs" + } + }, + devServer: { + port: grunt.option("port") || 8080, + client: { + logging: "error", + overlay: true + }, + hot: "only" + }, + plugins: [ + new webpack.DefinePlugin(BUILD_CONSTANTS), + new HtmlWebpackPlugin({ + filename: "index.html", + template: "./src/web/html/index.html", + chunks: ["main"], + compileYear: compileYear, + compileTime: compileTime, + version: pkg.version, + }) + ] + } + }, + zip: { + standalone: { + cwd: "build/prod/", + src: [ + "build/prod/**/*", + "!build/prod/index.html", + "!build/prod/BundleAnalyzerReport.html", + ], + dest: `build/prod/SRK_Toolbox_v${pkg.version}.zip`, + compression: "DEFLATE" + } + }, + connect: { + prod: { + options: { + port: grunt.option("port") || 8000, + base: "build/prod/" + } + } + }, + copy: { + ghPages: { + options: { + process: function (content, srcpath) { + if (srcpath.indexOf("index.html") >= 0) { + // Add Google Analytics code to index.html + content = content.replace("", + grunt.file.read("src/web/static/ga.html") + ""); + + // Add Structured Data for SEO + content = content.replace("", + ""); + return grunt.template.process(content, srcpath); + } else { + return content; + } + }, + noProcess: ["**", "!**/*.html"] + }, + files: [ + { + src: ["build/prod/index.html"], + dest: "build/prod/index.html" + } + ] + }, + standalone: { + options: { + process: function (content, srcpath) { + if (srcpath.indexOf("index.html") >= 0) { + // Replace download link with version number + content = content.replace(/]+>.+下载离线版SRK Toolbox.+?<\/a>/, + `版本 ${pkg.version}`); + + return grunt.template.process(content, srcpath); + } else { + return content; + } + }, + noProcess: ["**", "!**/*.html"] + }, + files: [ + { + src: ["build/prod/index.html"], + dest: `build/prod/SRK_Toolbox_v${pkg.version}.html` + } + ] + } + }, + chmod: { + build: { + options: { + mode: "755", + }, + src: ["build/**/*", "build/"] + } + }, + watch: { + config: { + files: ["src/core/operations/**/*", "!src/core/operations/index.mjs"], + tasks: ["exec:generateNodeIndex", "exec:generateConfig"] + } + }, + concurrent: { + dev: ["watch:config", "webpack-dev-server:start"], + options: { + logConcurrentOutput: true + } + }, + exec: { + calcDownloadHash: { + command: function () { + switch (process.platform) { + case "darwin": + return chainCommands([ + `shasum -a 256 build/prod/SRK_Toolbox_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`, + `sed -i '' -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html` + ]); + default: + return chainCommands([ + `sha256sum build/prod/SRK_Toolbox_v${pkg.version}.zip | awk '{print $1;}' > build/prod/sha256digest.txt`, + `sed -i -e "s/DOWNLOAD_HASH_PLACEHOLDER/$(cat build/prod/sha256digest.txt)/" build/prod/index.html` + ]); + } + }, + }, + repoSize: { + command: chainCommands([ + "git ls-files | wc -l | xargs printf '\n%b\ttracked files\n'", + "du -hs | egrep -o '^[^\t]*' | xargs printf '%b\trepository size\n'" + ]), + stderr: false + }, + cleanGit: { + command: "git gc --prune=now --aggressive" + }, + sitemap: { + command: `node ${nodeFlags} src/web/static/sitemap.mjs > build/prod/sitemap.xml`, + sync: true + }, + generateConfig: { + command: chainCommands([ + "echo '\n--- Regenerating config files. ---'", + "echo [] > src/core/config/OperationConfig.json", + `node ${nodeFlags} src/core/config/scripts/generateOpsIndex.mjs`, + `node ${nodeFlags} src/core/config/scripts/generateConfig.mjs`, + "echo '--- Config scripts finished. ---\n'" + ]), + sync: true + }, + generateNodeIndex: { + command: chainCommands([ + "echo '\n--- Regenerating node index ---'", + `node ${nodeFlags} src/node/config/scripts/generateNodeIndex.mjs`, + "echo '--- Node index generated. ---\n'" + ]), + sync: true + }, + browserTests: { + command: "./node_modules/.bin/nightwatch --env prod" + }, + setupNodeConsumers: { + command: chainCommands([ + "echo '\n--- Testing node consumers ---'", + "npm link", + `mkdir ${nodeConsumerTestPath}`, + `cp tests/node/consumers/* ${nodeConsumerTestPath}`, + `cd ${nodeConsumerTestPath}`, + "npm link srktoolbox" + ]), + sync: true + }, + teardownNodeConsumers: { + command: chainCommands([ + `rm -rf ${nodeConsumerTestPath}`, + "echo '\n--- Node consumer tests complete ---'" + ]), + }, + testCJSNodeConsumer: { + command: chainCommands([ + `cd ${nodeConsumerTestPath}`, + `node ${nodeFlags} cjs-consumer.js`, + ]), + stdout: false, + }, + testESMNodeConsumer: { + command: chainCommands([ + `cd ${nodeConsumerTestPath}`, + `node ${nodeFlags} esm-consumer.mjs`, + ]), + stdout: false, + }, + fixCryptoApiImports: { + command: function () { + switch (process.platform) { + case "darwin": + return `find ./node_modules/crypto-api/src/ \\( -type d -name .git -prune \\) -o -type f -print0 | xargs -0 sed -i '' -e '/\\.mjs/!s/\\(from "\\.[^"]*\\)";/\\1.mjs";/g'`; + default: + return `find ./node_modules/crypto-api/src/ \\( -type d -name .git -prune \\) -o -type f -print0 | xargs -0 sed -i -e '/\\.mjs/!s/\\(from "\\.[^"]*\\)";/\\1.mjs";/g'`; + } + }, + stdout: false + }, + fixSnackbarMarkup: { + command: function () { + switch (process.platform) { + case "darwin": + return `sed -i '' 's/
/
/g' ./node_modules/snackbarjs/src/snackbar.js`; + default: + return `sed -i 's/
/
/g' ./node_modules/snackbarjs/src/snackbar.js`; + } + }, + stdout: false + }, + }, + }); +}; diff --git a/plugins/srktoolbox/LICENSE b/plugins/srktoolbox/LICENSE new file mode 100644 index 00000000..7a4a3ea2 --- /dev/null +++ b/plugins/srktoolbox/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/plugins/srktoolbox/README.md b/plugins/srktoolbox/README.md new file mode 100644 index 00000000..54faaf49 --- /dev/null +++ b/plugins/srktoolbox/README.md @@ -0,0 +1,363 @@ +<<<<<<< HEAD +# SRK Toolbox for ZTools + +SRK Toolbox for ZTools 是一个可导入 ZTools 的中文安全工具箱插件,基于 CyberChef 适配而来,提供编码转换、加密解密、压缩处理和数据分析等常用能力。 + +## 项目特性 + +- 可直接作为 ZTools 插件导入 +- 保留 SRK Toolbox 的核心操作体验 +- 适配 ZTools 窗口展示 +- 支持本地开发与生产打包 + +## 插件信息 + +插件清单位于 `public/plugin.json`,ZTools 会根据这里识别插件名称、描述、图标、命令入口和窗口高度等信息。 + +## 安装 +======= +# vanusee + +> A ZTools plugin + +这是一个使用 **Vue 3 + Vite + TypeScript** 构建的 ZTools 插件。 + +## ✨ 功能特性 + +### 📌 已包含的示例功能 + +- **Hello** - 基础功能指令示例 + - 触发指令:`你好` / `hello` + - 展示简单的 Vue 组件界面 + +- **读文件** - 文件读取功能示例 + - 功能指令:`读文件` + - 匹配指令:支持拖拽文件触发 + - 演示如何使用 Node.js 能力读取文件内容 + +- **保存为文件** - 文件写入功能示例 + - 匹配指令:任意文本/图片 → `保存为文件` + - 演示如何将剪贴板内容保存为文件 + +## 📁 项目结构 + +``` +. +├── public/ +│ ├── logo.png # 插件图标 +│ ├── plugin.json # 插件配置文件 +│ └── preload/ # Preload 脚本目录 +│ ├── package.json # Preload 依赖配置 +│ └── services.js # Node.js 能力扩展 +├── src/ +│ ├── main.ts # 入口文件 +│ ├── main.css # 全局样式 +│ ├── App.vue # 根组件 +│ ├── env.d.ts # 类型声明 +│ ├── Hello/ # Hello 功能组件 +│ │ └── index.vue +│ ├── Read/ # 读文件功能组件 +│ │ └── index.vue +│ └── Write/ # 写文件功能组件 +│ └── index.vue +├── index.html # HTML 模板 +├── vite.config.js # Vite 配置 +├── tsconfig.json # TypeScript 配置 +├── package.json # 项目依赖 +└── README.md # 项目文档 +``` + +## 🚀 快速开始 + +### 安装依赖 +>>>>>>> 334f3fc (first commit) + +```bash +npm install +``` + +<<<<<<< HEAD +## 开发 + +启动本地开发环境后,将 `public/plugin.json` 中的 `development.main` 指向本地服务地址,即可在 ZTools 中进行调试。 +======= +### 开发模式 +>>>>>>> 334f3fc (first commit) + +```bash +npm run dev +``` + +<<<<<<< HEAD +如果你的本地开发端口与清单中的地址不同,请同步修改: + +```json +"development": { + "main": "http://localhost:54333" +} +``` + +## 构建 + +生产构建会生成 ZTools 可用的插件包和普通离线包: +======= +开发服务器将在 `http://localhost:5173` 启动。ZTools 会自动加载开发版本。 + +### 构建生产版本 +>>>>>>> 334f3fc (first commit) + +```bash +npm run build +``` + +<<<<<<< HEAD +构建完成后,产物位于: + +- `build/prod/SRK_Toolbox_ztools_v10.22.1.zip` +- `build/prod/SRK_Toolbox_v10.22.1.zip` + +其中 `SRK_Toolbox_ztools_v10.22.1.zip` 是用于导入 ZTools 的插件包。 + +## 导入到 ZTools + +1. 打开 ZTools +2. 导入 `build/prod/SRK_Toolbox_ztools_v10.22.1.zip` +3. 安装后即可通过“SRK Toolbox”或“srk”等命令打开插件 + +## 命令入口 + +插件清单中的快捷命令包括: + +- `SRK Toolbox` +- `srk` +- `toolbox` +- `工具箱` +- `密码工具` +- `编码转换` +- `CyberChef` + +## 窗口适配 + +由于 ZTools 插件窗口宽度受宿主限制,本项目已针对主界面做了最小宽度和滚动适配,避免操作面板在较窄窗口中被过度挤压。 + +## 目录说明 + +- `src/`:核心源码 +- `public/`:插件清单和图标资源 +- `build/prod/`:生产构建输出 +- `webpack.config.js`:Webpack 构建配置 +- `Gruntfile.js`:构建与打包任务 + +## 许可 + +本项目基于 CyberChef 相关代码演化而来,具体许可请参考原项目与仓库中的许可证文件。 +======= +构建产物将输出到 `dist/` 目录。 + +## 📖 开发指南 + +### 1. 修改插件配置 + +编辑 `public/plugin.json` 文件: + +```json +{ + "name": "你的插件名称", + "description": "插件描述", + "author": "作者名称", + "version": "1.0.0", + "features": [ + // 添加你的功能配置 + ] +} +``` + +### 2. 创建新功能 + +#### 步骤 1: 创建 Vue 组件 + +在 `src/` 目录下创建新的功能组件: + +```vue + + + + + + +``` + +#### 步骤 2: 注册路由 + +在 `src/App.vue` 中添加路由: + +```vue + +``` + +#### 步骤 3: 配置功能 + +在 `plugin.json` 中添加功能配置: + +```json +{ + "code": "myfeature", + "explain": "我的新功能", + "icon": "logo.png", + "cmds": ["触发指令"] +} +``` + +### 3. 使用 Node.js 能力 + +#### 扩展 Preload 服务 + +编辑 `public/preload/services.js`: + +```javascript +const fs = require('fs') +const path = require('path') + +module.exports = { + // 示例:读取文件 + readFile: (filePath) => { + return fs.readFileSync(filePath, 'utf-8') + }, + + // 添加你的服务 + myService: (params) => { + // 实现你的逻辑 + return result + } +} +``` + +#### 在 Vue 组件中调用 + +```vue + +``` + +### 4. 使用 ZTools API + +```vue + +``` + +## 🎨 样式开发 + +### 使用 CSS 变量 + +ZTools 提供了一套 CSS 变量用于主题适配: + +```css +.my-component { + background: var(--bg-color); + color: var(--text-color); + border: 1px solid var(--border-color); +} +``` + +### 暗色模式支持 + +```css +@media (prefers-color-scheme: dark) { + .my-component { + /* 暗色模式样式 */ + } +} +``` + +## 📦 构建与发布 + +### 1. 构建插件 + +```bash +npm run build +``` + +### 2. 测试构建产物 + +将 `dist/` 目录中的所有文件复制到 ZTools 插件目录进行测试。 + +### 3. 发布到插件市场 + +1. 确保 `plugin.json` 中的信息完整准确 +2. 准备好插件截图和详细说明 +3. 访问 ZTools 插件市场提交插件 + +## 📚 相关资源 + +- [ZTools 官方文档](https://github.com/ztool-center/ztools) +- [ZTools API 文档](https://github.com/ztool-center/ztools-api-types) +- [Vue 3 文档](https://vuejs.org/) +- [Vite 文档](https://vitejs.dev/) + +## ❓ 常见问题 + +### Q: 如何调试插件? + +A: 使用 `npm run dev` 启动开发服务器,在插件界面中点击插件头像图标,在弹出的菜单中选择"打开开发者工具"进行调试。 + +### Q: 如何访问 Node.js 能力? + +A: 通过 `public/preload/services.js` 文件扩展服务,然后在组件中使用 `window.services` 调用。 + +### Q: 插件图标不显示? + +A: 确保 `public/logo.png` 文件存在,且在 `plugin.json` 中正确配置了 `logo` 字段。 + +### Q: 如何处理大文件上传? + +A: 建议使用 Node.js 流式处理,在 preload 脚本中实现文件分块处理逻辑。 + +## 📄 开源协议 + +MIT License + +--- + +**祝你开发愉快!** 🎉 +>>>>>>> 334f3fc (first commit) diff --git a/plugins/srktoolbox/SECURITY.md b/plugins/srktoolbox/SECURITY.md new file mode 100644 index 00000000..c934c934 --- /dev/null +++ b/plugins/srktoolbox/SECURITY.md @@ -0,0 +1,26 @@ +# Security Policy + +## Supported Versions + +CyberChef is supported on a best endeavours basis. Patches will be applied to +the latest version rather than retroactively to older versions. To ensure you +are using the most secure version of CyberChef, please make sure you have the +[latest release](https://github.com/gchq/CyberChef/releases/latest). The +official [live demo](https://gchq.github.io/CyberChef/) is always up to date. + +## Reporting a Vulnerability + +In most scenarios, the most appropriate way to report a vulnerability is to +[raise a new issue](https://github.com/gchq/CyberChef/issues/new/choose) +describing the problem in as much detail as possible, ideally with examples. +This will obviously be public. If you feel that the vulnerability is +significant enough to warrant a private disclosure, please email +[oss@gchq.gov.uk](mailto:oss@gchq.gov.uk) and +[n1474335@gmail.com](mailto:n1474335@gmail.com). + +Disclosures of vulnerabilities in CyberChef are always welcomed. Whilst we aim +to write clean and secure code free from bugs, we recognise that this is an open +source project written by analysts in their spare time, relying on dozens of +open source libraries that are modified and updated on a regular basis. We hope +that the community will continue to support us as we endeavour to maintain and +develop this tool together. diff --git a/plugins/srktoolbox/babel.config.js b/plugins/srktoolbox/babel.config.js new file mode 100644 index 00000000..deab9108 --- /dev/null +++ b/plugins/srktoolbox/babel.config.js @@ -0,0 +1,27 @@ +module.exports = function(api) { + api.cache.forever(); + + return { + "presets": [ + ["@babel/preset-env", { + "modules": false, + "useBuiltIns": "entry", + "corejs": 3 + }] + ], + "plugins": [ + "dynamic-import-node", + "@babel/plugin-syntax-import-assertions", + [ + "babel-plugin-transform-builtin-extend", { + "globals": ["Error"] + } + ], + [ + "@babel/plugin-transform-runtime", { + "regenerator": true + } + ] + ] + }; +}; diff --git a/plugins/srktoolbox/eslint.config.mjs b/plugins/srktoolbox/eslint.config.mjs new file mode 100644 index 00000000..c0a7222c --- /dev/null +++ b/plugins/srktoolbox/eslint.config.mjs @@ -0,0 +1,129 @@ +import babelParser from "@babel/eslint-parser"; +import jsdoc from "eslint-plugin-jsdoc"; +import js from "@eslint/js"; +import globals from "globals"; + +export default [ + js.configs.recommended, + { + languageOptions: { + ecmaVersion: 2022, + parser: babelParser, + parserOptions: { + ecmaVersion: 2022, + ecmaFeatures: { + impliedStrict: true + }, + sourceType: "module", + allowImportExportEverywhere: true + }, + globals: { + ...globals.browser, + ...globals.node, + ...globals.es6, + "$": false, + "jQuery": false, + "log": false, + "app": false, + + "COMPILE_TIME": false, + "COMPILE_MSG": false, + "PKG_VERSION": false + }, + }, + ignores: ["src/core/vendor/**"], + plugins: { + jsdoc + }, + rules: { + // enable additional rules + "no-eval": "error", + "no-implied-eval": "error", + "dot-notation": "error", + "eqeqeq": ["error", "smart"], + "no-caller": "error", + "no-extra-bind": "error", + "no-unused-expressions": "error", + "no-useless-call": "error", + "no-useless-return": "error", + "radix": "warn", + + // modify rules from base configurations + "no-unused-vars": ["error", { + "args": "none", + "vars": "all", + "caughtErrors": "none" + }], + "no-empty": ["error", { + "allowEmptyCatch": true + }], + + // disable rules from base configurations + "no-control-regex": "off", + "require-atomic-updates": "off", + "no-async-promise-executor": "off", + + // stylistic conventions + "brace-style": ["error", "1tbs"], + "space-before-blocks": ["error", "always"], + "block-spacing": "error", + "array-bracket-spacing": "error", + "comma-spacing": "error", + "spaced-comment": ["error", "always", { "exceptions": ["/"] }], + "comma-style": "error", + "computed-property-spacing": "error", + "no-trailing-spaces": "warn", + "eol-last": "error", + "func-call-spacing": "error", + "key-spacing": ["warn", { + "mode": "minimum" + }], + "indent": ["error", 4, { + "ignoreComments": true, + "ArrayExpression": "first", + "SwitchCase": 1 + }], + "linebreak-style": ["error", "unix"], + "quotes": ["error", "double", { + "avoidEscape": true, + "allowTemplateLiterals": true + }], + "camelcase": ["error", { + "properties": "always" + }], + "semi": ["error", "always"], + "unicode-bom": "error", + "jsdoc/require-jsdoc": ["error", { + "require": { + "FunctionDeclaration": true, + "MethodDefinition": true, + "ClassDeclaration": true, + "ArrowFunctionExpression": false + } + }], + "keyword-spacing": ["error", { + "before": true, + "after": true + }], + "no-multiple-empty-lines": ["warn", { + "max": 2, + "maxEOF": 1, + "maxBOF": 0 + }], + "no-whitespace-before-property": "error", + "operator-linebreak": ["error", "after"], + "space-in-parens": "error", + "no-var": "error", + "prefer-const": "error", + "no-console": "error" + }, + }, + // File-pattern specific overrides + { + files: ["tests/**/*"], + rules: { + "no-unused-expressions": "off", + "no-console": "off" + } + }, +]; diff --git a/plugins/srktoolbox/index.html b/plugins/srktoolbox/index.html new file mode 100644 index 00000000..eaa17316 --- /dev/null +++ b/plugins/srktoolbox/index.html @@ -0,0 +1,11 @@ + + + + + + + +
+ + + diff --git a/plugins/srktoolbox/nightwatch.json b/plugins/srktoolbox/nightwatch.json new file mode 100644 index 00000000..95359f44 --- /dev/null +++ b/plugins/srktoolbox/nightwatch.json @@ -0,0 +1,32 @@ +{ + "src_folders": ["tests/browser"], + "exclude": ["tests/browser/browserUtils.js"], + "output_folder": "tests/browser/output", + + "test_settings": { + + "default": { + "launch_url": "http://localhost:8080", + "webdriver": { + "start_process": true, + "server_path": "./node_modules/.bin/chromedriver", + "port": 9515, + "log_path": "tests/browser/output" + }, + "desiredCapabilities": { + "browserName": "chrome" + }, + "enable_fail_fast": true + }, + + "dev": { + "launch_url": "http://localhost:8080" + }, + + "prod": { + "launch_url": "http://localhost:8000/index.html" + } + + } +} + diff --git a/plugins/srktoolbox/package-lock.json b/plugins/srktoolbox/package-lock.json new file mode 100644 index 00000000..326b961d --- /dev/null +++ b/plugins/srktoolbox/package-lock.json @@ -0,0 +1,24662 @@ +{ + "name": "srktoolbox", + "version": "10.22.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "srktoolbox", + "version": "10.22.1", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "14": "^3.1.6", + "@astronautlabs/amf": "^0.0.6", + "@babel/polyfill": "^7.12.1", + "@blu3r4y/lzma": "^2.3.3", + "@wavesenterprise/crypto-gost-js": "^2.1.0-RC1", + "@xmldom/xmldom": "^0.8.11", + "argon2-browser": "^1.18.0", + "arrive": "^2.5.2", + "assert": "^2.1.0", + "avsc": "^5.7.9", + "bcryptjs": "^2.4.3", + "bignumber.js": "^9.3.1", + "blakejs": "^1.2.1", + "bootstrap": "4.6.2", + "bootstrap-colorpicker": "^3.4.0", + "bootstrap-material-design": "^4.1.3", + "browserify-zlib": "^0.2.0", + "bson": "^4.7.2", + "buffer": "^6.0.3", + "cbor": "9.0.2", + "chi-squared": "^1.1.0", + "codepage": "^1.15.0", + "crypto-api": "^0.8.5", + "crypto-browserify": "^3.12.1", + "crypto-js": "^4.2.0", + "ctph.js": "0.0.5", + "d3": "7.9.0", + "d3-hexbin": "^0.2.2", + "diff": "^5.2.2", + "dompurify": "^3.3.1", + "es6-promisify": "^7.0.0", + "escodegen": "^2.1.0", + "esprima": "^4.0.1", + "events": "^3.3.0", + "exif-parser": "^0.1.12", + "fernet": "^0.3.3", + "file-saver": "^2.0.5", + "flat": "^6.0.1", + "geodesy": "1.1.3", + "handlebars": "^4.7.8", + "hash-wasm": "^4.12.0", + "highlight.js": "^11.11.1", + "ieee754": "^1.2.1", + "jimp": "^1.6.0", + "jq-web": "^0.6.2", + "jquery": "3.7.1", + "js-sha3": "^0.9.3", + "jsesc": "^3.1.0", + "json5": "^2.2.3", + "jsonata": "^2.1.0", + "jsonpath-plus": "^10.4.0", + "jsonwebtoken": "8.5.1", + "jsqr": "^1.4.0", + "jsrsasign": "^11.1.1", + "kbpgp": "^2.1.17", + "libbzip2-wasm": "0.0.4", + "libyara-wasm": "^1.2.1", + "lodash": "^4.17.23", + "loglevel": "^1.9.2", + "loglevel-message-prefix": "^3.0.0", + "lz-string": "^1.5.0", + "lz4js": "^0.2.0", + "markdown-it": "^14.1.1", + "moment": "^2.30.1", + "moment-timezone": "^0.6.0", + "ngeohash": "^0.6.3", + "node-forge": "^1.3.3", + "node-md6": "^0.1.0", + "nodom": "^2.4.0", + "notepack.io": "^3.0.1", + "ntlm": "^0.1.3", + "nwmatcher": "^1.4.4", + "otpauth": "9.3.6", + "path": "^0.12.7", + "popper.js": "^1.16.1", + "process": "^0.11.10", + "protobufjs": "^7.5.4", + "qr-image": "^3.2.0", + "reflect-metadata": "^0.2.2", + "rison": "^0.1.1", + "scryptsy": "^2.1.0", + "snackbarjs": "^1.1.0", + "sortablejs": "^1.15.7", + "split.js": "^1.6.5", + "ssdeep.js": "0.0.3", + "stream-browserify": "^3.0.0", + "tesseract.js": "5.1.1", + "toastr": "^2.1.4", + "ua-parser-js": "^1.0.41", + "unorm": "^1.6.0", + "url": "^0.11.4", + "utf8": "^3.0.0", + "uuid": "^13.0.0", + "vkbeautify": "^0.99.3", + "xpath": "0.0.34", + "xregexp": "^5.1.2", + "zlibjs": "^0.3.1" + }, + "devDependencies": { + "@babel/core": "^7.29.0", + "@babel/eslint-parser": "^7.28.6", + "@babel/plugin-syntax-import-assertions": "^7.28.6", + "@babel/plugin-transform-runtime": "^7.29.0", + "@babel/preset-env": "^7.29.0", + "@babel/runtime": "^7.28.6", + "@codemirror/commands": "^6.10.2", + "@codemirror/language": "^6.12.1", + "@codemirror/search": "^6.6.0", + "@codemirror/state": "^6.5.4", + "@codemirror/view": "^6.39.15", + "autoprefixer": "^10.4.24", + "babel-loader": "^10.0.0", + "babel-plugin-dynamic-import-node": "^2.3.3", + "babel-plugin-transform-builtin-extend": "1.1.2", + "base64-loader": "^1.0.0", + "chromedriver": "^143.0.4", + "cli-progress": "^3.12.0", + "colors": "^1.4.0", + "compression-webpack-plugin": "^11.1.0", + "copy-webpack-plugin": "^13.0.1", + "core-js": "^3.48.0", + "cspell": "^8.19.4", + "css-loader": "7.1.4", + "eslint": "^9.39.3", + "eslint-plugin-jsdoc": "^48.11.0", + "globals": "^15.15.0", + "grunt": "^1.6.1", + "grunt-chmod": "~1.1.1", + "grunt-concurrent": "^3.0.0", + "grunt-contrib-clean": "~2.0.1", + "grunt-contrib-connect": "^5.0.1", + "grunt-contrib-copy": "~1.0.0", + "grunt-contrib-watch": "^1.1.0", + "grunt-eslint": "^25.0.0", + "grunt-exec": "~3.0.0", + "grunt-webpack": "^6.0.0", + "grunt-zip": "^1.0.0", + "html-webpack-plugin": "^5.6.6", + "imports-loader": "^5.0.0", + "mini-css-extract-plugin": "2.10.0", + "modify-source-webpack-plugin": "^4.1.0", + "nightwatch": "^3.15.0", + "postcss": "^8.5.6", + "postcss-css-variables": "^0.19.0", + "postcss-import": "^16.1.1", + "postcss-loader": "^8.2.1", + "prompt": "^1.3.0", + "sitemap": "^8.0.2", + "terser": "^5.46.0", + "webpack": "^5.105.2", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "5.0.4", + "webpack-node-externals": "^3.0.0", + "worker-loader": "^3.0.8" + } + }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", + "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@astronautlabs/amf": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@astronautlabs/amf/-/amf-0.0.6.tgz", + "integrity": "sha512-cJgbXW45TIDLQf2hiHqDoRfmeRy5u9Z4npr7sZfBThvbp5cbqDieTWaJTu91cUAj35/u87OHZijLTbMO18ZIow==", + "license": "MIT", + "dependencies": { + "@astronautlabs/bitstream": "^4.0.0" + }, + "engines": { + "node": "^14" + } + }, + "node_modules/@astronautlabs/amf/node_modules/@astronautlabs/bitstream": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@astronautlabs/bitstream/-/bitstream-4.2.2.tgz", + "integrity": "sha512-/D18Aua0Er95TkulkVBXK5oweh55tXlgpug7g2cKdUvVBT91k2YD9n1RYnbrfaaHIN+KVDaBIrf3j9dS3DhzXw==", + "license": "MIT", + "peerDependencies": { + "reflect-metadata": "^0.1.13" + } + }, + "node_modules/@astronautlabs/amf/node_modules/reflect-metadata": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==", + "license": "Apache-2.0", + "peer": true + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz", + "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/eslint-parser": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.28.6.tgz", + "integrity": "sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.3.tgz", + "integrity": "sha512-RpLYy2sb51oNLjuu1iD3bwBqCBWUzjO0ocp+iaCP/lJtb2CPLcnC2Fftw+4sAzaMELGeWTgExSKADbdo0GFVzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.29.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", + "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "regexpu-core": "^6.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.11" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", + "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-wrap-function": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", + "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", + "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", + "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.3.tgz", + "integrity": "sha512-SRS46DFR4HqzUzCVgi90/xMoL+zeBDBvWdKYXSEzh79kXswNFEglUpMKxR04//dPqwYXWUBJ3mpUd933ru9Kmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", + "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", + "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", + "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.0.tgz", + "integrity": "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", + "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-remap-async-to-generator": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", + "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", + "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", + "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", + "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", + "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-globals": "^7.28.0", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-replace-supers": "^7.28.6", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", + "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/template": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", + "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", + "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", + "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz", + "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", + "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", + "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", + "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", + "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", + "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", + "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", + "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", + "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", + "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", + "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", + "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", + "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.29.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz", + "integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.29.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", + "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz", + "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", + "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", + "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", + "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", + "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", + "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", + "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", + "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", + "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", + "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", + "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz", + "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", + "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", + "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.0.tgz", + "integrity": "sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", + "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", + "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", + "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", + "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", + "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", + "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", + "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", + "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/polyfill": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz", + "integrity": "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==", + "deprecated": "🚨 This package has been deprecated in favor of separate inclusion of a polyfill and regenerator-runtime (when needed). See the @babel/polyfill docs (https://babeljs.io/docs/en/babel-polyfill) for more information.", + "license": "MIT", + "dependencies": { + "core-js": "^2.6.5", + "regenerator-runtime": "^0.13.4" + } + }, + "node_modules/@babel/polyfill/node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true, + "license": "MIT" + }, + "node_modules/@babel/preset-env": { + "version": "7.29.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.5.tgz", + "integrity": "sha512-/69t2aEzGKHD76DyLbHysF/QH2LJOB8iFnYO37unDTKBTubzcMRv0f3H5EiN1Q6ajOd/eB7dAInF0qdFVS06kA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.3", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.3", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.28.6", + "@babel/plugin-syntax-import-attributes": "^7.28.6", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.29.0", + "@babel/plugin-transform-async-to-generator": "^7.28.6", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.6", + "@babel/plugin-transform-class-properties": "^7.28.6", + "@babel/plugin-transform-class-static-block": "^7.28.6", + "@babel/plugin-transform-classes": "^7.28.6", + "@babel/plugin-transform-computed-properties": "^7.28.6", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-dotall-regex": "^7.28.6", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.0", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.6", + "@babel/plugin-transform-exponentiation-operator": "^7.28.6", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.28.6", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.28.6", + "@babel/plugin-transform-modules-systemjs": "^7.29.4", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", + "@babel/plugin-transform-numeric-separator": "^7.28.6", + "@babel/plugin-transform-object-rest-spread": "^7.28.6", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.28.6", + "@babel/plugin-transform-optional-chaining": "^7.28.6", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/plugin-transform-private-methods": "^7.28.6", + "@babel/plugin-transform-private-property-in-object": "^7.28.6", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.29.0", + "@babel/plugin-transform-regexp-modifiers": "^7.28.6", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.28.6", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.28.6", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.29.2.tgz", + "integrity": "sha512-Lc94FOD5+0aXhdb0Tdg3RUtqT6yWbI/BbFWvlaSJ3gAb9Ks+99nHRDKADVqC37er4eCB0fHyWT+y+K3QOvJKbw==", + "license": "MIT", + "dependencies": { + "core-js-pure": "^3.48.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bazel/runfiles": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@bazel/runfiles/-/runfiles-6.5.0.tgz", + "integrity": "sha512-RzahvqTkfpY2jsDxo8YItPX+/iZ6hbiikw1YhE0bA9EKBR5Og8Pa6FHn9PO9M0zaXRVsr0GFQLKbB/0rzy9SzA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@blu3r4y/lzma": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@blu3r4y/lzma/-/lzma-2.3.3.tgz", + "integrity": "sha512-2ckRSsYewLAgq/s8tUW3o5gurtCNYga1f9l0egV4QlT8hgVEilQHRt18s+behmPL2M/BPBxUINaOz67u++r0wA==", + "license": "MIT", + "bin": { + "lzma.js": "bin/lzma.js" + } + }, + "node_modules/@borewit/text-codec": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.2.2.tgz", + "integrity": "sha512-DDaRehssg1aNrH4+2hnj1B7vnUGEjU6OIlyRdkMd0aUdIUvKXrJfXsy8LVtXAy7DRvYVluWbMspsRhz2lcW0mQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.3.tgz", + "integrity": "sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.6.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.3.tgz", + "integrity": "sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.5.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/search": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.7.0.tgz", + "integrity": "sha512-ZvGm99wc/s2cITtMT15LFdn8aH/aS+V+DqyGq/N5ZlV5vWtH+nILvC2nw0zX7ByNoHHDZ2IxxdW38O0tc5nVHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.37.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.6.0.tgz", + "integrity": "sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.42.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.42.1.tgz", + "integrity": "sha512-ToN3oFc0nsxNUYVF5P0ztLgbC4UPPjPtA9aKYhkOKQaZASpOUo6ISXyQLP66ctVwlDc+j6Jv0uK5IFALkiXztg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@codemirror/state": "^6.6.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@cspell/cspell-bundled-dicts": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-8.19.4.tgz", + "integrity": "sha512-2ZRcZP/ncJ5q953o8i+R0fb8+14PDt5UefUNMrFZZHvfTI0jukAASOQeLY+WT6ASZv6CgbPrApAdbppy9FaXYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/dict-ada": "^4.1.0", + "@cspell/dict-al": "^1.1.0", + "@cspell/dict-aws": "^4.0.10", + "@cspell/dict-bash": "^4.2.0", + "@cspell/dict-companies": "^3.1.15", + "@cspell/dict-cpp": "^6.0.8", + "@cspell/dict-cryptocurrencies": "^5.0.4", + "@cspell/dict-csharp": "^4.0.6", + "@cspell/dict-css": "^4.0.17", + "@cspell/dict-dart": "^2.3.0", + "@cspell/dict-data-science": "^2.0.8", + "@cspell/dict-django": "^4.1.4", + "@cspell/dict-docker": "^1.1.13", + "@cspell/dict-dotnet": "^5.0.9", + "@cspell/dict-elixir": "^4.0.7", + "@cspell/dict-en_us": "^4.4.3", + "@cspell/dict-en-common-misspellings": "^2.0.10", + "@cspell/dict-en-gb": "1.1.33", + "@cspell/dict-filetypes": "^3.0.11", + "@cspell/dict-flutter": "^1.1.0", + "@cspell/dict-fonts": "^4.0.4", + "@cspell/dict-fsharp": "^1.1.0", + "@cspell/dict-fullstack": "^3.2.6", + "@cspell/dict-gaming-terms": "^1.1.1", + "@cspell/dict-git": "^3.0.4", + "@cspell/dict-golang": "^6.0.20", + "@cspell/dict-google": "^1.0.8", + "@cspell/dict-haskell": "^4.0.5", + "@cspell/dict-html": "^4.0.11", + "@cspell/dict-html-symbol-entities": "^4.0.3", + "@cspell/dict-java": "^5.0.11", + "@cspell/dict-julia": "^1.1.0", + "@cspell/dict-k8s": "^1.0.10", + "@cspell/dict-kotlin": "^1.1.0", + "@cspell/dict-latex": "^4.0.3", + "@cspell/dict-lorem-ipsum": "^4.0.4", + "@cspell/dict-lua": "^4.0.7", + "@cspell/dict-makefile": "^1.0.4", + "@cspell/dict-markdown": "^2.0.10", + "@cspell/dict-monkeyc": "^1.0.10", + "@cspell/dict-node": "^5.0.7", + "@cspell/dict-npm": "^5.2.1", + "@cspell/dict-php": "^4.0.14", + "@cspell/dict-powershell": "^5.0.14", + "@cspell/dict-public-licenses": "^2.0.13", + "@cspell/dict-python": "^4.2.17", + "@cspell/dict-r": "^2.1.0", + "@cspell/dict-ruby": "^5.0.8", + "@cspell/dict-rust": "^4.0.11", + "@cspell/dict-scala": "^5.0.7", + "@cspell/dict-shell": "^1.1.0", + "@cspell/dict-software-terms": "^5.0.5", + "@cspell/dict-sql": "^2.2.0", + "@cspell/dict-svelte": "^1.0.6", + "@cspell/dict-swift": "^2.0.5", + "@cspell/dict-terraform": "^1.1.1", + "@cspell/dict-typescript": "^3.2.1", + "@cspell/dict-vue": "^3.0.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/cspell-json-reporter": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-json-reporter/-/cspell-json-reporter-8.19.4.tgz", + "integrity": "sha512-pOlUtLUmuDdTIOhDTvWxxta0Wm8RCD/p1V0qUqeP6/Ups1ajBI4FWEpRFd7yMBTUHeGeSNicJX5XeX7wNbAbLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-types": "8.19.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/cspell-pipe": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-pipe/-/cspell-pipe-8.19.4.tgz", + "integrity": "sha512-GNAyk+7ZLEcL2fCMT5KKZprcdsq3L1eYy3e38/tIeXfbZS7Sd1R5FXUe6CHXphVWTItV39TvtLiDwN/2jBts9A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/cspell-resolver": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-resolver/-/cspell-resolver-8.19.4.tgz", + "integrity": "sha512-S8vJMYlsx0S1D60glX8H2Jbj4mD8519VjyY8lu3fnhjxfsl2bDFZvF3ZHKsLEhBE+Wh87uLqJDUJQiYmevHjDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-directory": "^4.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/cspell-service-bus": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-service-bus/-/cspell-service-bus-8.19.4.tgz", + "integrity": "sha512-uhY+v8z5JiUogizXW2Ft/gQf3eWrh5P9036jN2Dm0UiwEopG/PLshHcDjRDUiPdlihvA0RovrF0wDh4ptcrjuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/cspell-types": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/@cspell/cspell-types/-/cspell-types-8.19.4.tgz", + "integrity": "sha512-ekMWuNlFiVGfsKhfj4nmc8JCA+1ZltwJgxiKgDuwYtR09ie340RfXFF6YRd2VTW5zN7l4F1PfaAaPklVz6utSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/dict-ada": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-ada/-/dict-ada-4.1.1.tgz", + "integrity": "sha512-E+0YW9RhZod/9Qy2gxfNZiHJjCYFlCdI69br1eviQQWB8yOTJX0JHXLs79kOYhSW0kINPVUdvddEBe6Lu6CjGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-al": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-al/-/dict-al-1.1.1.tgz", + "integrity": "sha512-sD8GCaZetgQL4+MaJLXqbzWcRjfKVp8x+px3HuCaaiATAAtvjwUQ5/Iubiqwfd1boIh2Y1/3EgM3TLQ7Q8e0wQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-aws": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-aws/-/dict-aws-4.0.17.tgz", + "integrity": "sha512-ORcblTWcdlGjIbWrgKF+8CNEBQiLVKdUOFoTn0KPNkAYnFcdPP0muT4892h7H4Xafh3j72wqB4/loQ6Nti9E/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-bash": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-bash/-/dict-bash-4.2.2.tgz", + "integrity": "sha512-kyWbwtX3TsCf5l49gGQIZkRLaB/P8g73GDRm41Zu8Mv51kjl2H7Au0TsEvHv7jzcsRLS6aUYaZv6Zsvk1fOz+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/dict-shell": "1.1.2" + } + }, + "node_modules/@cspell/dict-companies": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/@cspell/dict-companies/-/dict-companies-3.2.11.tgz", + "integrity": "sha512-0cmafbcz2pTHXLd59eLR1gvDvN6aWAOM0+cIL4LLF9GX9yB2iKDNrKsvs4tJRqutoaTdwNFBbV0FYv+6iCtebQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-cpp": { + "version": "6.0.15", + "resolved": "https://registry.npmjs.org/@cspell/dict-cpp/-/dict-cpp-6.0.15.tgz", + "integrity": "sha512-N7MKK3llRNoBncygvrnLaGvmjo4xzVr5FbtAc9+MFGHK6/LeSySBupr1FM72XDaVSIsmBEe7sDYCHHwlI9Jb2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-cryptocurrencies": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.5.tgz", + "integrity": "sha512-R68hYYF/rtlE6T/dsObStzN5QZw+0aQBinAXuWCVqwdS7YZo0X33vGMfChkHaiCo3Z2+bkegqHlqxZF4TD3rUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-csharp": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-csharp/-/dict-csharp-4.0.8.tgz", + "integrity": "sha512-qmk45pKFHSxckl5mSlbHxmDitSsGMlk/XzFgt7emeTJWLNSTUK//MbYAkBNRtfzB4uD7pAFiKgpKgtJrTMRnrQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-css": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-css/-/dict-css-4.1.1.tgz", + "integrity": "sha512-y/Vgo6qY08e1t9OqR56qjoFLBCpi4QfWMf2qzD1l9omRZwvSMQGRPz4x0bxkkkU4oocMAeztjzCsmLew//c/8w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-dart": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-dart/-/dict-dart-2.3.2.tgz", + "integrity": "sha512-sUiLW56t9gfZcu8iR/5EUg+KYyRD83Cjl3yjDEA2ApVuJvK1HhX+vn4e4k4YfjpUQMag8XO2AaRhARE09+/rqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-data-science": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-data-science/-/dict-data-science-2.0.13.tgz", + "integrity": "sha512-l1HMEhBJkPmw4I2YGVu2eBSKM89K9pVF+N6qIr5Uo5H3O979jVodtuwP8I7LyPrJnC6nz28oxeGRCLh9xC5CVA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-django": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-django/-/dict-django-4.1.6.tgz", + "integrity": "sha512-SdbSFDGy9ulETqNz15oWv2+kpWLlk8DJYd573xhIkeRdcXOjskRuxjSZPKfW7O3NxN/KEf3gm3IevVOiNuFS+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-docker": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/@cspell/dict-docker/-/dict-docker-1.1.17.tgz", + "integrity": "sha512-OcnVTIpHIYYKhztNTyK8ShAnXTfnqs43hVH6p0py0wlcwRIXe5uj4f12n7zPf2CeBI7JAlPjEsV0Rlf4hbz/xQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-dotnet": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/@cspell/dict-dotnet/-/dict-dotnet-5.0.13.tgz", + "integrity": "sha512-xPp7jMnFpOri7tzmqmm/dXMolXz1t2bhNqxYkOyMqXhvs08oc7BFs+EsbDY0X7hqiISgeFZGNqn0dOCr+ncPYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-elixir": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-elixir/-/dict-elixir-4.0.8.tgz", + "integrity": "sha512-CyfphrbMyl4Ms55Vzuj+mNmd693HjBFr9hvU+B2YbFEZprE5AG+EXLYTMRWrXbpds4AuZcvN3deM2XVB80BN/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-en_us": { + "version": "4.4.33", + "resolved": "https://registry.npmjs.org/@cspell/dict-en_us/-/dict-en_us-4.4.33.tgz", + "integrity": "sha512-zWftVqfUStDA37wO1ZNDN1qMJOfcxELa8ucHW8W8wBAZY3TK5Nb6deLogCK/IJi/Qljf30dwwuqqv84Qqle9Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-en-common-misspellings": { + "version": "2.1.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.1.12.tgz", + "integrity": "sha512-14Eu6QGqyksqOd4fYPuRb58lK1Va7FQK9XxFsRKnZU8LhL3N+kj7YKDW+7aIaAN/0WGEqslGP6lGbQzNti8Akw==", + "dev": true, + "license": "CC BY-SA 4.0" + }, + "node_modules/@cspell/dict-en-gb": { + "version": "1.1.33", + "resolved": "https://registry.npmjs.org/@cspell/dict-en-gb/-/dict-en-gb-1.1.33.tgz", + "integrity": "sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-filetypes": { + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/@cspell/dict-filetypes/-/dict-filetypes-3.0.18.tgz", + "integrity": "sha512-yU7RKD/x1IWmDLzWeiItMwgV+6bUcU/af23uS0+uGiFUbsY1qWV/D4rxlAAO6Z7no3J2z8aZOkYIOvUrJq0Rcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-flutter": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-flutter/-/dict-flutter-1.1.1.tgz", + "integrity": "sha512-UlOzRcH2tNbFhZmHJN48Za/2/MEdRHl2BMkCWZBYs+30b91mWvBfzaN4IJQU7dUZtowKayVIF9FzvLZtZokc5A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-fonts": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-fonts/-/dict-fonts-4.0.6.tgz", + "integrity": "sha512-aR/0csY01dNb0A1tw/UmN9rKgHruUxsYsvXu6YlSBJFu60s26SKr/k1o4LavpHTQ+lznlYMqAvuxGkE4Flliqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-fsharp": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-fsharp/-/dict-fsharp-1.1.1.tgz", + "integrity": "sha512-imhs0u87wEA4/cYjgzS0tAyaJpwG7vwtC8UyMFbwpmtw+/bgss+osNfyqhYRyS/ehVCWL17Ewx2UPkexjKyaBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-fullstack": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-fullstack/-/dict-fullstack-3.2.9.tgz", + "integrity": "sha512-diZX+usW5aZ4/b2T0QM/H/Wl9aNMbdODa1Jq0ReBr/jazmNeWjd+PyqeVgzd1joEaHY+SAnjrf/i9CwKd2ZtWQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-gaming-terms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.1.2.tgz", + "integrity": "sha512-9XnOvaoTBscq0xuD6KTEIkk9hhdfBkkvJAIsvw3JMcnp1214OCGW8+kako5RqQ2vTZR3Tnf3pc57o7VgkM0q1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-git": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@cspell/dict-git/-/dict-git-3.1.0.tgz", + "integrity": "sha512-KEt9zGkxqGy2q1nwH4CbyqTSv5nadpn8BAlDnzlRcnL0Xb3LX9xTgSGShKvzb0bw35lHoYyLWN2ZKAqbC4pgGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-golang": { + "version": "6.0.26", + "resolved": "https://registry.npmjs.org/@cspell/dict-golang/-/dict-golang-6.0.26.tgz", + "integrity": "sha512-YKA7Xm5KeOd14v5SQ4ll6afe9VSy3a2DWM7L9uBq4u3lXToRBQ1W5PRa+/Q9udd+DTURyVVnQ+7b9cnOlNxaRg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-google": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-google/-/dict-google-1.0.9.tgz", + "integrity": "sha512-biL65POqialY0i4g6crj7pR6JnBkbsPovB2WDYkj3H4TuC/QXv7Pu5pdPxeUJA6TSCHI7T5twsO4VSVyRxD9CA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-haskell": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-haskell/-/dict-haskell-4.0.6.tgz", + "integrity": "sha512-ib8SA5qgftExpYNjWhpYIgvDsZ/0wvKKxSP+kuSkkak520iPvTJumEpIE+qPcmJQo4NzdKMN8nEfaeci4OcFAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-html": { + "version": "4.0.15", + "resolved": "https://registry.npmjs.org/@cspell/dict-html/-/dict-html-4.0.15.tgz", + "integrity": "sha512-GJYnYKoD9fmo2OI0aySEGZOjThnx3upSUvV7mmqUu8oG+mGgzqm82P/f7OqsuvTaInZZwZbo+PwJQd/yHcyFIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-html-symbol-entities": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.5.tgz", + "integrity": "sha512-429alTD4cE0FIwpMucvSN35Ld87HCyuM8mF731KU5Rm4Je2SG6hmVx7nkBsLyrmH3sQukTcr1GaiZsiEg8svPA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-java": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-java/-/dict-java-5.0.12.tgz", + "integrity": "sha512-qPSNhTcl7LGJ5Qp6VN71H8zqvRQK04S08T67knMq9hTA8U7G1sTKzLmBaDOFhq17vNX/+rT+rbRYp+B5Nwza1A==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-julia": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-julia/-/dict-julia-1.1.1.tgz", + "integrity": "sha512-WylJR9TQ2cgwd5BWEOfdO3zvDB+L7kYFm0I9u0s9jKHWQ6yKmfKeMjU9oXxTBxIufhCXm92SKwwVNAC7gjv+yA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-k8s": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-k8s/-/dict-k8s-1.0.12.tgz", + "integrity": "sha512-2LcllTWgaTfYC7DmkMPOn9GsBWsA4DZdlun4po8s2ysTP7CPEnZc1ZfK6pZ2eI4TsZemlUQQ+NZxMe9/QutQxg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-kotlin": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-kotlin/-/dict-kotlin-1.1.1.tgz", + "integrity": "sha512-J3NzzfgmxRvEeOe3qUXnSJQCd38i/dpF9/t3quuWh6gXM+krsAXP75dY1CzDmS8mrJAlBdVBeAW5eAZTD8g86Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-latex": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@cspell/dict-latex/-/dict-latex-4.0.4.tgz", + "integrity": "sha512-YdTQhnTINEEm/LZgTzr9Voz4mzdOXH7YX+bSFs3hnkUHCUUtX/mhKgf1CFvZ0YNM2afjhQcmLaR9bDQVyYBvpA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-lorem-ipsum": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-lorem-ipsum/-/dict-lorem-ipsum-4.0.5.tgz", + "integrity": "sha512-9a4TJYRcPWPBKkQAJ/whCu4uCAEgv/O2xAaZEI0n4y1/l18Yyx8pBKoIX5QuVXjjmKEkK7hi5SxyIsH7pFEK9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-lua": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/@cspell/dict-lua/-/dict-lua-4.0.8.tgz", + "integrity": "sha512-N4PkgNDMu9JVsRu7JBS/3E/dvfItRgk9w5ga2dKq+JupP2Y3lojNaAVFhXISh4Y0a6qXDn2clA6nvnavQ/jjLA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-makefile": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-makefile/-/dict-makefile-1.0.5.tgz", + "integrity": "sha512-4vrVt7bGiK8Rx98tfRbYo42Xo2IstJkAF4tLLDMNQLkQ86msDlYSKG1ZCk8Abg+EdNcFAjNhXIiNO+w4KflGAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-markdown": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-markdown/-/dict-markdown-2.0.16.tgz", + "integrity": "sha512-976RRqKv6cwhrxdFCQP2DdnBVB86BF57oQtPHy4Zbf4jF/i2Oy29MCrxirnOBalS1W6KQeto7NdfDXRAwkK4PQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@cspell/dict-css": "^4.1.1", + "@cspell/dict-html": "^4.0.15", + "@cspell/dict-html-symbol-entities": "^4.0.5", + "@cspell/dict-typescript": "^3.2.3" + } + }, + "node_modules/@cspell/dict-monkeyc": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.12.tgz", + "integrity": "sha512-MN7Vs11TdP5mbdNFQP5x2Ac8zOBm97ARg6zM5Sb53YQt/eMvXOMvrep7+/+8NJXs0jkp70bBzjqU4APcqBFNAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-node": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-node/-/dict-node-5.0.9.tgz", + "integrity": "sha512-hO+ga+uYZ/WA4OtiMEyKt5rDUlUyu3nXMf8KVEeqq2msYvAPdldKBGH7lGONg6R/rPhv53Rb+0Y1SLdoK1+7wQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-npm": { + "version": "5.2.38", + "resolved": "https://registry.npmjs.org/@cspell/dict-npm/-/dict-npm-5.2.38.tgz", + "integrity": "sha512-21ucGRPYYhr91C2cDBoMPTrcIOStQv33xOqJB0JLoC5LAs2Sfj9EoPGhGb+gIFVHz6Ia7JQWE2SJsOVFJD1wmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-php": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-php/-/dict-php-4.1.1.tgz", + "integrity": "sha512-EXelI+4AftmdIGtA8HL8kr4WlUE11OqCSVlnIgZekmTkEGSZdYnkFdiJ5IANSALtlQ1mghKjz+OFqVs6yowgWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-powershell": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/@cspell/dict-powershell/-/dict-powershell-5.0.15.tgz", + "integrity": "sha512-l4S5PAcvCFcVDMJShrYD0X6Huv9dcsQPlsVsBGbH38wvuN7gS7+GxZFAjTNxDmTY1wrNi1cCatSg6Pu2BW4rgg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-public-licenses": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.16.tgz", + "integrity": "sha512-EQRrPvEOmwhwWezV+W7LjXbIBjiy6y/shrET6Qcpnk3XANTzfvWflf9PnJ5kId/oKWvihFy0za0AV1JHd03pSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-python": { + "version": "4.2.26", + "resolved": "https://registry.npmjs.org/@cspell/dict-python/-/dict-python-4.2.26.tgz", + "integrity": "sha512-hbjN6BjlSgZOG2dA2DtvYNGBM5Aq0i0dHaZjMOI9K/9vRicVvKbcCiBSSrR3b+jwjhQL5ff7HwG5xFaaci0GQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/dict-data-science": "^2.0.13" + } + }, + "node_modules/@cspell/dict-r": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-r/-/dict-r-2.1.1.tgz", + "integrity": "sha512-71Ka+yKfG4ZHEMEmDxc6+blFkeTTvgKbKAbwiwQAuKl3zpqs1Y0vUtwW2N4b3LgmSPhV3ODVY0y4m5ofqDuKMw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-ruby": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-ruby/-/dict-ruby-5.1.1.tgz", + "integrity": "sha512-LHrp84oEV6q1ZxPPyj4z+FdKyq1XAKYPtmGptrd+uwHbrF/Ns5+fy6gtSi7pS+uc0zk3JdO9w/tPK+8N1/7WUA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-rust": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-rust/-/dict-rust-4.1.2.tgz", + "integrity": "sha512-O1FHrumYcO+HZti3dHfBPUdnDFkI+nbYK3pxYmiM1sr+G0ebOd6qchmswS0Wsc6ZdEVNiPYJY/gZQR6jfW3uOg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-scala": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@cspell/dict-scala/-/dict-scala-5.0.9.tgz", + "integrity": "sha512-AjVcVAELgllybr1zk93CJ5wSUNu/Zb5kIubymR/GAYkMyBdYFCZ3Zbwn4Zz8GJlFFAbazABGOu0JPVbeY59vGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-shell": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-shell/-/dict-shell-1.1.2.tgz", + "integrity": "sha512-WqOUvnwcHK1X61wAfwyXq04cn7KYyskg90j4lLg3sGGKMW9Sq13hs91pqrjC44Q+lQLgCobrTkMDw9Wyl9nRFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-software-terms": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@cspell/dict-software-terms/-/dict-software-terms-5.2.2.tgz", + "integrity": "sha512-0CaYd6TAsKtEoA7tNswm1iptEblTzEe3UG8beG2cpSTHk7afWIVMtJLgXDv0f/Li67Lf3Z1Jf3JeXR7GsJ2TRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-sql": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@cspell/dict-sql/-/dict-sql-2.2.1.tgz", + "integrity": "sha512-qDHF8MpAYCf4pWU8NKbnVGzkoxMNrFqBHyG/dgrlic5EQiKANCLELYtGlX5auIMDLmTf1inA0eNtv74tyRJ/vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-svelte": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@cspell/dict-svelte/-/dict-svelte-1.0.7.tgz", + "integrity": "sha512-hGZsGqP0WdzKkdpeVLBivRuSNzOTvN036EBmpOwxH+FTY2DuUH7ecW+cSaMwOgmq5JFSdTcbTNFlNC8HN8lhaQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-swift": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@cspell/dict-swift/-/dict-swift-2.0.6.tgz", + "integrity": "sha512-PnpNbrIbex2aqU1kMgwEKvCzgbkHtj3dlFLPMqW1vSniop7YxaDTtvTUO4zA++ugYAEL+UK8vYrBwDPTjjvSnA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-terraform": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-terraform/-/dict-terraform-1.1.3.tgz", + "integrity": "sha512-gr6wxCydwSFyyBKhBA2xkENXtVFToheqYYGFvlMZXWjviynXmh+NK/JTvTCk/VHk3+lzbO9EEQKee6VjrAUSbA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-typescript": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@cspell/dict-typescript/-/dict-typescript-3.2.3.tgz", + "integrity": "sha512-zXh1wYsNljQZfWWdSPYwQhpwiuW0KPW1dSd8idjMRvSD0aSvWWHoWlrMsmZeRl4qM4QCEAjua8+cjflm41cQBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dict-vue": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@cspell/dict-vue/-/dict-vue-3.0.5.tgz", + "integrity": "sha512-Mqutb8jbM+kIcywuPQCCaK5qQHTdaByoEO2J9LKFy3sqAdiBogNkrplqUK0HyyRFgCfbJUgjz3N85iCMcWH0JA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cspell/dynamic-import": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/@cspell/dynamic-import/-/dynamic-import-8.19.4.tgz", + "integrity": "sha512-0LLghC64+SiwQS20Sa0VfFUBPVia1rNyo0bYeIDoB34AA3qwguDBVJJkthkpmaP1R2JeR/VmxmJowuARc4ZUxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/url": "8.19.4", + "import-meta-resolve": "^4.1.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@cspell/filetypes": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/@cspell/filetypes/-/filetypes-8.19.4.tgz", + "integrity": "sha512-D9hOCMyfKtKjjqQJB8F80PWsjCZhVGCGUMiDoQpcta0e+Zl8vHgzwaC0Ai4QUGBhwYEawHGiWUd7Y05u/WXiNQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/strong-weak-map": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/@cspell/strong-weak-map/-/strong-weak-map-8.19.4.tgz", + "integrity": "sha512-MUfFaYD8YqVe32SQaYLI24/bNzaoyhdBIFY5pVrvMo1ZCvMl8AlfI2OcBXvcGb5aS5z7sCNCJm11UuoYbLI1zw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@cspell/url": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/@cspell/url/-/url-8.19.4.tgz", + "integrity": "sha512-Pa474iBxS+lxsAL4XkETPGIq3EgMLCEb9agj3hAd2VGMTCApaiUvamR4b+uGXIPybN70piFxvzrfoxsG2uIP6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.1.0", + "@csstools/css-calc": "^2.1.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.46.0.tgz", + "integrity": "sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@gulpjs/messages": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@gulpjs/messages/-/messages-1.1.0.tgz", + "integrity": "sha512-Ys9sazDatyTgZVb4xPlDufLweJ/Os2uHWOv+Caxvy2O85JcnT4M3vc73bi8pdLWlv3fdWQz3pdI9tVwo8rQQSg==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@gulpjs/to-absolute-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@gulpjs/to-absolute-glob/-/to-absolute-glob-4.0.0.tgz", + "integrity": "sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA==", + "license": "MIT", + "dependencies": { + "is-negated-glob": "^1.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@jimp/core": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.1.tgz", + "integrity": "sha512-+BoKC5G6hkrSy501zcJ2EpfnllP+avPevcBfRcZe/CW+EwEfY6X1EZ8QWyT7NpDIvEEJb1fdJnMMfUnFkxmw9A==", + "license": "MIT", + "dependencies": { + "@jimp/file-ops": "1.6.1", + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1", + "await-to-js": "^3.0.0", + "exif-parser": "^0.1.12", + "file-type": "^21.3.3", + "mime": "3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/core/node_modules/file-type": { + "version": "21.3.4", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.3.4.tgz", + "integrity": "sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g==", + "license": "MIT", + "dependencies": { + "@tokenizer/inflate": "^0.4.1", + "strtok3": "^10.3.4", + "token-types": "^6.1.1", + "uint8array-extras": "^1.4.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, + "node_modules/@jimp/core/node_modules/strtok3": { + "version": "10.3.5", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.5.tgz", + "integrity": "sha512-ki4hZQfh5rX0QDLLkOCj+h+CVNkqmp/CMf8v8kZpkNVK6jGQooMytqzLZYUVYIZcFZ6yDB70EfD8POcFXiF5oA==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@jimp/diff": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.1.tgz", + "integrity": "sha512-YkKDPdHjLgo1Api3+Bhc0GLAygldlpt97NfOKoNg1U6IUNXA6X2MgosCjPfSBiSvJvrrz1fsIR+/4cfYXBI/HQ==", + "license": "MIT", + "dependencies": { + "@jimp/plugin-resize": "1.6.1", + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1", + "pixelmatch": "^5.3.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/file-ops": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.1.tgz", + "integrity": "sha512-T+gX6osHjprbDRad0/B71Evyre7ZdVY1z/gFGEG9Z8KOtZPKboWvPeP2UjbZYWQLy9UKCPQX1FNAnDiOPkJL7w==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-bmp": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.1.tgz", + "integrity": "sha512-xzWzNT4/u5zGrTT3Tme9sGU7YzIKxi13+BCQwLqACbt5DXf9SAfdzRkopZQnmDko+6In5nqaT89Gjs43/WdnYQ==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1", + "bmp-ts": "^1.0.9" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-gif": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.1.tgz", + "integrity": "sha512-YjY2W26rQa05XhanYhRZ7dingCiNN+T2Ymb1JiigIbABY0B28wHE3v3Cf1/HZPWGu0hOg36ylaKgV5KxF2M58w==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/types": "1.6.1", + "gifwrap": "^0.10.1", + "omggif": "^1.0.10" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-jpeg": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.1.tgz", + "integrity": "sha512-HT9H3yOmlOFzYmdI15IYdfy6ggQhSRIaHeA+OTJSEORXBqEo97sUZu/DsgHIcX5NJ7TkJBTgZ9BZXsV6UbsyMg==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/types": "1.6.1", + "jpeg-js": "^0.4.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-png": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.1.tgz", + "integrity": "sha512-SZ/KVhI5UjcSzzlXsXdIi/LhJ7UShf2NkMOtVrbZQcGzsqNtynAelrOXeoTxcanfVqmNhAoVHg8yR2cYoqrYjA==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/types": "1.6.1", + "pngjs": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/js-tiff": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.1.tgz", + "integrity": "sha512-jDG/eJquID1M4MBlKMmDRBmz2TpXMv7TUyu2nIRUxhlUc2ogC82T+VQUkca9GJH1BBJ9dx5sSE5dGkWNjIbZxw==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/types": "1.6.1", + "utif2": "^4.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-blit": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.1.tgz", + "integrity": "sha512-MwnI7C7K81uWddY9FLw1fCOIy6SsPIUftUz36Spt7jisCn8/40DhQMlSxpxTNelnZb/2SnloFimQfRZAmHLOqQ==", + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-blur": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.1.tgz", + "integrity": "sha512-lIo7Tzp5jQu30EFFSK/phXANK3citKVEjepDjQ6ljHoIFtuMRrnybnmI2Md24ulvWlDaz+hh3n6qrMb8ydwhZQ==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/utils": "1.6.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-circle": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.1.tgz", + "integrity": "sha512-kK1PavY6cKHNNKce37vdV4Tmpc1/zDKngGoeOV3j+EMatoHFZUinV3s6F9aWryPs3A0xhCLZgdJ6Zeea1d5LCQ==", + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.1", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-color": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.1.tgz", + "integrity": "sha512-LtUN1vAP+LRlZAtTNVhDRSiXx+26Kbz3zJaG6a5k59gQ95jgT5mknnF8lxkHcqJthM4MEk3/tPxkdJpEybyF/A==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1", + "tinycolor2": "^1.6.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-contain": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.1.tgz", + "integrity": "sha512-m0qhrfA8jkTqretGv4w+T/ADFR4GwBpE0sCOC2uJ0dzr44/ddOMsIdrpi89kabqYiPYIrxkgdCVCLm3zn1Vkkg==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/plugin-blit": "1.6.1", + "@jimp/plugin-resize": "1.6.1", + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-cover": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.1.tgz", + "integrity": "sha512-hZytnsth0zoll6cPf434BrT+p/v569Wr5tyO6Dp0dH1IDPhzhB5F38sZGMLDo7bzQiN9JFVB3fxkcJ/WYCJ3Mg==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/plugin-crop": "1.6.1", + "@jimp/plugin-resize": "1.6.1", + "@jimp/types": "1.6.1", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-crop": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.1.tgz", + "integrity": "sha512-EerRSLlclXyKDnYc/H9w/1amZW7b7v3OGi/VlerPd2M/pAu5X8TkyYWtfqYCXnNp1Ixtd8oCo9zGfY9zoXT4rg==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-displace": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.1.tgz", + "integrity": "sha512-K07QVl7xQwIfD6KfxRV/c3E9e7ZBXxUXdWuvoTWcKHL2qV48MOF5Nqbz/aJW4ThnQARIsxvYlZjPFiqkCjlU+g==", + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-dither": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-1.6.1.tgz", + "integrity": "sha512-+2V+GCV2WycMoX1/z977TkZ8Zq/4MVSKElHYatgUqtwXMi2fDK2gKYU2g9V39IqFvTJsTIsK0+58VFz/ROBVew==", + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-fisheye": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.1.tgz", + "integrity": "sha512-XtS5ZyoZ0vxZxJ6gkqI63SivhtI58vX95foMPM+cyzYkRsJXMOYCr8DScxF5bp4Xr003NjYm/P+7+08tibwzHA==", + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-flip": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-1.6.1.tgz", + "integrity": "sha512-ws38W/sGj7LobNRayQ83garxiktOyWxM5vO/y4a/2cy9v65SLEUzVkrj+oeAaUSSObdz4HcCEla7XtGlnAGAaA==", + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.1", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-hash": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-hash/-/plugin-hash-1.6.1.tgz", + "integrity": "sha512-sZt6ZcMX6i8vFWb4GYnw0pR/o9++ef0dTVcboTB5B/g7nrxCODIB4wfEkJ/YqZM5wUvol77K1qeS0/rVO6z21A==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/js-bmp": "1.6.1", + "@jimp/js-jpeg": "1.6.1", + "@jimp/js-png": "1.6.1", + "@jimp/js-tiff": "1.6.1", + "@jimp/plugin-color": "1.6.1", + "@jimp/plugin-resize": "1.6.1", + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1", + "any-base": "^1.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-mask": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-1.6.1.tgz", + "integrity": "sha512-SIG0/FcmEj3tkwFxc7fAGLO8o4uNzMpSOdQOhbCgxefQKq5wOVMk9BQx/sdMPBwtMLr9WLq0GzLA/rk6t2v20A==", + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.1", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-print": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-1.6.1.tgz", + "integrity": "sha512-BYVz/X3Xzv8XYilVeDy11NOp0h7BTDjlOtu0BekIFHP1yHVd24AXNzbOy52XlzYZWQ0Dl36HOHEpl/nSNrzc6w==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/js-jpeg": "1.6.1", + "@jimp/js-png": "1.6.1", + "@jimp/plugin-blit": "1.6.1", + "@jimp/types": "1.6.1", + "parse-bmfont-ascii": "^1.0.6", + "parse-bmfont-binary": "^1.0.6", + "parse-bmfont-xml": "^1.1.6", + "simple-xml-to-json": "^1.2.2", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-quantize": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-quantize/-/plugin-quantize-1.6.1.tgz", + "integrity": "sha512-J2En9PLURfP+vwYDtuZ9T8yBW6BWYZBScydAjRiPBmJfEhTcNQqiiQODrZf7EqbbX/Sy5H6dAeRiqkgoV9N6Ww==", + "license": "MIT", + "dependencies": { + "image-q": "^4.0.0", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-resize": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-1.6.1.tgz", + "integrity": "sha512-CLkrtJoIz2HdWnpYiN6p8KYcPc00rCH/SUu6o+lfZL05Q4uhecJlnvXuj9x+U6mDn3ldPmJj6aZqMHuUJzdVqg==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/types": "1.6.1", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-rotate": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-1.6.1.tgz", + "integrity": "sha512-nOjVjbbj705B02ksysKnh0POAwEBXZtJ9zQ5qC+X7Tavl3JNn+P3BzQovbBxLPSbUSld6XID9z5ijin4PtOAUg==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/plugin-crop": "1.6.1", + "@jimp/plugin-resize": "1.6.1", + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/plugin-threshold": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.1.tgz", + "integrity": "sha512-JOKv9F8s6tnVLf4sB/2fF0F339EFnHvgEdFYugO6VhowKLsap0pEZmLyE/DlRnYtIj2RddHZVxVMp/eKJ04l2Q==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/plugin-color": "1.6.1", + "@jimp/plugin-hash": "1.6.1", + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1", + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/types": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.1.tgz", + "integrity": "sha512-leI7YbveTNi565m910XgIOwXyuu074H5qazAD1357HImJSv2hqxnWXpwxQbadGWZ7goZRYBDZy5lpqud0p7q5w==", + "license": "MIT", + "dependencies": { + "zod": "^3.23.8" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jimp/utils": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.1.tgz", + "integrity": "sha512-veFPRd93FCnS7AgmCkPgARVGoDRrJ9cm1ujuNyA+UfQ5VKbED2002sm5XfFLFwTsKC8j04heTrwe+tU1dluXOw==", + "license": "MIT", + "dependencies": { + "@jimp/types": "1.6.1", + "tinycolor2": "^1.6.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsep-plugin/assignment": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz", + "integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==", + "license": "MIT", + "engines": { + "node": ">= 10.16.0" + }, + "peerDependencies": { + "jsep": "^0.4.0||^1.0.0" + } + }, + "node_modules/@jsep-plugin/regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz", + "integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==", + "license": "MIT", + "engines": { + "node": ">= 10.16.0" + }, + "peerDependencies": { + "jsep": "^0.4.0||^1.0.0" + } + }, + "node_modules/@jsonjoy.com/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/buffers": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-17.67.0.tgz", + "integrity": "sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/codegen": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-1.0.0.tgz", + "integrity": "sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-core": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-core/-/fs-core-4.57.2.tgz", + "integrity": "sha512-SVjwklkpIV5wrynpYtuYnfYH1QF4/nDuLBX7VXdb+3miglcAgBVZb/5y0cOsehRV/9Vb+3UqhkMq3/NR3ztdkQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-fsa": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-fsa/-/fs-fsa-4.57.2.tgz", + "integrity": "sha512-fhO8+iR2I+OCw668ISDJdn1aArc9zx033sWejIyzQ8RBeXa9bDSaUeA3ix0poYOfrj1KdOzytmYNv2/uLDfV6g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node/-/fs-node-4.57.2.tgz", + "integrity": "sha512-nX2AdL6cOFwLdju9G4/nbRnYevmCJbh7N7hvR3gGm97Cs60uEjyd0rpR+YBS7cTg175zzl22pGKXR5USaQMvKg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/fs-print": "4.57.2", + "@jsonjoy.com/fs-snapshot": "4.57.2", + "glob-to-regex.js": "^1.0.0", + "thingies": "^2.5.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-builtins": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-builtins/-/fs-node-builtins-4.57.2.tgz", + "integrity": "sha512-xhiegylRmhw43Ki2HO1ZBL7DQ5ja/qpRsL29VtQ2xuUHiuDGbgf2uD4p9Qd8hJI5P6RCtGYD50IXHXVq/Ocjcg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-to-fsa": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-to-fsa/-/fs-node-to-fsa-4.57.2.tgz", + "integrity": "sha512-18LmWTSONhoAPW+IWRuf8w/+zRolPFGPeGwMxlAhhfY11EKzX+5XHDBPAw67dBF5dxDErHJbl40U+3IXSDRXSQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-fsa": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-node-utils": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-node-utils/-/fs-node-utils-4.57.2.tgz", + "integrity": "sha512-rsPSJgekz43IlNbLyAM/Ab+ouYLWGp5DDBfYBNNEqDaSpsbXfthBn29Q4muFA9L0F+Z3mKo+CWlgSCXrf+mOyQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-builtins": "4.57.2" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-print": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-print/-/fs-print-4.57.2.tgz", + "integrity": "sha512-wK9NSow48i4DbDl9F1CQE5TqnyZOJ04elU3WFG5aJ76p+YxO/ulyBBQvKsessPxdo381Bc2pcEoyPujMOhcRqQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-node-utils": "4.57.2", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/fs-snapshot/-/fs-snapshot-4.57.2.tgz", + "integrity": "sha512-GdduDZuoP5V/QCgJkx9+BZ6SC0EZ/smXAdTS7PfMqgMTGXLlt/bH/FqMYaqB9JmLf05sJPtO0XRbAwwkEEPbVw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^17.65.0", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/json-pack": "^17.65.0", + "@jsonjoy.com/util": "^17.65.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/base64": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-17.67.0.tgz", + "integrity": "sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/codegen": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/codegen/-/codegen-17.67.0.tgz", + "integrity": "sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pack": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-17.67.0.tgz", + "integrity": "sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "17.67.0", + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0", + "@jsonjoy.com/json-pointer": "17.67.0", + "@jsonjoy.com/util": "17.67.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/json-pointer": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-17.67.0.tgz", + "integrity": "sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/util": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/fs-snapshot/node_modules/@jsonjoy.com/util": { + "version": "17.67.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-17.67.0.tgz", + "integrity": "sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "17.67.0", + "@jsonjoy.com/codegen": "17.67.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.21.0.tgz", + "integrity": "sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/base64": "^1.1.2", + "@jsonjoy.com/buffers": "^1.2.0", + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/json-pointer": "^1.0.2", + "@jsonjoy.com/util": "^1.9.0", + "hyperdyperid": "^1.2.0", + "thingies": "^2.5.0", + "tree-dump": "^1.1.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pack/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/json-pointer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pointer/-/json-pointer-1.0.2.tgz", + "integrity": "sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/codegen": "^1.0.0", + "@jsonjoy.com/util": "^1.9.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.9.0.tgz", + "integrity": "sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/buffers": "^1.0.0", + "@jsonjoy.com/codegen": "^1.0.0" + }, + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@jsonjoy.com/util/node_modules/@jsonjoy.com/buffers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jsonjoy.com/buffers/-/buffers-1.2.1.tgz", + "integrity": "sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@lezer/common": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.2.tgz", + "integrity": "sha512-sxQE460fPZyU3sdc8lafxiPwJHBzZRy/udNFynGQky1SePYBdhkBl1kOagA9uT3pxR8K09bOrmTUqA9wb/PjSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@lezer/highlight": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", + "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.3.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.10.tgz", + "integrity": "sha512-rnCpTIBafOx4mRp43xOxDJbFipJm/c0cia/V5TiGlhmMa+wsSdoGmUN3w5Bqrks/09Q/D4tNAmWaT8p6NRi77A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@napi-rs/nice": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice/-/nice-1.1.1.tgz", + "integrity": "sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "optionalDependencies": { + "@napi-rs/nice-android-arm-eabi": "1.1.1", + "@napi-rs/nice-android-arm64": "1.1.1", + "@napi-rs/nice-darwin-arm64": "1.1.1", + "@napi-rs/nice-darwin-x64": "1.1.1", + "@napi-rs/nice-freebsd-x64": "1.1.1", + "@napi-rs/nice-linux-arm-gnueabihf": "1.1.1", + "@napi-rs/nice-linux-arm64-gnu": "1.1.1", + "@napi-rs/nice-linux-arm64-musl": "1.1.1", + "@napi-rs/nice-linux-ppc64-gnu": "1.1.1", + "@napi-rs/nice-linux-riscv64-gnu": "1.1.1", + "@napi-rs/nice-linux-s390x-gnu": "1.1.1", + "@napi-rs/nice-linux-x64-gnu": "1.1.1", + "@napi-rs/nice-linux-x64-musl": "1.1.1", + "@napi-rs/nice-openharmony-arm64": "1.1.1", + "@napi-rs/nice-win32-arm64-msvc": "1.1.1", + "@napi-rs/nice-win32-ia32-msvc": "1.1.1", + "@napi-rs/nice-win32-x64-msvc": "1.1.1" + } + }, + "node_modules/@napi-rs/nice-android-arm-eabi": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm-eabi/-/nice-android-arm-eabi-1.1.1.tgz", + "integrity": "sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-android-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-android-arm64/-/nice-android-arm64-1.1.1.tgz", + "integrity": "sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-darwin-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-arm64/-/nice-darwin-arm64-1.1.1.tgz", + "integrity": "sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-darwin-x64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-darwin-x64/-/nice-darwin-x64-1.1.1.tgz", + "integrity": "sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-freebsd-x64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-freebsd-x64/-/nice-freebsd-x64-1.1.1.tgz", + "integrity": "sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm-gnueabihf": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm-gnueabihf/-/nice-linux-arm-gnueabihf-1.1.1.tgz", + "integrity": "sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-gnu/-/nice-linux-arm64-gnu-1.1.1.tgz", + "integrity": "sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-arm64-musl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-arm64-musl/-/nice-linux-arm64-musl-1.1.1.tgz", + "integrity": "sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-ppc64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-ppc64-gnu/-/nice-linux-ppc64-gnu-1.1.1.tgz", + "integrity": "sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-riscv64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-riscv64-gnu/-/nice-linux-riscv64-gnu-1.1.1.tgz", + "integrity": "sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-s390x-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-s390x-gnu/-/nice-linux-s390x-gnu-1.1.1.tgz", + "integrity": "sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-x64-gnu": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-gnu/-/nice-linux-x64-gnu-1.1.1.tgz", + "integrity": "sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-linux-x64-musl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-linux-x64-musl/-/nice-linux-x64-musl-1.1.1.tgz", + "integrity": "sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-openharmony-arm64": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-openharmony-arm64/-/nice-openharmony-arm64-1.1.1.tgz", + "integrity": "sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-arm64-msvc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-arm64-msvc/-/nice-win32-arm64-msvc-1.1.1.tgz", + "integrity": "sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-ia32-msvc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-ia32-msvc/-/nice-win32-ia32-msvc-1.1.1.tgz", + "integrity": "sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@napi-rs/nice-win32-x64-msvc": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@napi-rs/nice-win32-x64-msvc/-/nice-win32-x64-msvc-1.1.1.tgz", + "integrity": "sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nightwatch/chai": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@nightwatch/chai/-/chai-5.0.3.tgz", + "integrity": "sha512-1OIkOf/7jswOC3/t+Add/HVQO8ib75kz6BVYSNeWGghTlmHUqYEfNJ6vcACbXrn/4v3+9iRlWixuhFkxXkU/RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "1.1.0", + "check-error": "1.0.2", + "deep-eql": "4.0.1", + "loupe": "^2.3.7", + "pathval": "1.1.1", + "type-detect": "4.0.8" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@nightwatch/html-reporter-template": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@nightwatch/html-reporter-template/-/html-reporter-template-0.3.0.tgz", + "integrity": "sha512-Mze1z6pmUz2O8N9w1/h3QWz1lzMig45PGyh8PrL9ERs3FxVnIX0RCn37vjZUYiV4wgjZOg41JjdcpriZ3dJxkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@nightwatch/nightwatch-inspector": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@nightwatch/nightwatch-inspector/-/nightwatch-inspector-1.0.1.tgz", + "integrity": "sha512-/ax11EOB4eJXT5VioMztcalbCtsNeuFn6icfT75qPLBmkxLvThePSfyGTys+t9AULUR0ug0wMDMiLV1Oy586Fg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "archiver": "^5.3.1" + } + }, + "node_modules/@noble/hashes": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", + "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.2.tgz", + "integrity": "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz", + "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.1.tgz", + "integrity": "sha512-mnzgDV26ueAvk7rsbt9L7bE0SuAoqyuys/sMMrmVcN5x9VsxpcG3rqAUSgDyLp0UZlmNfIbQ4fHfCtreVBk8Ew==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.1.tgz", + "integrity": "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg==", + "license": "BSD-3-Clause" + }, + "node_modules/@sec-ant/readable-stream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz", + "integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==", + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-6.3.1.tgz", + "integrity": "sha512-FX4MfcifwJyFOI2lPoX7PQxCqx8BG1HCho7WdiXwpEQx1Ycij0JxkfYtGK7yqNScrZGSlt6RE6sw8QYoH7eKnQ==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@testim/chrome-version": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz", + "integrity": "sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tokenizer/inflate": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz", + "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "token-types": "^6.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/@tokenizer/token": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz", + "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==", + "license": "MIT" + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/body-parser": { + "version": "1.19.6", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", + "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/chai": { + "version": "4.3.20", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", + "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/expect": { + "version": "1.20.4", + "resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz", + "integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==", + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz", + "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "^1" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz", + "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/express/node_modules/@types/express-serve-static-core": { + "version": "4.19.8", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz", + "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/http-errors": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz", + "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.17", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz", + "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.2.tgz", + "integrity": "sha512-sokuT28dxf9JT5Kady1fsXOvI4HVpjZa95NKT5y9PNTIrs2AsobR4GFAA90ZG8M+nxVRLysCXsVj6eGC7Vbrlw==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.19.0" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz", + "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/retry": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz", + "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/selenium-webdriver": { + "version": "4.35.5", + "resolved": "https://registry.npmjs.org/@types/selenium-webdriver/-/selenium-webdriver-4.35.5.tgz", + "integrity": "sha512-wCQCjWmahRkUAO7S703UAvBFkxz4o/rjX4T2AOSWKXSi0sTQPsrXxR0GjtFUT0ompedLkYH4R5HO5Urz0hyeog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/ws": "*" + } + }, + "node_modules/@types/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz", + "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz", + "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "<1" + } + }, + "node_modules/@types/serve-static/node_modules/@types/send": { + "version": "0.17.6", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz", + "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, + "node_modules/@types/vinyl": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.12.tgz", + "integrity": "sha512-Sr2fYMBUVGYq8kj3UthXFAu5UN6ZW+rYr4NACjZQJvHvj+c8lYv0CahmZ2P/r7iUkN44gGUBwqxZkrKXYPb7cw==", + "license": "MIT", + "dependencies": { + "@types/expect": "^1.20.4", + "@types/node": "*" + } + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@wavesenterprise/crypto-gost-js": { + "version": "2.1.0-RC1", + "resolved": "https://registry.npmjs.org/@wavesenterprise/crypto-gost-js/-/crypto-gost-js-2.1.0-RC1.tgz", + "integrity": "sha512-liAR3/T/vxnEgNUE00Llt+sDvKYqo+sm/L7tqkJorg2ha3SsplOSXAqpH0t4Ya0gRj8qN8zXqO+WwLCxXXuQcw==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.13", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.13.tgz", + "integrity": "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/14": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/14/-/14-3.1.6.tgz", + "integrity": "sha512-Dy9rp+KQshffwe5NjDudvNNhdvNlgTqwv1crwBIuK0Dq/RrAoY3HmbiTZpuuoE6TX32HEDMgZ93q1mjr76UYRA==", + "license": "ISC", + "dependencies": { + "gulp": "*", + "gulp-concat": "*", + "gulp-imagemin": "*", + "gulp-minify-css": "*", + "gulp-minify-html": "*", + "gulp-rename": "*", + "gulp-uglify": "*" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", + "license": "BSD-3-Clause OR MIT", + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha512-HrgGIZUl8h2EHuZaU9hTR/cU5nhKxpVE1V6kdGsQ8e4zirElJ5fvtfc8N7Q1oq1aatO275i8pUFUCpNWCAnVWw==", + "license": "MIT", + "dependencies": { + "ansi-wrap": "0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "license": "Apache-2.0", + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-to-html": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.7.2.tgz", + "integrity": "sha512-v6MqmEpNlxF+POuyhKkidusCHWWkaLcGRURzivcU3I9tv7k4JVhFcnukrM5Rlk2rUywdZuzYAZ+kbZqWCnfN3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^2.2.0" + }, + "bin": { + "ansi-to-html": "bin/ansi-to-html" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ansi-to-html/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/any-base": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz", + "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==", + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/archive-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-4.0.0.tgz", + "integrity": "sha512-zV4Ky0v1F8dBrdYElwTvQhweQ0P7Kwc1aluqJsYtOBP01jXcWCyW2IEfI1YiqsG+Iy7ZR+o5LF1N+PGECBxHWA==", + "license": "MIT", + "optional": true, + "dependencies": { + "file-type": "^4.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/archive-type/node_modules/file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha512-f2UbFQEk7LXgWpi5ntcO86OeA/cC80fuDDDaX/fZ2ZGel+AF7leRQqBBW1eJNiiQkrZlAoM6P+VYP5P6bOlDEQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/archiver": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "archiver-utils": "^2.1.0", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/archiver-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/archiver/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/argh": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/argh/-/argh-0.1.4.tgz", + "integrity": "sha512-sQN85FUGbEUBLyQiSJp4v8yAHTST2ao1WVXb/L8jkVqQTsypZuJQD0gMVeOLoSZBz21p22izF6HsBQP16QKQtg==", + "license": "MIT" + }, + "node_modules/argon2-browser": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/argon2-browser/-/argon2-browser-1.18.0.tgz", + "integrity": "sha512-ImVAGIItnFnvET1exhsQB7apRztcoC5TnlSqernMJDUjbc/DLq3UEYeXFrLPrlaIl8cVfwnXb6wX2KpFf2zxHw==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/aria-query/node_modules/deep-equal": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aria-query/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha512-LeZY+DZDRnvP7eMuQ6LHfCzUGxAAIViUBliK24P3hWXL6y4SortgR6Nim6xrkfSLlmH0+k+9NYNwVC2s53ZrYQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-slice": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/arrive": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/arrive/-/arrive-2.5.3.tgz", + "integrity": "sha512-FsZjDDxS2BZ1TuGvqhTf8KbGaH0hOx+DS7HhYIvsreCkAuSUFgJ9NUhIC4f3SM3c5T/1he1KAn566GZjzqJarA==", + "license": "MIT" + }, + "node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-done": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-2.0.0.tgz", + "integrity": "sha512-j0s3bzYq9yKIVLKGE/tWlCpa3PfFLcrDZLTSVdnnCTGagXuXBJO4SsY9Xdk/fQBirCkH4evW5xOeJXqlAQFdsw==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.4.4", + "once": "^1.4.0", + "stream-exhaust": "^1.0.2" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/async-settle": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-2.0.0.tgz", + "integrity": "sha512-Obu/KE8FurfQRN6ODdHN9LuXqwC+JFIM9NRyZqJJ4ZfLJmIYN9Rg0/kb+wF70VV5+fJusTMQlJ1t5rF7J/ETdg==", + "license": "MIT", + "dependencies": { + "async-done": "^2.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", + "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.2", + "caniuse-lite": "^1.0.30001787", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/avsc": { + "version": "5.7.9", + "resolved": "https://registry.npmjs.org/avsc/-/avsc-5.7.9.tgz", + "integrity": "sha512-yOA4wFeI7ET3v32Di/sUybQ+ttP20JHSW3mxLuNGeO0uD6PPcvLrIQXSvy/rhJOWU5JrYh7U4OHplWMmtAtjMg==", + "license": "MIT", + "engines": { + "node": ">=0.11" + } + }, + "node_modules/await-to-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz", + "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/axe-core": { + "version": "4.11.4", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.4.tgz", + "integrity": "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axios": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.0.tgz", + "integrity": "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/axios/node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/b4a": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.8.1.tgz", + "integrity": "sha512-aiqre1Nr0B/6DgE2N5vwTc+2/oQZ4Wh1t4NznYY4E00y8LCt6NqdRv81so00oo27D8MVKTpUa/MwUUtBLXCoDw==", + "license": "Apache-2.0", + "peerDependencies": { + "react-native-b4a": "*" + }, + "peerDependenciesMeta": { + "react-native-b4a": { + "optional": true + } + } + }, + "node_modules/babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "node_modules/babel-code-frame/node_modules/js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-loader": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-10.1.1.tgz", + "integrity": "sha512-JwKSzk2kjIe7mgPK+/lyZ2QAaJcpahNAdM+hgR2HI8D0OJVkdj8Rl6J3kaLYki9pwF7P2iWnD8qVv80Lq1ABtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": "^18.20.0 || ^20.10.0 || >=22.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0 || ^8.0.0-beta.1", + "@rspack/core": "^1.0.0 || ^2.0.0-0", + "webpack": ">=5.61.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-runtime": "^6.22.0" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-transform-builtin-extend": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-builtin-extend/-/babel-plugin-transform-builtin-extend-1.1.2.tgz", + "integrity": "sha512-foUQxHjMiLNynzJaBKrIoZfoRY22S620MLafGC5UfnBEwqcBODIFcgwqqzHE8Hj590lbUJCQ2uBo9y08+sYIkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-runtime": "^6.2.0", + "babel-template": "^6.3.0" + } + }, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "node_modules/babel-runtime/node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "dev": true, + "hasInstallScript": true, + "license": "MIT" + }, + "node_modules/babel-runtime/node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "node_modules/babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "node_modules/babel-traverse/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/babel-traverse/node_modules/globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/babel-traverse/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "node_modules/babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true, + "license": "MIT", + "bin": { + "babylon": "bin/babylon.js" + } + }, + "node_modules/bach": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bach/-/bach-2.0.1.tgz", + "integrity": "sha512-A7bvGMGiTOxGMpNupYl9HQTf0FFDNF4VCmks4PJpFyN1AX2pdKuxuwdvUz2Hu388wcgp+OvGFNsumBfFNkR7eg==", + "license": "MIT", + "dependencies": { + "async-done": "^2.0.0", + "async-settle": "^2.0.0", + "now-and-later": "^3.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/bare-events": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", + "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", + "license": "Apache-2.0", + "peerDependencies": { + "bare-abort-controller": "*" + }, + "peerDependenciesMeta": { + "bare-abort-controller": { + "optional": true + } + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/base64-loader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base64-loader/-/base64-loader-1.0.0.tgz", + "integrity": "sha512-p32+F8dg+ANGx7s8QsZS74ZPHfIycmC2yZcoerzFgbersIYWitPbbF39G6SBx3gyvzyLH5nt1ooocxr0IHuWKA==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.29", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz", + "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/basic-auth/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/basic-ftp": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.1.tgz", + "integrity": "sha512-bopVNp6ugyA150DDuZfPFdt1KZ5a94ZDiwX4hMgZDzF+GttD80lEy8kj98kbyhLXnPvhtIo93mdnLIjpCAeeOw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "dev": true, + "license": "MIT" + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", + "license": "MIT" + }, + "node_modules/beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha512-3vqtKL1N45I5dV0RdssXZG7X6pCqQrWPNOlBPZPrd+QkE2HEhR57Z04m0KtpbsZH73j+a3F8UD1TQnn+ExTvIA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bignumber.js": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz", + "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bin-build": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bin-build/-/bin-build-3.0.0.tgz", + "integrity": "sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA==", + "license": "MIT", + "optional": true, + "dependencies": { + "decompress": "^4.0.0", + "download": "^6.2.2", + "execa": "^0.7.0", + "p-map-series": "^1.0.0", + "tempfile": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-build/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/bin-build/node_modules/execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-build/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-build/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "license": "ISC", + "optional": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/bin-build/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", + "optional": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bin-build/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bin-build/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/bin-build/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "license": "ISC", + "optional": true + }, + "node_modules/bin-check": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bin-check/-/bin-check-4.1.0.tgz", + "integrity": "sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA==", + "license": "MIT", + "optional": true, + "dependencies": { + "execa": "^0.7.0", + "executable": "^4.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-check/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/bin-check/node_modules/execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-check/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-check/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "license": "ISC", + "optional": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/bin-check/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", + "optional": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bin-check/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bin-check/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/bin-check/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "license": "ISC", + "optional": true + }, + "node_modules/bin-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-3.1.0.tgz", + "integrity": "sha512-Mkfm4iE1VFt4xd4vH+gx+0/71esbfus2LsnCGe8Pi4mndSPyT+NGES/Eg99jx8/lUGWfu3z2yuB/bt5UB+iVbQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "execa": "^1.0.0", + "find-versions": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/bin-version-check": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-4.0.0.tgz", + "integrity": "sha512-sR631OrhC+1f8Cvs8WyVWOA33Y8tgwjETNPyyD/myRBXLkfS/vl74FmH/lFcRl9KY3zwGh7jFhvyk9vV3/3ilQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "bin-version": "^3.0.0", + "semver": "^5.6.0", + "semver-truncate": "^1.1.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/bin-version-check/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/bin-wrapper": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bin-wrapper/-/bin-wrapper-4.1.0.tgz", + "integrity": "sha512-hfRmo7hWIXPkbpi0ZltboCMVrU+0ClXR/JgbCKKjlDjQf6igXa7OwdqNcFWQZPZTgiY7ZpzE3+LjjkLiTN2T7Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "bin-check": "^4.1.0", + "bin-version-check": "^4.0.0", + "download": "^7.1.0", + "import-lazy": "^3.1.0", + "os-filter-obj": "^2.0.0", + "pify": "^4.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/bin-wrapper/node_modules/@sindresorhus/is": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.7.0.tgz", + "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-wrapper/node_modules/download": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/download/-/download-7.1.0.tgz", + "integrity": "sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "archive-type": "^4.0.0", + "caw": "^2.0.1", + "content-disposition": "^0.5.2", + "decompress": "^4.2.0", + "ext-name": "^5.0.0", + "file-type": "^8.1.0", + "filenamify": "^2.0.0", + "get-stream": "^3.0.0", + "got": "^8.3.1", + "make-dir": "^1.2.0", + "p-event": "^2.1.0", + "pify": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/bin-wrapper/node_modules/download/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-wrapper/node_modules/file-type": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-8.1.0.tgz", + "integrity": "sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/bin-wrapper/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-wrapper/node_modules/got": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", + "integrity": "sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@sindresorhus/is": "^0.7.0", + "cacheable-request": "^2.1.1", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "into-stream": "^3.1.0", + "is-retry-allowed": "^1.1.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "mimic-response": "^1.0.0", + "p-cancelable": "^0.4.0", + "p-timeout": "^2.0.1", + "pify": "^3.0.0", + "safe-buffer": "^5.1.1", + "timed-out": "^4.0.1", + "url-parse-lax": "^3.0.0", + "url-to-options": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-wrapper/node_modules/got/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-wrapper/node_modules/p-cancelable": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.4.1.tgz", + "integrity": "sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-wrapper/node_modules/p-event": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-2.3.1.tgz", + "integrity": "sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA==", + "license": "MIT", + "optional": true, + "dependencies": { + "p-timeout": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/bin-wrapper/node_modules/p-timeout": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-2.0.1.tgz", + "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", + "license": "MIT", + "optional": true, + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-wrapper/node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/bin-wrapper/node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/blakejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "license": "MIT" + }, + "node_modules/bmp-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bmp-js/-/bmp-js-0.1.0.tgz", + "integrity": "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==", + "license": "MIT" + }, + "node_modules/bmp-ts": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz", + "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==", + "license": "MIT" + }, + "node_modules/bn": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bn/-/bn-1.0.5.tgz", + "integrity": "sha512-7TvGbqbZb6lDzsBtNz1VkdXXV0BVmZKPPViPmo2IpvwaryF7P+QKYKACyVkwo2mZPr2CpFiz7EtgPEcc3o/JFQ==", + "license": "BSD-3-Clause" + }, + "node_modules/bn.js": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.3.tgz", + "integrity": "sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==", + "license": "MIT" + }, + "node_modules/body": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/body/-/body-5.1.0.tgz", + "integrity": "sha512-chUsBxGRtuElD6fmw1gHLpvnKdVLK302peeFa9ZqAEk8TyzZ3fygLyUEDDPTJvL9+Bor0dIwn6ePOsRM2y0zQQ==", + "dev": true, + "dependencies": { + "continuable-cache": "^0.3.1", + "error": "^7.0.0", + "raw-body": "~1.1.0", + "safe-json-parse": "~1.0.1" + } + }, + "node_modules/body-parser": { + "version": "1.20.5", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/body-parser/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bonjour-service": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz", + "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/bootstrap": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz", + "integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==", + "deprecated": "This version of Bootstrap is no longer supported. Please upgrade to the latest version.", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "license": "MIT", + "peerDependencies": { + "jquery": "1.9.1 - 3", + "popper.js": "^1.16.1" + } + }, + "node_modules/bootstrap-colorpicker": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/bootstrap-colorpicker/-/bootstrap-colorpicker-3.4.0.tgz", + "integrity": "sha512-7vA0hvLrat3ptobEKlT9+6amzBUJcDAoh6hJRQY/AD+5dVZYXXf1ivRfrTwmuwiVLJo9rZwM8YB4lYzp6agzqg==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", + "dependencies": { + "bootstrap": ">=4.0", + "jquery": ">=2.2", + "popper.js": ">=1.10" + } + }, + "node_modules/bootstrap-material-design": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/bootstrap-material-design/-/bootstrap-material-design-4.1.3.tgz", + "integrity": "sha512-jOB9io76BKLxwF+IAgObFH9f88ityqOiYsQe9Aa8m88h7sSP3eFL1K8ygb0FsYyIiVm194iodg9i4GMOSlLeRA==", + "license": "MIT" + }, + "node_modules/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/boxen/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/boxen/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/boxen/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "license": "MIT" + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true, + "license": "ISC" + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "license": "MIT", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", + "license": "MIT", + "dependencies": { + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.5.tgz", + "integrity": "sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==", + "license": "ISC", + "dependencies": { + "bn.js": "^5.2.2", + "browserify-rsa": "^4.1.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.6.1", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.9", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "license": "MIT", + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bson": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", + "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==", + "license": "Apache-2.0", + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/bson/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "license": "MIT", + "optional": true, + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "license": "MIT", + "optional": true + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", + "license": "MIT", + "optional": true + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "license": "MIT" + }, + "node_modules/bufferstreams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz", + "integrity": "sha512-LZmiIfQprMLS6/k42w/PTc7awhU8AdNNcUerxTgr01WlP9agR2SgMv0wjlYYFD6eDOi8WvofrTX8RayjR/AeUQ==", + "dependencies": { + "readable-stream": "^1.0.33" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/bufferstreams/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, + "node_modules/bufferstreams/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/bufferstreams/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "license": "MIT" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-1.0.0.tgz", + "integrity": "sha512-/x68VkHLeTl3/Ll8IvxdwzhrT+IyKc52e/oyHhA2RwqPqswSnjVbSddfPRwAsJtbilMAPSRWwAlpxdYsSWOTKQ==", + "dev": true + }, + "node_modules/bzip-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bzip-deflate/-/bzip-deflate-1.0.0.tgz", + "integrity": "sha512-9RMnpiJqMYMJcLdr4pxwowZ8Zh3P+tVswE/bnX6tZ14UGKNcdV5WVK2P+lGp2As+RCjl+i3SFJ117HyCaaHNDA==", + "license": "CC-SA 3.0" + }, + "node_modules/cacheable-request": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-2.1.4.tgz", + "integrity": "sha512-vag0O2LKZ/najSoUwDbVlnlCFvhBE/7mGTY2B5FgCBDcRD+oVV1HYTOwM6JZfMg/hIcM6IwnTZ1uQQL5/X3xIQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "clone-response": "1.0.2", + "get-stream": "3.0.0", + "http-cache-semantics": "3.8.1", + "keyv": "3.0.0", + "lowercase-keys": "1.0.0", + "normalize-url": "2.0.1", + "responselike": "1.0.2" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cacheable-request/node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", + "license": "MIT", + "optional": true + }, + "node_modules/cacheable-request/node_modules/keyv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.0.0.tgz", + "integrity": "sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==", + "license": "MIT", + "optional": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha512-RPlX0+PHuvxVDZ7xX+EBVAp4RsVxP/TdDSN2mJYdiq1Lc4Hz7EUSjUI7RZrKKlmrIzVhf6Jo2stj7++gVarS0A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.2.0.tgz", + "integrity": "sha512-kfzR4zzQtAE9PC7CzZsjl3aBNbXWuXiSeOCdLcPpBfGW8YuCqQHcRPFDbr/BPVmd3EEPVpuFzLyuT/cUhPr4OQ==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001792", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", + "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "license": "MIT", + "optional": true, + "dependencies": { + "get-proxy": "^2.0.0", + "isurl": "^1.0.0-alpha5", + "tunnel-agent": "^0.6.0", + "url-to-options": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "license": "MIT", + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/chai-nightwatch": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/chai-nightwatch/-/chai-nightwatch-0.5.3.tgz", + "integrity": "sha512-38ixH/mqpY6IwnZkz6xPqx8aB5/KVR+j6VPugcir3EGOsphnWXrPH/mUt8Jp+ninL6ghY0AaJDQ10hSfCPGy/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "1.1.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalk-template": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-1.1.2.tgz", + "integrity": "sha512-2bxTP2yUH7AJj/VAXfcA+4IcWGdQ87HwBANLt5XxGTeomo8yG0y95N1um9i5StvhT/Bl0/2cARA5v1PpPXUxUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^5.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/chalk/chalk-template?sponsor=1" + } + }, + "node_modules/chalk-template/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/change-file-extension": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/change-file-extension/-/change-file-extension-0.1.1.tgz", + "integrity": "sha512-lB0j9teu8JtDPDHRfU8pNH33w4wMu5bOaKoT4PxH+AKugBrIfpiJMTTKIm0TErNeJPkeQEgvH31YpccTwOKPRg==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/chi-squared": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/chi-squared/-/chi-squared-1.1.0.tgz", + "integrity": "sha512-IFJA5igW44wzi7VHSsBcuHQ1+sF6noKRK6eFb+so4v9A/dH23RElM+8UBCi6+kWSINB/hDPNH+KDBCazPuKVwg==", + "license": "MIT", + "dependencies": { + "gamma": "^1.0.0" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/chromedriver": { + "version": "143.0.4", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-143.0.4.tgz", + "integrity": "sha512-mE++40DprY2n4d3OPxzW7ujIFRY9eLYwJf4uBgQtMaJQkapSVXRzUrLzSMcRaybrt47Y1t8xW5AKoaUIL3aYZw==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@testim/chrome-version": "^1.1.4", + "axios": "^1.12.0", + "compare-versions": "^6.1.0", + "extract-zip": "^2.0.1", + "proxy-agent": "^6.4.0", + "proxy-from-env": "^1.1.0", + "tcp-port-used": "^1.0.2" + }, + "bin": { + "chromedriver": "bin/chromedriver" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/ci-info": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cipher-base": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz", + "integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/clean-css": { + "version": "3.4.28", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", + "integrity": "sha512-aTWyttSdI2mYi07kWqHi24NUU9YlELFKGOAgFzZjDN1064DMAOy2FBuoyGmkKRlXkbpXd0EVHmiVkbKhKoirTw==", + "license": "MIT", + "dependencies": { + "commander": "2.8.x", + "source-map": "0.4.x" + }, + "bin": { + "cleancss": "bin/cleancss" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-css/node_modules/commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha512-+pJLBFVk+9ZZdlAOB5WuIElVPPth47hILFkmGym57aq8kwxsowvByvB0DHs1vQAhyMZzdcpTtF0VDKGkSDR4ZQ==", + "license": "MIT", + "dependencies": { + "graceful-readlink": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha512-Y8nIfcb1s/7DcobUz1yOO1GSp7gyL+D9zLHDehT7iRESqGSxjJ448Sg7rvfgsRJCnKLdSl11uGf0s9X80cH0/A==", + "license": "BSD-3-Clause", + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/clear-module": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/clear-module/-/clear-module-4.1.2.tgz", + "integrity": "sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^2.0.0", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-color": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.1.0.tgz", + "integrity": "sha512-SzsTUTopL62kJOMbLqBUkaLVbkyw0qKB3uMRFxgy9LrEQ5tdFO9dT8oUhqszpJB9FMpVTIQnZMjb6zn0abilvQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "2", + "d": "^0.1.1", + "es5-ext": "^0.10.8", + "es6-iterator": "2", + "memoizee": "^0.3.9", + "timers-ext": "0.1" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-progress": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", + "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.3" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==", + "license": "MIT" + }, + "node_modules/cloneable-readable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz", + "integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" + } + }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/color/-/color-0.8.0.tgz", + "integrity": "sha512-tKmPx2t+2N4pxZT+P4jXaT3qHMkYqE1ZHe5z6TpRVR/wSONGwHDracgkv//oRsFZ3T1QO6ZBxAxjpDIeNqEQyw==", + "license": "MIT", + "dependencies": { + "color-convert": "^0.5.0", + "color-string": "^0.3.0" + } + }, + "node_modules/color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling==" + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-string": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-0.3.0.tgz", + "integrity": "sha512-sz29j1bmSDfoAxKIEU6zwoIZXN6BrFbAMIhfYCNyiZXBDuU/aiHlN84lp/xDzL2ubyFhLDobHIlU1X70XRrMDA==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/colornames": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-0.0.2.tgz", + "integrity": "sha512-aeaoTql364CeoC6VHeRJd8uUiOVZDDtCyTP2dwXPD3WIt8UuPcXzmBB5gEhLDLaJS3MW152O7DfYm1a2HQv11g==", + "license": "MIT" + }, + "node_modules/colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/colorspace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.0.1.tgz", + "integrity": "sha512-rCnzSo6lkArg8rgeLdPQgxC5avqkyFGSpg3Roqn+rGRZfaHSBKgeDMr1YJZ9XTNZAeVoR4KxLjq9SUQ6hMvFlQ==", + "license": "MIT", + "dependencies": { + "color": "0.8.x", + "text-hex": "0.0.x" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/comment-json": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.6.2.tgz", + "integrity": "sha512-R2rze/hDX30uul4NZoIZ76ImSJLFxn/1/ZxtKC1L77y2X1k+yYu1joKbAtMA2Fg3hZrTOiw0I5mwVMo0cf250w==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-timsort": "^1.0.3", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/compare-versions": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz", + "integrity": "sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==", + "dev": true, + "license": "MIT" + }, + "node_modules/compress-commons": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression-webpack-plugin": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/compression-webpack-plugin/-/compression-webpack-plugin-11.1.0.tgz", + "integrity": "sha512-zDOQYp10+upzLxW+VRSjEpRRwBXJdsb5lBMlRxx1g8hckIFBpe3DTI0en2w7h+beuq89576RVzfiXrkdPGrHhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "schema-utils": "^4.2.0", + "serialize-javascript": "^6.0.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/compression/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "license": "ISC", + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/config-chain/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC", + "optional": true + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/connect-livereload": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/connect-livereload/-/connect-livereload-0.6.1.tgz", + "integrity": "sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/connect/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/connect/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/continuable-cache": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/continuable-cache/-/continuable-cache-0.3.1.tgz", + "integrity": "sha512-TF30kpKhTH8AGCG3dut0rdd/19B7Z+qCnrMoBLpyQu/2drZdNrrpcjPEoJeSVsQM+8KmWG5O56oPDjSSUsuTyA==", + "dev": true + }, + "node_modules/convert-hrtime": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/convert-hrtime/-/convert-hrtime-5.0.0.tgz", + "integrity": "sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/copy-props": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-4.0.0.tgz", + "integrity": "sha512-bVWtw1wQLzzKiYROtvNlbJgxgBYt2bMJpkCbKmXM3xyijvcjjWXEk5nyrrT3bgJ7ODb19ZohE2T0Y3FgNPyoTw==", + "license": "MIT", + "dependencies": { + "each-props": "^3.0.0", + "is-plain-object": "^5.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-13.0.1.tgz", + "integrity": "sha512-J+YV3WfhY6W/Xf9h+J1znYuqTye2xkBUIGyTPWuBAT27qajBa5mR4f8WBmfDY3YjRftT2kqZZiLi1qf0H+UOFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-parent": "^6.0.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.2.0", + "serialize-javascript": "^6.0.2", + "tinyglobby": "^0.2.12" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/core-js": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", + "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.49.0.tgz", + "integrity": "sha512-XM4RFka59xATyJv/cS3O3Kml72hQXUeGRuuTmMYFxwzc9/7C8OYTaIR/Ji+Yt8DXzsFLNhat15cE/JP15HrCgw==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.1.tgz", + "integrity": "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig/node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-api": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/crypto-api/-/crypto-api-0.8.5.tgz", + "integrity": "sha512-kcif7fCeYZpUsA3Y1VidFrK4HRf2Lsx9X4cnl7pauTXjgnXfEjaTyUGxzIBJ6DZwEPgX/VyKkhAeBV+vXHwX2Q==", + "license": "MIT" + }, + "node_modules/crypto-browserify": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, + "node_modules/cspell": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/cspell/-/cspell-8.19.4.tgz", + "integrity": "sha512-toaLrLj3usWY0Bvdi661zMmpKW2DVLAG3tcwkAv4JBTisdIRn15kN/qZDrhSieUEhVgJgZJDH4UKRiq29mIFxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-json-reporter": "8.19.4", + "@cspell/cspell-pipe": "8.19.4", + "@cspell/cspell-types": "8.19.4", + "@cspell/dynamic-import": "8.19.4", + "@cspell/url": "8.19.4", + "chalk": "^5.4.1", + "chalk-template": "^1.1.0", + "commander": "^13.1.0", + "cspell-dictionary": "8.19.4", + "cspell-gitignore": "8.19.4", + "cspell-glob": "8.19.4", + "cspell-io": "8.19.4", + "cspell-lib": "8.19.4", + "fast-json-stable-stringify": "^2.1.0", + "file-entry-cache": "^9.1.0", + "semver": "^7.7.1", + "tinyglobby": "^0.2.13" + }, + "bin": { + "cspell": "bin.mjs", + "cspell-esm": "bin.mjs" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/streetsidesoftware/cspell?sponsor=1" + } + }, + "node_modules/cspell-config-lib": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/cspell-config-lib/-/cspell-config-lib-8.19.4.tgz", + "integrity": "sha512-LtFNZEWVrnpjiTNgEDsVN05UqhhJ1iA0HnTv4jsascPehlaUYVoyucgNbFeRs6UMaClJnqR0qT9lnPX+KO1OLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-types": "8.19.4", + "comment-json": "^4.2.5", + "yaml": "^2.7.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell-dictionary": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/cspell-dictionary/-/cspell-dictionary-8.19.4.tgz", + "integrity": "sha512-lr8uIm7Wub8ToRXO9f6f7in429P1Egm3I+Ps3ZGfWpwLTCUBnHvJdNF/kQqF7PL0Lw6acXcjVWFYT7l2Wdst2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-pipe": "8.19.4", + "@cspell/cspell-types": "8.19.4", + "cspell-trie-lib": "8.19.4", + "fast-equals": "^5.2.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell-gitignore": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/cspell-gitignore/-/cspell-gitignore-8.19.4.tgz", + "integrity": "sha512-KrViypPilNUHWZkMV0SM8P9EQVIyH8HvUqFscI7+cyzWnlglvzqDdV4N5f+Ax5mK+IqR6rTEX8JZbCwIWWV7og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/url": "8.19.4", + "cspell-glob": "8.19.4", + "cspell-io": "8.19.4" + }, + "bin": { + "cspell-gitignore": "bin.mjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell-glob": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/cspell-glob/-/cspell-glob-8.19.4.tgz", + "integrity": "sha512-042uDU+RjAz882w+DXKuYxI2rrgVPfRQDYvIQvUrY1hexH4sHbne78+OMlFjjzOCEAgyjnm1ktWUCCmh08pQUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/url": "8.19.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell-grammar": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/cspell-grammar/-/cspell-grammar-8.19.4.tgz", + "integrity": "sha512-lzWgZYTu/L7DNOHjxuKf8H7DCXvraHMKxtFObf8bAzgT+aBmey5fW2LviXUkZ2Lb2R0qQY+TJ5VIGoEjNf55ow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-pipe": "8.19.4", + "@cspell/cspell-types": "8.19.4" + }, + "bin": { + "cspell-grammar": "bin.mjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell-io": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/cspell-io/-/cspell-io-8.19.4.tgz", + "integrity": "sha512-W48egJqZ2saEhPWf5ftyighvm4mztxEOi45ILsKgFikXcWFs0H0/hLwqVFeDurgELSzprr12b6dXsr67dV8amg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-service-bus": "8.19.4", + "@cspell/url": "8.19.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell-lib": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/cspell-lib/-/cspell-lib-8.19.4.tgz", + "integrity": "sha512-NwfdCCYtIBNQuZcoMlMmL3HSv2olXNErMi/aOTI9BBAjvCHjhgX5hbHySMZ0NFNynnN+Mlbu5kooJ5asZeB3KA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-bundled-dicts": "8.19.4", + "@cspell/cspell-pipe": "8.19.4", + "@cspell/cspell-resolver": "8.19.4", + "@cspell/cspell-types": "8.19.4", + "@cspell/dynamic-import": "8.19.4", + "@cspell/filetypes": "8.19.4", + "@cspell/strong-weak-map": "8.19.4", + "@cspell/url": "8.19.4", + "clear-module": "^4.1.2", + "comment-json": "^4.2.5", + "cspell-config-lib": "8.19.4", + "cspell-dictionary": "8.19.4", + "cspell-glob": "8.19.4", + "cspell-grammar": "8.19.4", + "cspell-io": "8.19.4", + "cspell-trie-lib": "8.19.4", + "env-paths": "^3.0.0", + "fast-equals": "^5.2.2", + "gensequence": "^7.0.0", + "import-fresh": "^3.3.1", + "resolve-from": "^5.0.0", + "vscode-languageserver-textdocument": "^1.0.12", + "vscode-uri": "^3.1.0", + "xdg-basedir": "^5.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell-trie-lib": { + "version": "8.19.4", + "resolved": "https://registry.npmjs.org/cspell-trie-lib/-/cspell-trie-lib-8.19.4.tgz", + "integrity": "sha512-yIPlmGSP3tT3j8Nmu+7CNpkPh/gBO2ovdnqNmZV+LNtQmVxqFd2fH7XvR1TKjQyctSH1ip0P5uIdJmzY1uhaYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspell/cspell-pipe": "8.19.4", + "@cspell/cspell-types": "8.19.4", + "gensequence": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cspell/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cspell/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/css-loader": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.4.tgz", + "integrity": "sha512-vv3J9tlOl04WjiMvHQI/9tmIrCxVrj6PFbHemBB1iihpeRbi/I4h033eoFIhwxBBqLhI0KYFS7yvynBFhIZfTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.40", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.6.3" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", + "webpack": "^5.27.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-loader/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-select/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/css-select/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "devOptional": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/css-select/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/css-select/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/css-select/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "devOptional": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "devOptional": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "license": "MIT", + "optional": true, + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/cssstyle": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", + "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^3.2.0", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ctph.js": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/ctph.js/-/ctph.js-0.0.5.tgz", + "integrity": "sha512-xcgQ6zzamT6ESHBhFPZHjkcpjzv4rtWw9GLoeNwvQwQQdXNR49xKBF5/Nt1oLsE3X1JM8QHktbGknp5cH20PTA==" + }, + "node_modules/cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/d": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz", + "integrity": "sha512-0SdM9V9pd/OXJHoWmTfNPTAeD+lw6ZqHg+isPyBFuJsZLSE0Ygg1cYZ/0l6DrKQXMOqGOu1oWupMoOfoRfMZrQ==", + "license": "MIT", + "dependencies": { + "es5-ext": "~0.10.2" + } + }, + "node_modules/d3": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz", + "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==", + "license": "ISC", + "dependencies": { + "d3-array": "3", + "d3-axis": "3", + "d3-brush": "3", + "d3-chord": "3", + "d3-color": "3", + "d3-contour": "4", + "d3-delaunay": "6", + "d3-dispatch": "3", + "d3-drag": "3", + "d3-dsv": "3", + "d3-ease": "3", + "d3-fetch": "3", + "d3-force": "3", + "d3-format": "3", + "d3-geo": "3", + "d3-hierarchy": "3", + "d3-interpolate": "3", + "d3-path": "3", + "d3-polygon": "3", + "d3-quadtree": "3", + "d3-random": "3", + "d3-scale": "4", + "d3-scale-chromatic": "3", + "d3-selection": "3", + "d3-shape": "3", + "d3-time": "3", + "d3-time-format": "4", + "d3-timer": "3", + "d3-transition": "3", + "d3-zoom": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-axis": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", + "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-brush": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", + "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "3", + "d3-transition": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-chord": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", + "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", + "license": "ISC", + "dependencies": { + "d3-path": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-contour": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", + "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", + "license": "ISC", + "dependencies": { + "d3-array": "^3.2.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-delaunay": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", + "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", + "license": "ISC", + "dependencies": { + "delaunator": "5" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", + "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", + "license": "ISC", + "dependencies": { + "commander": "7", + "iconv-lite": "0.6", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json.js", + "csv2tsv": "bin/dsv2dsv.js", + "dsv2dsv": "bin/dsv2dsv.js", + "dsv2json": "bin/dsv2json.js", + "json2csv": "bin/json2dsv.js", + "json2dsv": "bin/json2dsv.js", + "json2tsv": "bin/json2dsv.js", + "tsv2csv": "bin/dsv2dsv.js", + "tsv2json": "bin/dsv2json.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dsv/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-fetch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", + "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", + "license": "ISC", + "dependencies": { + "d3-dsv": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-force": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", + "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-quadtree": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-geo": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz", + "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2.5.0 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-hexbin": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/d3-hexbin/-/d3-hexbin-0.2.2.tgz", + "integrity": "sha512-KS3fUT2ReD4RlGCjvCEm1RgMtp2NFZumdMu4DBzQK8AZv3fXRM6Xm8I4fSU07UXvH4xxg03NwWKWdvxfS/yc4w==", + "license": "BSD-3-Clause" + }, + "node_modules/d3-hierarchy": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", + "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-polygon": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", + "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-quadtree": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", + "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz", + "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-interpolate": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "license": "ISC", + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/dateformat": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", + "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tar/node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2/node_modules/file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-targz/node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==", + "license": "MIT", + "optional": true, + "dependencies": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip/node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-unzip/node_modules/get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", + "license": "MIT", + "optional": true, + "dependencies": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-unzip/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-eql": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.0.1.tgz", + "integrity": "sha512-D/Oxqobjr+kxaHsgiQBZq9b6iAWdEj5W/JdJm8deNduAPc9CwXQ3BJJCuEqlrPXcy45iOMkGPZ0T81Dnz7UDCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-equal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", + "license": "MIT", + "dependencies": { + "is-arguments": "^1.1.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.5.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-for-each": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/deep-for-each/-/deep-for-each-3.0.0.tgz", + "integrity": "sha512-pPN+0f8jlnNP+z90qqOdxGghJU5XM6oBDhvAR+qdQzjCg5pk/7VPPvKK1GqoXEFkHza6ZS+Otzzvmr0g3VUaKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.isplainobject": "^4.0.6" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/default-gateway/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/default-gateway/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-gateway/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-gateway/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defaults/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/delaunator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.1.0.tgz", + "integrity": "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==", + "license": "ISC", + "dependencies": { + "robust-predicates": "^3.0.2" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true, + "license": "MIT" + }, + "node_modules/devtools-protocol": { + "version": "0.0.1140464", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1140464.tgz", + "integrity": "sha512-I1jXnjpQh/6TBFyQ0A9dB2kXXk6DprpPFZoI8pUsxHtlNuOTQEdv9fUqYBsFtf8tOJCbdsZZyQrWeXu6GfK+Bw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/diagnostics": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.0.1.tgz", + "integrity": "sha512-CRx2wYrfE/5+CpLdQY0Oat5A14C/ntU7BCVeczr4S8WtCDAkhiNAgf7sDy19eIg2byEEJ8UIOPo8frUdQdO/0Q==", + "license": "MIT", + "dependencies": { + "colorspace": "1.0.x", + "enabled": "1.0.x", + "kuler": "0.0.x" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/diff": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/dompurify": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.2.tgz", + "integrity": "sha512-lHeS9SA/IKeIFFyYciHBr2n0v1VMPlSj843HdLOwjb2OxNwdq9Xykxqhk+FE42MzAdHvInbAolSE4mhahPpjXA==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-8.0.2.tgz", + "integrity": "sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ==", + "license": "MIT", + "dependencies": { + "type-fest": "^3.8.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/download": { + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/download/-/download-6.2.5.tgz", + "integrity": "sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA==", + "license": "MIT", + "optional": true, + "dependencies": { + "caw": "^2.0.0", + "content-disposition": "^0.5.2", + "decompress": "^4.0.0", + "ext-name": "^5.0.0", + "file-type": "5.2.0", + "filenamify": "^2.0.0", + "get-stream": "^3.0.0", + "got": "^7.0.0", + "make-dir": "^1.0.0", + "p-event": "^1.0.0", + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/download/node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/download/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/download/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true, + "license": "MIT" + }, + "node_modules/duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha512-+AWBwjGadtksxjOQSFDhPNQbed7icNXApT4+2BNpsXzcCBiInq2H9XW0O8sfHFaPmnQRs7cg/P0fAr2IWQSW0g==", + "license": "BSD", + "dependencies": { + "readable-stream": "~1.1.9" + } + }, + "node_modules/duplexer2/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "license": "MIT" + }, + "node_modules/duplexer3": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/each-props": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-3.0.0.tgz", + "integrity": "sha512-IYf1hpuWrdzse/s/YJOrFmU15lyhSzxelNVAHTEG3DtP4QsLTWZUzcUL3HMXmKQxXpa4EIrBPpwRgj0aehdvAw==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^5.0.0", + "object.defaults": "^1.1.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/easy-transform-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/easy-transform-stream/-/easy-transform-stream-1.0.1.tgz", + "integrity": "sha512-ktkaa6XR7COAR3oj02CF3IOgz2m1hCaY3SfzvKT4Svt2MhHw9XCt+ncJNWfe2TGz31iqzNGZ8spdKQflj+Rlog==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.353", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.353.tgz", + "integrity": "sha512-kOrWphBi8TOZyiJZqsgqIle0lw+tzmnQK83pV9dZUd01Nm2POECSyFQMAuarzZdYqQW7FH9RaYOuaRo3h+bQ3w==", + "dev": true, + "license": "ISC" + }, + "node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, + "node_modules/emits": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emits/-/emits-3.0.0.tgz", + "integrity": "sha512-WJSCMaN/qjIkzWy5Ayu0MDENFltcu4zTPPnWqdFPOVBtsENVTN+A3d76G61yuiVALsMK+76MejdPrwmccv/wag==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha512-nnzgVSpB35qKrUN8358SjO1bYAmxoThECTWw9s3J0x5G8A9hokKHVDFzBjVpCoSryo6MhN8woVyascN5jheaNA==", + "license": "MIT", + "dependencies": { + "env-variable": "0.0.x" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.21.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.2.tgz", + "integrity": "sha512-xe9vQb5kReirPUxgQrXA3ihgbCqssmTiM7cOZ+Gzu+VeGWgpV98lLZvp0dl4yriyAePcewxGUs9UpKD8PET9KQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/env-paths": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/env-variable": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.6.tgz", + "integrity": "sha512-bHz59NlBbtS0NhftmR8+ExBEekE7br0e01jw+kk0NDro7TtZzBYZ5ScGPs3OmwnpyfHTHOtr1Y6uedCdrIldtg==", + "license": "MIT" + }, + "node_modules/envinfo": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.11.0.tgz", + "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", + "dev": true, + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/error": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/error/-/error-7.2.1.tgz", + "integrity": "sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==", + "dev": true, + "dependencies": { + "string-template": "~0.2.1" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-iterator/node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/es6-object-assign": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es6-object-assign/-/es6-object-assign-1.1.0.tgz", + "integrity": "sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==", + "license": "MIT" + }, + "node_modules/es6-polyfills": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/es6-polyfills/-/es6-polyfills-2.0.0.tgz", + "integrity": "sha512-daIt/MHqdYmxnuo5KcwAU9EqSxvaDRyajYOUU9fy+CLuU5+RFhpNCnL3oPsq7n+g673F3z/Vb+FXo/EmQjlkbw==", + "deprecated": "Use @natlibfi/es6-polyfills instead", + "license": " LGPL-3.0+", + "dependencies": { + "es6-object-assign": "^1.0.3", + "es6-promise-polyfill": "^1.2.0" + } + }, + "node_modules/es6-promise-polyfill": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es6-promise-polyfill/-/es6-promise-polyfill-1.2.0.tgz", + "integrity": "sha512-HHb0vydCpoclpd0ySPkRXMmBw80MRt1wM4RBJBlXkux97K7gleabZdsR0gvE1nNPM9mgOZIBTzjjXiPxf4lIqQ==", + "license": "MIT" + }, + "node_modules/es6-promisify": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-7.0.0.tgz", + "integrity": "sha512-ginqzK3J90Rd4/Yz7qRrqUeIpe3TwSXTPPZtPne7tGBPeAaQiU8qt4fpKApnxHcq1AwtUdHVg5P77x/yrggG8Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/es6-symbol/node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/es6-weak-map": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-0.1.4.tgz", + "integrity": "sha512-P+N5Cd2TXeb7G59euFiM7snORspgbInS29Nbf3KNO2JQp/DyhvMCDWd58nsVAXwYJ6W3Bx7qDdy6QQ3PCJ7jKQ==", + "license": "MIT", + "dependencies": { + "d": "~0.1.1", + "es5-ext": "~0.10.6", + "es6-iterator": "~0.1.3", + "es6-symbol": "~2.0.1" + } + }, + "node_modules/es6-weak-map/node_modules/es6-iterator": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-0.1.3.tgz", + "integrity": "sha512-6TOmbFM6OPWkTe+bQ3ZuUkvqcWUjAnYjKUCLdbvRsAUz2Pr+fYIibwNXNkLNtIK9PPFbNMZZddaRNkyJhlGJhA==", + "license": "MIT", + "dependencies": { + "d": "~0.1.1", + "es5-ext": "~0.10.5", + "es6-symbol": "~2.0.1" + } + }, + "node_modules/es6-weak-map/node_modules/es6-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-2.0.1.tgz", + "integrity": "sha512-wjobO4zO8726HVU7mI2OA/B6QszqwHJuKab7gKHVx+uRfVVYGcWJkCIFxV2Madqb9/RUSrhJ/r6hPfG7FsWtow==", + "license": "MIT", + "dependencies": { + "d": "~0.1.1", + "es5-ext": "~0.10.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/eslint": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsdoc": { + "version": "48.11.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.11.0.tgz", + "integrity": "sha512-d12JHJDPNo7IFwTOAItCeJY1hcqoIxE0lHA8infQByLilQ9xkqrRa6laWCnsuCrf+8rUnvxXY1XuTbibRBNylA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.46.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.3.5", + "escape-string-regexp": "^4.0.0", + "espree": "^10.1.0", + "esquery": "^1.6.0", + "parse-imports": "^2.1.1", + "semver": "^7.6.3", + "spdx-expression-parse": "^4.0.0", + "synckit": "^0.9.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/eslint/node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esniff/node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/event-emitter/node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true, + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/events-universal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz", + "integrity": "sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==", + "license": "Apache-2.0", + "dependencies": { + "bare-events": "^2.7.0" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/exec-buffer": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz", + "integrity": "sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA==", + "license": "MIT", + "optional": true, + "dependencies": { + "execa": "^0.7.0", + "p-finally": "^1.0.0", + "pify": "^3.0.0", + "rimraf": "^2.5.4", + "tempfile": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/exec-buffer/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/exec-buffer/node_modules/execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/exec-buffer/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/exec-buffer/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "license": "ISC", + "optional": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/exec-buffer/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/exec-buffer/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", + "optional": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/exec-buffer/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/exec-buffer/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/exec-buffer/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "license": "ISC", + "optional": true + }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "license": "MIT", + "optional": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/execa/node_modules/cross-spawn": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz", + "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", + "license": "MIT", + "optional": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/execa/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "license": "MIT", + "optional": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/execa/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/execa/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "license": "MIT", + "optional": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/executable": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", + "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "license": "MIT", + "optional": true, + "dependencies": { + "pify": "^2.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/executable/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/exif-parser": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz", + "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==" + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", + "license": "MIT", + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/express": { + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.14.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/express/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/express/node_modules/qs": { + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", + "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/express/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "license": "MIT", + "optional": true, + "dependencies": { + "mime-db": "^1.28.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ext-list": "^2.0.0", + "sort-keys-length": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", + "license": "MIT", + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "dev": true, + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/fancy-log": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz", + "integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==", + "license": "MIT", + "dependencies": { + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "parse-node-version": "^1.0.0", + "time-stamp": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-equals": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz", + "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fast-xml-parser": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.6.tgz", + "integrity": "sha512-Yd4vkROfJf8AuJrDIVMVmYfULKmIJszVsMv7Vo71aocsKgFxpdlpSHXSaInvyYfgw2PRuObQSW2GFpVMUjxu9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha512-Xhj93RXbMSq8urNCUq4p9l0P6hnySJ/7YNRhYNug0bLOuii7pKO7xQFb5mx9xZXWCar88pLPb805PvUkwrLZpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/fernet": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/fernet/-/fernet-0.3.3.tgz", + "integrity": "sha512-DvvqouVhv3VCor83wkQbSycekYUKDRQ1IKqcInaF5n5BSKgWBVfYLbSf7RRxojwQO0DZySiz5MlM2vO4MG3SUg==", + "license": "MIT", + "dependencies": { + "crypto-js": "~4.2.0", + "urlsafe-base64": "1.0.0" + } + }, + "node_modules/file-entry-cache": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.1.0.tgz", + "integrity": "sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/file-saver": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", + "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==", + "license": "MIT" + }, + "node_modules/file-sync-cmp": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/file-sync-cmp/-/file-sync-cmp-0.1.1.tgz", + "integrity": "sha512-0k45oWBokCqh2MOexeYKpyqmGKG+8mQ2Wd8iawx+uWd/weWJQAZ6SoPybagdCI4xFisag8iAR77WPm4h3pTfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/file-type": { + "version": "19.6.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-19.6.0.tgz", + "integrity": "sha512-VZR5I7k5wkD0HgFnMsq5hOsSc710MJMu5Nc5QYsbe38NN5iPV/XTObYLc/cpttRTf6lX538+5uO1ZQRhYibiZQ==", + "license": "MIT", + "dependencies": { + "get-stream": "^9.0.1", + "strtok3": "^9.0.1", + "token-types": "^6.0.0", + "uint8array-extras": "^1.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/file-type?sponsor=1" + } + }, + "node_modules/file-type/node_modules/get-stream": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", + "integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==", + "license": "MIT", + "dependencies": { + "@sec-ant/readable-stream": "^0.4.1", + "is-stream": "^4.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-type/node_modules/is-stream": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz", + "integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/filelist": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/filename-reserved-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", + "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/filenamify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-2.1.0.tgz", + "integrity": "sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA==", + "license": "MIT", + "optional": true, + "dependencies": { + "filename-reserved-regex": "^2.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-versions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", + "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "license": "MIT", + "optional": true, + "dependencies": { + "semver-regex": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/findup-sync": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-5.0.0.tgz", + "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", + "license": "MIT", + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.3", + "micromatch": "^4.0.4", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/fined": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-2.0.0.tgz", + "integrity": "sha512-OFRzsL6ZMHz5s0JrsEr+TpdGNCtrVtnuG3x1yzGNiQHT0yaDnXAj8V/lWcpJVrnoDpcwXcASxAZYbuXda2Y82A==", + "license": "MIT", + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^5.0.0", + "object.defaults": "^1.1.0", + "object.pick": "^1.3.0", + "parse-filepath": "^1.0.2" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/flagged-respawn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-2.0.0.tgz", + "integrity": "sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA==", + "license": "MIT", + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/flat": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/flat/-/flat-6.0.1.tgz", + "integrity": "sha512-/3FfIa8mbrg3xE7+wAhWeV+bd7L2Mof+xtZb5dRDKZ+wDvYJK4WDYeIOuOhre5Yv5aQObZrlbRmk3RTSiuQBtw==", + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/flat-cache": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", + "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.3.1", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==", + "license": "MIT", + "dependencies": { + "for-in": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/fs-mkdirp-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-2.0.1.tgz", + "integrity": "sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.8", + "streamx": "^2.12.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function-timeout": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/function-timeout/-/function-timeout-1.0.2.tgz", + "integrity": "sha512-939eZS4gJ3htTHAldmyyuzlrD58P03fHG49v2JfFXbV6OhvZKRC9j2yAtdHw/zrp2zXHuv05zMIy40F0ge7spA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gamma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gamma/-/gamma-1.0.0.tgz", + "integrity": "sha512-bPI4QJKNe/PfuO6PZU7ckMkBk0wEe3iQWx3DadEp5ceiAkJwc8CRukwncOZ5Hk5rc6nNTbIfByZKGz7Vv+xXdw==", + "license": "MIT" + }, + "node_modules/gaze": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", + "integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "globule": "^1.0.0" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensequence": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/gensequence/-/gensequence-7.0.0.tgz", + "integrity": "sha512-47Frx13aZh01afHJTB3zTtKIlFI6vWY+MYCN9Qpew6i52rfKjnhCF/l1YlC8UmEMvvntZZ6z4PiCcmyuedR2aQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/geodesy": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/geodesy/-/geodesy-1.1.3.tgz", + "integrity": "sha512-H/0XSd1KjKZGZ2YGZcOYzRyY/foYAawwTEumNSo+YUwf+u5d4CfvBRg2i2Qimrx9yUEjWR8hLvMnhghuVFN0Zg==", + "license": "MIT" + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "license": "MIT", + "optional": true, + "dependencies": { + "npm-conf": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz", + "integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/getobject": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.2.tgz", + "integrity": "sha512-2zblDBaFcb3rB4rF77XVnuINOE2h2k/OnqXAiy0IrTxUfV1iFp3la33oAQVY9pCpWU268WFYVt2t71hlMuLsOg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/gifsicle": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-5.3.0.tgz", + "integrity": "sha512-FJTpgdj1Ow/FITB7SVza5HlzXa+/lqEY0tHQazAJbuAdvyJtkH4wIdsR2K414oaTwRXHFLLF+tYbipj+OpYg+Q==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bin-build": "^3.0.0", + "bin-wrapper": "^4.0.0", + "execa": "^5.0.0" + }, + "bin": { + "gifsicle": "cli.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/imagemin/gisicle-bin?sponsor=1" + } + }, + "node_modules/gifsicle/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "optional": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/gifsicle/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gifsicle/node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gifsicle/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "optional": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gifwrap": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz", + "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==", + "license": "MIT", + "dependencies": { + "image-q": "^4.0.0", + "omggif": "^1.0.10" + } + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "devOptional": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-stream": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-8.0.3.tgz", + "integrity": "sha512-fqZVj22LtFJkHODT+M4N1RJQ3TjnnQhfE9GwZI8qXscYarnhpip70poMldRnP8ipQ/w0B621kOhfc53/J9bd/A==", + "license": "MIT", + "dependencies": { + "@gulpjs/to-absolute-glob": "^4.0.0", + "anymatch": "^3.1.3", + "fastq": "^1.13.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "is-negated-glob": "^1.0.0", + "normalize-path": "^3.0.0", + "streamx": "^2.12.5" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regex.js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/glob-to-regex.js/-/glob-to-regex.js-1.2.0.tgz", + "integrity": "sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/glob-watcher": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-6.0.0.tgz", + "integrity": "sha512-wGM28Ehmcnk2NqRORXFOTOR064L4imSw3EeOqU5bIwUf62eXGwg89WivH6VMahL8zlQHeodzvHpXplrqzrz3Nw==", + "license": "MIT", + "dependencies": { + "async-done": "^2.0.0", + "chokidar": "^3.5.3" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "4.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "license": "MIT", + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", + "license": "MIT", + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.1.0.tgz", + "integrity": "sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==", + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.3", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/globule": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.4.tgz", + "integrity": "sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "~7.1.1", + "lodash": "^4.17.21", + "minimatch": "~3.0.2" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/globule/node_modules/minimatch": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.8.tgz", + "integrity": "sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glogg": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-2.2.0.tgz", + "integrity": "sha512-eWv1ds/zAlz+M1ioHsyKJomfY7jbDDPpwSkv14KQj89bycx1nvK5/2Cj/T9g7kzJcX5Bc7Yv22FjfBZS/jl94A==", + "license": "MIT", + "dependencies": { + "sparkles": "^2.1.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-7.1.0.tgz", + "integrity": "sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==", + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^3.2.0", + "duplexer3": "^0.1.4", + "get-stream": "^3.0.0", + "is-plain-obj": "^1.1.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "isurl": "^1.0.0-alpha5", + "lowercase-keys": "^1.0.0", + "p-cancelable": "^0.3.0", + "p-timeout": "^1.1.1", + "safe-buffer": "^5.0.1", + "timed-out": "^4.0.0", + "url-parse-lax": "^1.0.0", + "url-to-options": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/got/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==", + "license": "MIT" + }, + "node_modules/grunt": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.6.2.tgz", + "integrity": "sha512-bUzh5nA/P5L66ihXTDP6J5BGnMB/8lXJXejYWSbH4Y4TvWM9t2S39sggQDYYQlx06cYcCsmu63HMYHGCIzUVfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dateformat": "~4.6.2", + "eventemitter2": "~0.4.13", + "exit": "~0.1.2", + "findup-sync": "~5.0.0", + "glob": "~7.1.6", + "grunt-cli": "^1.4.3", + "grunt-known-options": "~2.0.0", + "grunt-legacy-log": "~3.0.0", + "grunt-legacy-util": "~2.0.1", + "iconv-lite": "~0.6.3", + "js-yaml": "~3.14.0", + "minimatch": "^3.1.5", + "nopt": "^5.0.0" + }, + "bin": { + "grunt": "bin/grunt" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/grunt-chmod": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grunt-chmod/-/grunt-chmod-1.1.1.tgz", + "integrity": "sha512-f807W/VOIhhaOW85JyeRd4DgB0RcbsGQV/4IvtcKctOWGvPJns4AqN7xW73PG9+RwDnSGxApS+6Xov5L2LeNXg==", + "dev": true, + "dependencies": { + "shelljs": "^0.5.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/grunt-cli": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.5.0.tgz", + "integrity": "sha512-rILKAFoU0dzlf22SUfDtq2R1fosChXXlJM5j7wI6uoW8gwmXDXzbUvirlKZSYCdXl3LXFbR+8xyS+WFo+b6vlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "grunt-known-options": "~2.0.0", + "interpret": "~1.1.0", + "liftup": "~3.0.1", + "nopt": "~5.0.0", + "v8flags": "^4.0.1" + }, + "bin": { + "grunt": "bin/grunt" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-concurrent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/grunt-concurrent/-/grunt-concurrent-3.0.0.tgz", + "integrity": "sha512-AgXtjUJESHEGeGX8neL3nmXBTHSj1QC48ABQ3ng2/vjuSBpDD8gKcVHSlXP71pFkIR8TQHf+eomOx6OSYSgfrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^2.0.1", + "async": "^3.1.0", + "indent-string": "^4.0.0", + "pad-stream": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "grunt": ">=1" + } + }, + "node_modules/grunt-contrib-clean": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-clean/-/grunt-contrib-clean-2.0.1.tgz", + "integrity": "sha512-uRvnXfhiZt8akb/ZRDHJpQQtkkVkqc/opWO4Po/9ehC2hPxgptB9S6JHDC/Nxswo4CJSM0iFPT/Iym3cEMWzKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "async": "^3.2.3", + "rimraf": "^2.6.2" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "grunt": ">=0.4.5" + } + }, + "node_modules/grunt-contrib-connect": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/grunt-contrib-connect/-/grunt-contrib-connect-5.0.1.tgz", + "integrity": "sha512-Hfq/0QJl3ddD2N/a/1cDJHkKEOGk6m7W6uxNe0AmYwtf6v0F/4+8q9rvPJ1tl+mrI90lU/89I9T/h48qqeMfQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "async": "^3.2.5", + "connect": "^3.7.0", + "connect-livereload": "^0.6.1", + "http2-wrapper": "^2.2.1", + "morgan": "^1.10.0", + "open": "^8.0.0", + "portscanner": "^2.2.0", + "serve-index": "^1.9.1", + "serve-static": "^1.15.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/grunt-contrib-copy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-copy/-/grunt-contrib-copy-1.0.0.tgz", + "integrity": "sha512-gFRFUB0ZbLcjKb67Magz1yOHGBkyU6uL29hiEW1tdQ9gQt72NuMKIy/kS6dsCbV0cZ0maNCb0s6y+uT1FKU7jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^1.1.1", + "file-sync-cmp": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-watch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/grunt-contrib-watch/-/grunt-contrib-watch-1.1.0.tgz", + "integrity": "sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "async": "^2.6.0", + "gaze": "^1.1.0", + "lodash": "^4.17.10", + "tiny-lr": "^1.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-contrib-watch/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/grunt-eslint": { + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-25.0.0.tgz", + "integrity": "sha512-JIV5IPgOuacorFLmYtUTq0n+0qGIL9FSQJ4KVnNfCg/8Fm+K1t6OWrzXXI8TxWTwq2K9E3parFVXCpn1sGLbKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "eslint": "^9.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + }, + "peerDependencies": { + "grunt": ">=1" + } + }, + "node_modules/grunt-eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/grunt-eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/grunt-eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/grunt-eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/grunt-exec": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/grunt-exec/-/grunt-exec-3.0.0.tgz", + "integrity": "sha512-cgAlreXf3muSYS5LzW0Cc4xHK03BjFOYk0MqCQ/MZ3k1Xz2GU7D+IAJg4UKicxpO+XdONJdx/NJ6kpy2wI+uHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + }, + "peerDependencies": { + "grunt": ">=0.4" + } + }, + "node_modules/grunt-known-options": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/grunt-known-options/-/grunt-known-options-2.0.0.tgz", + "integrity": "sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/grunt-legacy-log": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-log/-/grunt-legacy-log-3.0.1.tgz", + "integrity": "sha512-vytI3IUC8qUK9TcvvpHpGJzDojua/sfJV4TdLB4FtCFzospqduzBuL3+dEfpvO+tGECv7/273+33hjjMXSa92g==", + "dev": true, + "license": "MIT", + "dependencies": { + "colors": "~1.1.2", + "grunt-legacy-log-utils": "^2.1.3", + "hooker": "~0.2.3", + "lodash": "^4.18.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/grunt-legacy-log-utils": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/grunt-legacy-log-utils/-/grunt-legacy-log-utils-2.1.3.tgz", + "integrity": "sha512-sgG+QvKmdb44wZyzJP+ejDsy3jYxG2wzohpol+JTMlXqMUBDoZb01JPQ5jKAedtZBFwhmABAc88T9hEBLy3U+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-legacy-log-utils/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/grunt-legacy-log-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/grunt-legacy-log-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/grunt-legacy-log-utils/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/grunt-legacy-log/node_modules/colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/grunt-legacy-util": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.2.tgz", + "integrity": "sha512-0xoDILyR4BVJel5uJwnhjdWN9evOQ8A0uXbQUIJ0hgVthIA6kloXHSoqATQPj6BRrHrHkcQtCeGVb0ixFoHyEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async": "~3.2.0", + "exit-x": "~0.2.2", + "getobject": "~1.0.0", + "hooker": "~0.2.3", + "lodash": "^4.18.0", + "underscore.string": "~3.3.5", + "which": "~2.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/grunt-retro": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/grunt-retro/-/grunt-retro-0.6.4.tgz", + "integrity": "sha512-kqnvNUAngOhkDckEQPYFDqNcRlculVp/Sy+gCe4ey7utM4BCaENVf2JfDeK488mj/0cgmAZyXwpW6w9l1OAxMg==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/grunt-webpack": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/grunt-webpack/-/grunt-webpack-6.0.0.tgz", + "integrity": "sha512-FtRVTGJGuV9Ic/OrCR80p5u601e0ekvTyHo7vnwVo3XlvRh5wR1ATAVT9FnnobHqZnQ/DeF84W97si5+roUWEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-for-each": "^3.0.0", + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=16.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/grunt-zip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/grunt-zip/-/grunt-zip-1.0.0.tgz", + "integrity": "sha512-e5HOzf+BLFR6rXM67oGrFcVgfVbLDPBnv29YdWTupthwNg/1y91B0xXx667E6dKin8YvrwDShtQy48D1NRzn7g==", + "dev": true, + "dependencies": { + "grunt-retro": "~0.6.0", + "jszip": "^3.8.0" + }, + "bin": { + "grunt-zip": "bin/grunt-zip" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/grunt/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/grunt/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/grunt/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/gulp": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-5.0.1.tgz", + "integrity": "sha512-PErok3DZSA5WGMd6XXV3IRNO0mlB+wW3OzhFJLEec1jSERg2j1bxJ6e5Fh6N6fn3FH2T9AP4UYNb/pYlADB9sA==", + "license": "MIT", + "dependencies": { + "glob-watcher": "^6.0.0", + "gulp-cli": "^3.1.0", + "undertaker": "^2.0.0", + "vinyl-fs": "^4.0.2" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/gulp-cli": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-3.1.0.tgz", + "integrity": "sha512-zZzwlmEsTfXcxRKiCHsdyjZZnFvXWM4v1NqBJSYbuApkvVKivjcmOS2qruAJ+PkEHLFavcDKH40DPc1+t12a9Q==", + "license": "MIT", + "dependencies": { + "@gulpjs/messages": "^1.1.0", + "chalk": "^4.1.2", + "copy-props": "^4.0.0", + "gulplog": "^2.2.0", + "interpret": "^3.1.1", + "liftoff": "^5.0.1", + "mute-stdout": "^2.0.0", + "replace-homedir": "^2.0.0", + "semver-greatest-satisfied-range": "^2.0.0", + "string-width": "^4.2.3", + "v8flags": "^4.0.0", + "yargs": "^16.2.0" + }, + "bin": { + "gulp": "bin/gulp.js" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/gulp-cli/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/gulp-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/gulp-cli/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/gulp-cli/node_modules/interpret": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", + "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/gulp-cli/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha512-a2scActrQrDBpBbR3WUZGyGS1JEPLg5PZJdIa7/Bi3GuKAmPYDK6SFhy/NZq5R8KsKKFvtfR0fakbUCcKGCCjg==", + "license": "MIT", + "dependencies": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-imagemin": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/gulp-imagemin/-/gulp-imagemin-9.2.0.tgz", + "integrity": "sha512-y7yAHTUzfHHq6njHY2OIvLOcffF1I/ULSlfzunnIvPeNNpYDArwrlqCzPvnN4Le0p3H/1ERAAQJJPMhbnTRnFQ==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "gulp-plugin-extras": "^1.0.0", + "imagemin": "^9.0.0", + "plur": "^5.1.0", + "pretty-bytes": "^6.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + }, + "optionalDependencies": { + "imagemin-gifsicle": "^7.0.0", + "imagemin-mozjpeg": "^10.0.0", + "imagemin-optipng": "^8.0.0", + "imagemin-svgo": "^10.0.1" + }, + "peerDependencies": { + "gulp": ">=4" + }, + "peerDependenciesMeta": { + "gulp": { + "optional": true + } + } + }, + "node_modules/gulp-imagemin/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/gulp-minify-css": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/gulp-minify-css/-/gulp-minify-css-1.2.4.tgz", + "integrity": "sha512-byBqFQM/HrZoUVYihu/03iYH4m7U5TjSGhr6/7JvpMHh9+woewsCtEp6Noif2VXB+idDoM4ECd9sw+St+KFqsg==", + "deprecated": "Please use gulp-clean-css", + "license": "MIT", + "dependencies": { + "clean-css": "^3.3.3", + "gulp-util": "^3.0.5", + "object-assign": "^4.0.1", + "readable-stream": "^2.0.0", + "vinyl-bufferstream": "^1.0.1", + "vinyl-sourcemaps-apply": "^0.2.0" + } + }, + "node_modules/gulp-minify-html": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/gulp-minify-html/-/gulp-minify-html-1.0.6.tgz", + "integrity": "sha512-toazuTI8XG4BNOY7L/4Da258tgWbtFlfPAyZi0QwrDc+ba11LMMT8dLhGo48SMAil6Wu8PuTcICfkJ6d/dCjLQ==", + "license": "MIT", + "dependencies": { + "gulp-util": "^3.0.3", + "minimize": "^1.5.0", + "through2": "^0.6.1" + } + }, + "node_modules/gulp-minify-html/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, + "node_modules/gulp-minify-html/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/gulp-minify-html/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "license": "MIT" + }, + "node_modules/gulp-minify-html/node_modules/through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==", + "license": "MIT", + "dependencies": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "node_modules/gulp-plugin-extras": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/gulp-plugin-extras/-/gulp-plugin-extras-1.1.0.tgz", + "integrity": "sha512-T0AXOEVoKYzLIBlwEZ7LtAx2w4ExIozIoxVeYEVLFbdxI7i0sWvFDq0F8mm47djixDF3vAqDPoyGwh3Sg/PWtQ==", + "license": "MIT", + "dependencies": { + "@types/vinyl": "^2.0.12", + "chalk": "^5.3.0", + "easy-transform-stream": "^1.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gulp-plugin-extras/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/gulp-rename": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-2.1.0.tgz", + "integrity": "sha512-dGuzuH8jQGqCMqC544IEPhs5+O2l+IkdoSZsgd4kY97M1CxQeI3qrmweQBIrxLBbjbe/8uEWK8HHcNBc3OCy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/gulp-uglify": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-3.0.2.tgz", + "integrity": "sha512-gk1dhB74AkV2kzqPMQBLA3jPoIAPd/nlNzP2XMDSG8XZrqnlCiDGAqC+rZOumzFvB5zOphlFh6yr3lgcAb/OOg==", + "license": "MIT", + "dependencies": { + "array-each": "^1.0.1", + "extend-shallow": "^3.0.2", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "isobject": "^3.0.1", + "make-error-cause": "^1.1.1", + "safe-buffer": "^5.1.2", + "through2": "^2.0.0", + "uglify-js": "^3.0.5", + "vinyl-sourcemaps-apply": "^0.2.0" + } + }, + "node_modules/gulp-uglify/node_modules/glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "license": "MIT", + "dependencies": { + "sparkles": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-uglify/node_modules/gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha512-hm6N8nrm3Y08jXie48jsC55eCZz9mnb4OirAStEk2deqeyhXU3C1otDVh+ccttMuc1sBi6RX6ZJ720hs9RCvgw==", + "license": "MIT", + "dependencies": { + "glogg": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-uglify/node_modules/sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha512-q5oWPc12lwSFS9h/4VIjG+1NuNDlJ48ywV2JKItY4Ycc/n1fXJeYPVQsfu5ZrhQi7FGSDBalwUCLar/GyHXKGw==", + "deprecated": "gulp-util is deprecated - replace it, following the guidelines at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5", + "license": "MIT", + "dependencies": { + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", + "replace-ext": "0.0.1", + "through2": "^2.0.0", + "vinyl": "^0.5.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/gulp-util/node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/gulp-util/node_modules/clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA==", + "license": "MIT" + }, + "node_modules/gulp-util/node_modules/dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha512-GODcnWq3YGoTnygPfi02ygEiRxqUxpJwuRHjdhJYuxpcZmDq4rjBiXYmbCCzStxo176ixfLT6i4NPwQooRySnw==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/gulp-util/node_modules/glogg": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", + "license": "MIT", + "dependencies": { + "sparkles": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-util/node_modules/gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha512-hm6N8nrm3Y08jXie48jsC55eCZz9mnb4OirAStEk2deqeyhXU3C1otDVh+ccttMuc1sBi6RX6ZJ720hs9RCvgw==", + "license": "MIT", + "dependencies": { + "glogg": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-util/node_modules/object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gulp-util/node_modules/sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/gulp-util/node_modules/vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha512-P5zdf3WB9uzr7IFoVQ2wZTmUwHL8cMZWJGzLBNCHNZ3NB6HTMsYABtt7z8tAGIINLXyAob9B9a1yzVGMFOYKEA==", + "license": "MIT", + "dependencies": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + }, + "engines": { + "node": ">= 0.9" + } + }, + "node_modules/gulplog": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-2.2.0.tgz", + "integrity": "sha512-V2FaKiOhpR3DRXZuYdRLn/qiY0yI5XmqbTKrYbdemJ+xOh2d2MOweI/XFgMzd/9+1twdvMwllnZbWZNJ+BOm4A==", + "license": "MIT", + "dependencies": { + "glogg": "^2.2.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true, + "license": "MIT" + }, + "node_modules/handlebars": { + "version": "4.7.9", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", + "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha512-+F4GzLjwHNNDEAJW2DC1xXfEoPkRDmUdJ7CBYw4MpqtDwOnqdImJl7GWlpqx+Wko6//J8uKTnIe4wZSv7yCqmw==", + "license": "MIT", + "dependencies": { + "sparkles": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/has-gulplog/node_modules/sparkles": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz", + "integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbol-support-x": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz", + "integrity": "sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw==", + "license": "MIT", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "license": "MIT", + "optional": true, + "dependencies": { + "has-symbol-support-x": "^1.4.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/hash-wasm": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/hash-wasm/-/hash-wasm-4.12.0.tgz", + "integrity": "sha512-+/2B2rYLb48I/evdOIhP+K/DD2ca2fgBjp6O+GBEnCDk2e4rpeXIK8GvIyRPjTezgmWn9gmKwkQjjx6BtqDHVQ==", + "license": "MIT" + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/highlight.js": { + "version": "11.11.1", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz", + "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "license": "MIT", + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hooker": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", + "integrity": "sha512-t+UerCsQviSymAInD01Pw+Dn/usmz1sRO+3Zk1+lx8eg+WKpD2ulcwWqHHL0+aseRBr+3+vIhiG1K1JTwaIcTA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-minifier-terser/node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.7", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.7.tgz", + "integrity": "sha512-md+vXtdCAe60s1k6AU3dUyMJnDxUyQAwfwPKoLisvgUF1IXjtlLsk2se54+qfL9Mdm26bbwvjJybpNx48NKRLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/htmlparser2": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha512-RSOwLNCnCLDRB9XpSfCzsLzzX8COezhJ3D4kRBNWh0NC/facp1hAMmM8zD7kC01My8vD6lGEbPMlbRW/EwGK5w==", + "license": "MIT", + "dependencies": { + "domelementtype": "^1.3.0", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "license": "BSD-2-Clause" + }, + "node_modules/http-cache-semantics": { + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz", + "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", + "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz", + "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "devOptional": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/hyperdyperid": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz", + "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.18" + } + }, + "node_modules/iced-error": { + "version": "0.0.13", + "resolved": "https://registry.npmjs.org/iced-error/-/iced-error-0.0.13.tgz", + "integrity": "sha512-yEEaG8QfyyRL0SsbNNDw3rVgTyqwHFMCuV6jDvD43f/2shmdaFXkqvFLGhDlsYNSolzYHwVLM/CrXt9GygYopA==" + }, + "node_modules/iced-lock": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/iced-lock/-/iced-lock-1.1.0.tgz", + "integrity": "sha512-J9UMVitgTMYrkUil5EB9/Q4BPWiMpFH156yjDlmMoMRKs3s3PnXj/6G0UlzIOGnNi5JVNk/zVYLXVnuo+1QnqQ==", + "dependencies": { + "iced-runtime": "^1.0.0" + } + }, + "node_modules/iced-runtime": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/iced-runtime/-/iced-runtime-1.0.4.tgz", + "integrity": "sha512-rgiJXNF6ZgF2Clh/TKUlBDW3q51YPDJUXmxGQXx1b8tbZpVpTn+1RX9q1sjNkujXIIaVxZByQzPHHORg7KV51g==" + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/idb-keyval": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.2.tgz", + "integrity": "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==", + "license": "Apache-2.0" + }, + "node_modules/identifier-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/identifier-regex/-/identifier-regex-1.0.1.tgz", + "integrity": "sha512-ZrYyM0sozNPZlvBvE7Oq9Bn44n0qKGrYu5sQ0JzMUnjIhpgWYE2JB6aBoFwEYdPjqj7jPyxXTMJiHDOxDfd8yw==", + "license": "MIT", + "dependencies": { + "reserved-identifiers": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-dimensions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/image-dimensions/-/image-dimensions-2.5.0.tgz", + "integrity": "sha512-CKZPHjAEtSg9lBV9eER0bhNn/yrY7cFEQEhkwjLhqLY+Na8lcP1pEyWsaGMGc8t2qbKWA/tuqbhFQpOKGN72Yw==", + "license": "MIT", + "bin": { + "image-dimensions": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/image-q": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz", + "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==", + "license": "MIT", + "dependencies": { + "@types/node": "16.9.1" + } + }, + "node_modules/image-q/node_modules/@types/node": { + "version": "16.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz", + "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==", + "license": "MIT" + }, + "node_modules/imagemin": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-9.0.1.tgz", + "integrity": "sha512-UoHOfynN8QeqRoUGunn6ilMnLpJ+utbmleP2ufcFqaGal8mY/PeOpV43N31uqtb+CBMFqQ7hxgKzIaAAnmcrdA==", + "license": "MIT", + "dependencies": { + "change-file-extension": "^0.1.1", + "environment": "^1.0.0", + "file-type": "^19.0.0", + "globby": "^14.0.1", + "image-dimensions": "^2.3.0", + "junk": "^4.0.1", + "ow": "^2.0.0", + "p-pipe": "^4.0.0", + "slash": "^5.1.0", + "uint8array-extras": "^1.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-gifsicle": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/imagemin-gifsicle/-/imagemin-gifsicle-7.0.0.tgz", + "integrity": "sha512-LaP38xhxAwS3W8PFh4y5iQ6feoTSF+dTAXFRUEYQWYst6Xd+9L/iPk34QGgK/VO/objmIlmq9TStGfVY2IcHIA==", + "license": "MIT", + "optional": true, + "dependencies": { + "execa": "^1.0.0", + "gifsicle": "^5.0.0", + "is-gif": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/imagemin/imagemin-gifsicle?sponsor=1" + } + }, + "node_modules/imagemin-mozjpeg": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/imagemin-mozjpeg/-/imagemin-mozjpeg-10.0.0.tgz", + "integrity": "sha512-DK85QNOjS3/GzWYfNB3CACMZD10sIQgFDv1+WTOnZljgltQTEyATjdyUVyjKu5q4sCESQdwvwq7WEZzJ5fFjlg==", + "license": "MIT", + "optional": true, + "dependencies": { + "execa": "^6.0.0", + "is-jpg": "^3.0.0", + "mozjpeg": "^8.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/execa": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz", + "integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==", + "license": "MIT", + "optional": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^3.0.1", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/human-signals": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz", + "integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "license": "MIT", + "optional": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-mozjpeg/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imagemin-optipng": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/imagemin-optipng/-/imagemin-optipng-8.0.0.tgz", + "integrity": "sha512-CUGfhfwqlPjAC0rm8Fy+R2DJDBGjzy2SkfyT09L8rasnF9jSoHFqJ1xxSZWK6HVPZBMhGPMxCTL70OgTHlLF5A==", + "license": "MIT", + "optional": true, + "dependencies": { + "exec-buffer": "^3.0.0", + "is-png": "^2.0.0", + "optipng-bin": "^7.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/imagemin-svgo": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/imagemin-svgo/-/imagemin-svgo-10.0.1.tgz", + "integrity": "sha512-v27/UTGkb3vrm5jvjsMGQ2oxaDfSOTBfJOgmFO2fYepx05bY1IqWCK13aDytVR+l9w9eOlq0NMCLbxJlghYb2g==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-svg": "^4.3.1", + "svgo": "^2.5.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sindresorhus/imagemin-svgo?sponsor=1" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/import-fresh/node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-lazy": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-3.1.0.tgz", + "integrity": "sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/imports-loader": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/imports-loader/-/imports-loader-5.0.0.tgz", + "integrity": "sha512-tXgL8xxZFjOjQLLiE7my00UUQfktg4G8fdpXcZphL0bJWbk9eCxKKFaCwmFRcwyRJQl95GXBL1DoE1rCS/tcPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "source-map-js": "^1.0.2", + "strip-comments": "^2.0.1" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "devOptional": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/interpret": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha512-CLM8SNMDu7C5psFCn6Wg/tgpj/bKAg7hc2gWqcuR9OD5Ft9PhBpIu8PLicPeis+xDd6YX2ncI8MCA64I9tftIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/into-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/into-stream/-/into-stream-3.1.0.tgz", + "integrity": "sha512-TcdjPibTksa1NQximqep2r17ISRiNE9fwlfbg3F8ANdvP5/yrFTew86VcO//jk4QTaMlbjypPBq76HN2zaKfZQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "from2": "^2.1.1", + "p-is-promise": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ip-address": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-regex": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", + "integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ipaddr.js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz", + "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/irregular-plurals": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", + "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-absolute": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "license": "MIT", + "dependencies": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-electron": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-electron/-/is-electron-2.2.2.tgz", + "integrity": "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==", + "license": "MIT" + }, + "node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extendable/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-gif": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-gif/-/is-gif-3.0.0.tgz", + "integrity": "sha512-IqJ/jlbw5WJSNfwQ/lHEDXF8rxhRgF6ythk2oiEvhpG29F704eX9NO6TvPfMiq9DrbwgcEDnETYNcZDPewQoVw==", + "license": "MIT", + "optional": true, + "dependencies": { + "file-type": "^10.4.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-gif/node_modules/file-type": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-10.11.0.tgz", + "integrity": "sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-identifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-identifier/-/is-identifier-1.0.1.tgz", + "integrity": "sha512-HQ5v4rEJ7REUV54bCd2l5FaD299SGDEn2UPoVXaTHAyGviLq2menVUD2udi3trQ32uvB6LdAh/0ck2EuizrtpA==", + "license": "MIT", + "dependencies": { + "identifier-regex": "^1.0.0", + "super-regex": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-jpg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-jpg/-/is-jpg-3.0.0.tgz", + "integrity": "sha512-Vcd67KWHZblEKEBrtP25qLZ8wN9ICoAhl1pKUqD7SM7hf2qtuRl7loDgP5Zigh2oN/+7uj+KVyC0eRJvgOEFeQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==", + "license": "MIT", + "optional": true + }, + "node_modules/is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-network-error": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.2.tgz", + "integrity": "sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-like": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", + "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lodash.isfinite": "^3.3.2" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "license": "MIT", + "optional": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-png": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-png/-/is-png-2.0.0.tgz", + "integrity": "sha512-4KPGizaVGj2LK7xwJIz8o5B2ubu1D/vcQsgOGFEDlpcvgZHto4gBnyd0ig7Ws+67ixmwKoNmu0hYnpo6AaKb5g==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "license": "MIT", + "dependencies": { + "is-unc-path": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-retry-allowed": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz", + "integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-svg": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-4.4.0.tgz", + "integrity": "sha512-v+AgVwiK5DsGtT9ng+m4mClp6zDAmwrW8nZi6Gg15qzvBnRWWdfWA1TGaXyCDnWq5g5asofIgMVl3PjKxvk1ug==", + "license": "MIT", + "optional": true, + "dependencies": { + "fast-xml-parser": "^4.1.3" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unc-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "license": "MIT", + "dependencies": { + "unc-path-regex": "^0.1.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "license": "MIT" + }, + "node_modules/is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is2": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/is2/-/is2-2.0.9.tgz", + "integrity": "sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "ip-regex": "^4.1.0", + "is-url": "^1.2.4" + }, + "engines": { + "node": ">=v0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "license": "MIT", + "optional": true, + "dependencies": { + "has-to-string-tag-x": "^1.2.0", + "is-object": "^1.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jimp": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/jimp/-/jimp-1.6.1.tgz", + "integrity": "sha512-hNQh6rZtWfSVWSNVmvq87N5BPJsNH7k7I7qyrXf9DOma9xATQk3fsyHazCQe51nCjdkoWdTmh0vD7bjVSLoxxw==", + "license": "MIT", + "dependencies": { + "@jimp/core": "1.6.1", + "@jimp/diff": "1.6.1", + "@jimp/js-bmp": "1.6.1", + "@jimp/js-gif": "1.6.1", + "@jimp/js-jpeg": "1.6.1", + "@jimp/js-png": "1.6.1", + "@jimp/js-tiff": "1.6.1", + "@jimp/plugin-blit": "1.6.1", + "@jimp/plugin-blur": "1.6.1", + "@jimp/plugin-circle": "1.6.1", + "@jimp/plugin-color": "1.6.1", + "@jimp/plugin-contain": "1.6.1", + "@jimp/plugin-cover": "1.6.1", + "@jimp/plugin-crop": "1.6.1", + "@jimp/plugin-displace": "1.6.1", + "@jimp/plugin-dither": "1.6.1", + "@jimp/plugin-fisheye": "1.6.1", + "@jimp/plugin-flip": "1.6.1", + "@jimp/plugin-hash": "1.6.1", + "@jimp/plugin-mask": "1.6.1", + "@jimp/plugin-print": "1.6.1", + "@jimp/plugin-quantize": "1.6.1", + "@jimp/plugin-resize": "1.6.1", + "@jimp/plugin-rotate": "1.6.1", + "@jimp/plugin-threshold": "1.6.1", + "@jimp/types": "1.6.1", + "@jimp/utils": "1.6.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/jpeg-js": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz", + "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", + "license": "BSD-3-Clause" + }, + "node_modules/jq-web": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/jq-web/-/jq-web-0.6.2.tgz", + "integrity": "sha512-+7XvjBYwTx4vP5PYkf6Q6orubO/v+UgMU6By1GritrmShr9QpT3UKa4ANzXWQfhdqtBnQYXsm7ZNbdIHT6tYpQ==", + "license": "ISC" + }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "license": "MIT" + }, + "node_modules/js-sha3": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.9.3.tgz", + "integrity": "sha512-BcJPCQeLg6WjEx3FE591wVAevlli8lxsxm9/FzV4HXkV49TmBH38Yvrpce6fjbADGMKFrBMGTqrVz3qPIZ88Gg==", + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", + "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdom": { + "version": "24.1.3", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.3.tgz", + "integrity": "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.0.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.1.4", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsep": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", + "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", + "license": "MIT", + "engines": { + "node": ">= 10.16.0" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonata": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.1.0.tgz", + "integrity": "sha512-OCzaRMK8HobtX8fp37uIVmL8CY1IGc/a6gLsDqz3quExFR09/U78HUzWYr7T31UEB6+Eu0/8dkVD5fFDOl9a8w==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/jsonpath-plus": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.4.0.tgz", + "integrity": "sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA==", + "license": "MIT", + "dependencies": { + "@jsep-plugin/assignment": "^1.3.0", + "@jsep-plugin/regex": "^1.0.4", + "jsep": "^1.4.0" + }, + "bin": { + "jsonpath": "bin/jsonpath-cli.js", + "jsonpath-plus": "bin/jsonpath-cli.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "license": "MIT", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/jsqr": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.4.0.tgz", + "integrity": "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A==", + "license": "Apache-2.0" + }, + "node_modules/jsrsasign": { + "version": "11.1.3", + "resolved": "https://registry.npmjs.org/jsrsasign/-/jsrsasign-11.1.3.tgz", + "integrity": "sha512-nPnK5D/4lv0Dwr7TlzrKtAd8JlLZwFTqTUUB3NQCbtdobcRcohGFxjbPySDVh74iWUudcCsapYT6OxoyhJLhhA==", + "license": "MIT" + }, + "node_modules/jszip": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", + "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", + "dev": true, + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" + } + }, + "node_modules/junk": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/junk/-/junk-4.0.1.tgz", + "integrity": "sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "license": "MIT", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.3.tgz", + "integrity": "sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==", + "license": "MIT", + "dependencies": { + "jwa": "^1.4.2", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/kbpgp": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/kbpgp/-/kbpgp-2.1.17.tgz", + "integrity": "sha512-pnjH7amyg6dZLXyF42BKbCTST0l0r1ErunqtFRrJCkHkGJb83cZZmx1pnqNFr+d/ls+5gvcHrZLPfUG5q7oRYw==", + "license": "BSD-3-Clause", + "dependencies": { + "bn": "^1.0.5", + "bzip-deflate": "^1.0.0", + "deep-equal": "^1.1.0", + "iced-error": "0.0.13", + "iced-lock": "^1.0.2", + "iced-runtime": "^1.0.4", + "keybase-ecurve": "^1.0.1", + "keybase-nacl": "^1.1.2", + "minimist": "^1.2.0", + "pgp-utils": "0.0.35", + "purepack": "^1.0.5", + "triplesec": "^4.0.3", + "tweetnacl": "^0.13.1" + } + }, + "node_modules/keybase-ecurve": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/keybase-ecurve/-/keybase-ecurve-1.0.1.tgz", + "integrity": "sha512-2GlVxDsNF+52LtYjgFsjoKuN7MQQgiVeR4HRdJxLuN8fm4mf4stGKPUjDJjky15c/98UsZseLjp7Ih5X0Sy1jQ==", + "dependencies": { + "bn": "^1.0.4" + } + }, + "node_modules/keybase-nacl": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/keybase-nacl/-/keybase-nacl-1.1.4.tgz", + "integrity": "sha512-7TFyWLq42CQs7JES9arR+Vnv/eMk5D6JT1Y8samrEA5ff3FOmaiRcXIVrwJQd3KJduxmSjgAjdkXlQK7Q437xQ==", + "license": "BSD-3-Clause", + "dependencies": { + "iced-runtime": "^1.0.2", + "tweetnacl": "^0.13.1", + "uint64be": "^1.0.1" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kuler": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-0.0.0.tgz", + "integrity": "sha512-5h7OEDPSHedoxB6alJXF4FtFB95QA2OTXGCFaLCutHdkh0VrcSSy/OwH9UHtYqsG2KTrdN7gVEc9KgCBNah/yA==", + "license": "MIT", + "dependencies": { + "colornames": "0.0.2" + } + }, + "node_modules/last-run": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-2.0.0.tgz", + "integrity": "sha512-j+y6WhTLN4Itnf9j5ZQos1BGPCS8DAwmgMroR3OzfxAsBxam0hMw7J8M3KqZl0pLQJ1jNnwIexg5DYpC/ctwEQ==", + "license": "MIT", + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/launch-editor": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.13.2.tgz", + "integrity": "sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "picocolors": "^1.1.1", + "shell-quote": "^1.8.3" + } + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lead": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-4.0.0.tgz", + "integrity": "sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/libbzip2-wasm": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/libbzip2-wasm/-/libbzip2-wasm-0.0.4.tgz", + "integrity": "sha512-RqscTx95+RTKhFAyjedsboR0Lmo3zd8//EuRwQXkdWmsCwYlzarVRaiYg6kS1O8m10MCQkGdrnlK9L4eAmZUwA==", + "license": "ISC" + }, + "node_modules/libyara-wasm": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/libyara-wasm/-/libyara-wasm-1.2.1.tgz", + "integrity": "sha512-PNqUNWnwjZLe55iA8Rv6vLQRjSdO2OnVg24aRE8v+ytR8CRB8agIG6pS9h2VQejuJP1A/uR4pwcBggUxoNC7DA==", + "license": "ISC" + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/liftoff": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-5.0.1.tgz", + "integrity": "sha512-wwLXMbuxSF8gMvubFcFRp56lkFV69twvbU5vDPbaw+Q+/rF8j0HKjGbIdlSi+LuJm9jf7k9PB+nTxnsLMPcv2Q==", + "license": "MIT", + "dependencies": { + "extend": "^3.0.2", + "findup-sync": "^5.0.0", + "fined": "^2.0.0", + "flagged-respawn": "^2.0.0", + "is-plain-object": "^5.0.0", + "rechoir": "^0.8.0", + "resolve": "^1.20.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/liftup": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/liftup/-/liftup-3.0.1.tgz", + "integrity": "sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "extend": "^3.0.2", + "findup-sync": "^4.0.0", + "fined": "^1.2.0", + "flagged-respawn": "^1.0.1", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.1", + "rechoir": "^0.7.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/liftup/node_modules/findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/liftup/node_modules/fined": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz", + "integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/liftup/node_modules/flagged-respawn": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz", + "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/liftup/node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/liftup/node_modules/rechoir": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", + "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.9.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/livereload-js": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-2.4.0.tgz", + "integrity": "sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==", + "dev": true, + "license": "MIT" + }, + "node_modules/loader-runner": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/loader-utils-webpack-v4": { + "name": "loader-utils", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ==", + "license": "MIT" + }, + "node_modules/lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha512-mTzAr1aNAv/i7W43vOR/uD/aJ4ngbtsRaCubp2BfZhlGU/eORUjg/7F6X0orNMdv33JOrdgGybtvMN/po3EWrA==", + "license": "MIT" + }, + "node_modules/lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha512-H94wl5P13uEqlCg7OcNNhMQ8KvWSIyqXzOPusRgHC9DK3o54P6P3xtbXlVbRABG4q5gSmp7EDdJ0MSuW9HX6Mg==", + "license": "MIT" + }, + "node_modules/lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA==", + "license": "MIT" + }, + "node_modules/lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ==", + "license": "MIT" + }, + "node_modules/lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha512-Sjlavm5y+FUVIF3vF3B75GyXrzsfYV8Dlv3L4mEpuB9leg8N6yf/7rU06iLPx9fY0Mv3khVp9p7Dx0mGV6V5OQ==", + "license": "MIT" + }, + "node_modules/lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha512-OrPwdDc65iJiBeUe5n/LIjd7Viy99bKwDdk7Z5ljfZg0uFRFlfQaCy9tZ4YMAag9WAZmlVpe1iZrkIMMSMHD3w==", + "license": "MIT" + }, + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", + "license": "MIT" + }, + "node_modules/lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ==", + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.difference": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha512-n1PZMXgaaDWZDSvuNZ/8XOcYO2hOKDqZel5adtR30VKQAtoWs/5AOeFA0vPV8moiPzlqe7F4cP2tzpFewQyelQ==", + "license": "MIT", + "dependencies": { + "lodash._root": "^3.0.0" + } + }, + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", + "license": "MIT" + }, + "node_modules/lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==", + "license": "MIT" + }, + "node_modules/lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ==", + "license": "MIT" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", + "license": "MIT" + }, + "node_modules/lodash.isfinite": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", + "integrity": "sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", + "license": "MIT" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "license": "MIT" + }, + "node_modules/lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ==", + "license": "MIT", + "dependencies": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", + "license": "MIT" + }, + "node_modules/lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw==", + "license": "MIT" + }, + "node_modules/lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha512-0B4Y53I0OgHUJkt+7RmlDFWKjVAI/YUpWNiL9GQz5ORDr4ttgfQGo+phBWKFLJbBdtOwgMuUkdOHOnPg45jKmQ==", + "deprecated": "This package is deprecated. Use https://socket.dev/npm/package/eta instead.", + "license": "MIT", + "dependencies": { + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" + } + }, + "node_modules/lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha512-TcrlEr31tDYnWkHFWDCV3dHYroKEXpJZ2YJYvJdhN+y4AkWMDZ5I4I8XDtUKqSAyG81N7w+I1mFEJtcED+tGqQ==", + "license": "MIT", + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" + } + }, + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/loglevel": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.2.tgz", + "integrity": "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/loglevel-message-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/loglevel-message-prefix/-/loglevel-message-prefix-3.0.0.tgz", + "integrity": "sha512-/cBEOqsuU0vJsFm4n92R7h6mkiKqt8vh+JOmW722DTZVVD7egEpVOx66re3vWxO7pii3B4eQuqm2qfqq5cAs0w==", + "deprecated": "Use @natlibfi/loglevel-message-prefix instead", + "license": "MIT", + "dependencies": { + "es6-polyfills": "^2.0.0", + "loglevel": "^1.4.0" + } + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.1" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", + "license": "MIT", + "dependencies": { + "es5-ext": "~0.10.2" + } + }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "license": "MIT", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/lz4js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/lz4js/-/lz4js-0.2.0.tgz", + "integrity": "sha512-gY2Ia9Lm7Ep8qMiuGRhvUq0Q7qUereeldZPP1PMEJxPtEWHJLqw9pgX68oHajBH0nzJK4MaZEA/YNV3jT8u8Bg==", + "license": "ISC" + }, + "node_modules/make-asynchronous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/make-asynchronous/-/make-asynchronous-1.1.0.tgz", + "integrity": "sha512-ayF7iT+44LXdxJLTrTd3TLQpFDDvPCBxXxbv+pMUSuHA5Q8zyAfwkRP6aHHwNVFBUFWtxAHqwNJxF8vMZLAbVg==", + "license": "MIT", + "dependencies": { + "p-event": "^6.0.0", + "type-fest": "^4.6.0", + "web-worker": "^1.5.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-asynchronous/node_modules/p-event": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-6.0.1.tgz", + "integrity": "sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==", + "license": "MIT", + "dependencies": { + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-asynchronous/node_modules/p-timeout": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", + "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-asynchronous/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/make-dir/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "license": "ISC" + }, + "node_modules/make-error-cause": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/make-error-cause/-/make-error-cause-1.2.2.tgz", + "integrity": "sha512-4TO2Y3HkBnis4c0dxhAgD/jprySYLACf7nwN6V0HAHDx59g12WlRpUmFy1bRHamjGUEEBrEvCq6SUpsEE2lhUg==", + "license": "Apache-2.0", + "dependencies": { + "make-error": "^1.2.0" + } + }, + "node_modules/make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "license": "CC0-1.0", + "optional": true + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "4.57.2", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.57.2.tgz", + "integrity": "sha512-2nWzSsJzrukurSDna4Z0WywuScK4Id3tSKejgu74u8KCdW4uNrseKRSIDg75C6Yw5ZRqBe0F0EtMNlTbUq8bAQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jsonjoy.com/fs-core": "4.57.2", + "@jsonjoy.com/fs-fsa": "4.57.2", + "@jsonjoy.com/fs-node": "4.57.2", + "@jsonjoy.com/fs-node-builtins": "4.57.2", + "@jsonjoy.com/fs-node-to-fsa": "4.57.2", + "@jsonjoy.com/fs-node-utils": "4.57.2", + "@jsonjoy.com/fs-print": "4.57.2", + "@jsonjoy.com/fs-snapshot": "4.57.2", + "@jsonjoy.com/json-pack": "^1.11.0", + "@jsonjoy.com/util": "^1.9.0", + "glob-to-regex.js": "^1.0.1", + "thingies": "^2.5.0", + "tree-dump": "^1.0.3", + "tslib": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/memoizee": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.3.10.tgz", + "integrity": "sha512-LLzVUuWwGBKK188spgOK/ukrp5zvd9JGsiLDH41pH9vt5jvhZfsu5pxDuAnYAMG8YEGce72KO07sSBy9KkvOfw==", + "license": "MIT", + "dependencies": { + "d": "~0.1.1", + "es5-ext": "~0.10.11", + "es6-weak-map": "~0.1.4", + "event-emitter": "~0.3.4", + "lru-queue": "0.1", + "next-tick": "~0.2.2", + "timers-ext": "0.1" + } + }, + "node_modules/memoizee/node_modules/next-tick": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-0.2.2.tgz", + "integrity": "sha512-f7h4svPtl+QidoBv4taKXUjJ70G2asaZ8G28nS0OkqaalX8dwwrtWtyxEDPK62AC00ur/+/E0pUwBwY5EPn15Q==", + "license": "MIT" + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, + "node_modules/mime": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", + "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.0.tgz", + "integrity": "sha512-540P2c5dYnJlyJxTaSloliZexv8rji6rY8FhQN+WF/82iHQfA23j/xtJx97L+mXOML27EqksSek/g4eK7jaL3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimize": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/minimize/-/minimize-1.8.1.tgz", + "integrity": "sha512-vMXaO5/HgxKi06udiQ4MibwOb0mwxzcpX4DDf6G9k2h6fKNoY1xt8Wrzp82qBm4oZ5aQRP2ry1NzbwEuWBx9Ig==", + "license": "MIT", + "dependencies": { + "argh": "~0.1.4", + "async": "~1.5.2", + "cli-color": "~1.1.0", + "diagnostics": "~1.0.1", + "emits": "~3.0.0", + "htmlparser2": "~3.9.0", + "node-uuid": "~1.4.7" + }, + "bin": { + "minimize": "bin/minimize" + } + }, + "node_modules/minimize/node_modules/async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", + "license": "MIT" + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mocha": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/modify-source-webpack-plugin": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/modify-source-webpack-plugin/-/modify-source-webpack-plugin-4.1.0.tgz", + "integrity": "sha512-UaLQyFXoPWpWxkNUBFo9BotC20CCAGe7HEX9iKtB0P0MgNXgURf9TXUgNGuY5iVV5lDDQtcMjT2vneQWnNmwEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "loader-utils-webpack-v4": "npm:loader-utils@^2.0.4", + "schema-utils": "^4.0.0" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/moment-timezone": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.6.2.tgz", + "integrity": "sha512-lDsQv8FoGdBUdf0+TjGsq2orxKuXdwFlQ6Zw6TX3xIcTwTfEpCLyKqvEauvCHJ8iu3KBV8+uPhlv70YsNGdUBQ==", + "license": "MIT", + "dependencies": { + "moment": "^2.29.4" + }, + "engines": { + "node": "*" + } + }, + "node_modules/more-entropy": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/more-entropy/-/more-entropy-0.0.7.tgz", + "integrity": "sha512-e0TxQtU1F6/ZA8WnEA2JLQwwDqBTtZFLJSW7rWgUsQou35wx1IOL0g2O7q7oGoMgIJto+jHMnNGHLfSiylHRrw==", + "dependencies": { + "iced-runtime": ">=0.0.1" + } + }, + "node_modules/morgan": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz", + "integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.1.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/morgan/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/morgan/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/mozjpeg": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/mozjpeg/-/mozjpeg-8.0.0.tgz", + "integrity": "sha512-Ca2Yhah9hG0Iutgsn8MOrAl37P9ThnKsJatjXoWdUO+8X8GeG/6ahvHZrTyqvbs6leMww1SauWUCao/L9qBuFQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bin-build": "^3.0.0", + "bin-wrapper": "^4.0.0" + }, + "bin": { + "mozjpeg": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha512-7ZxrUybYv9NonoXgwoOqtStIu18D1c3eFZj27hqgf5kBrBF8Q+tE8V0MW8dKM5QLkQPh1JhhbKgHLY9kifov4Q==", + "license": "MIT", + "dependencies": { + "duplexer2": "0.0.2" + } + }, + "node_modules/mute-stdout": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-2.0.0.tgz", + "integrity": "sha512-32GSKM3Wyc8dg/p39lWPKYu8zci9mJFzV1Np9Of0ZEpe6Fhssn/FbI7ywAMd40uX+p3ZKh3T5EeCFv81qS3HmQ==", + "license": "MIT", + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, + "node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/netmask": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz", + "integrity": "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "license": "ISC" + }, + "node_modules/ngeohash": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/ngeohash/-/ngeohash-0.6.3.tgz", + "integrity": "sha512-kltF0cOxgx1AbmVzKxYZaoB0aj7mOxZeHaerEtQV0YaqnkXNq26WWqMmJ6lTqShYxVRWZ/mwvvTrNeOwdslWiw==", + "license": "MIT", + "engines": { + "node": ">=v0.2.0" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "license": "MIT", + "optional": true + }, + "node_modules/nightwatch": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/nightwatch/-/nightwatch-3.15.0.tgz", + "integrity": "sha512-Vvh7TsDyEN1YzOsDNoafEUPJDQ6jfnmJPAsWo/EmygljZiRk1Ja/pEqNAhE5UdYJzF38SNO46gJS8IRk9mUNfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nightwatch/chai": "5.0.3", + "@nightwatch/html-reporter-template": "^0.3.0", + "@nightwatch/nightwatch-inspector": "^1.0.1", + "@types/chai": "^4.3.5", + "@types/selenium-webdriver": "^4.1.14", + "ansi-to-html": "0.7.2", + "aria-query": "5.1.3", + "assertion-error": "1.1.0", + "boxen": "5.1.2", + "chai-nightwatch": "^0.5.3", + "chalk": "^4.1.2", + "ci-info": "3.3.0", + "cli-table3": "^0.6.3", + "devtools-protocol": "^0.0.1140464", + "didyoumean": "^1.2.2", + "dotenv": "16.3.1", + "ejs": "^3.1.10", + "envinfo": "7.11.0", + "glob": "7.2.3", + "jsdom": "^24.1.0", + "lodash": "^4.17.21", + "minimatch": "3.1.2", + "minimist": "1.2.6", + "mocha": "10.8.2", + "nightwatch-axe-verbose": "^2.3.0", + "open": "8.4.2", + "ora": "5.4.1", + "piscina": "^4.3.1", + "selenium-webdriver": "4.27.0", + "semver": "7.5.4", + "stacktrace-parser": "0.1.10", + "strip-ansi": "6.0.1", + "untildify": "4.0.0", + "uuid": "8.3.2" + }, + "bin": { + "nightwatch": "bin/nightwatch" + }, + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "@cucumber/cucumber": "*" + }, + "peerDependenciesMeta": { + "@cucumber/cucumber": { + "optional": true + }, + "chromedriver": { + "optional": true + }, + "geckodriver": { + "optional": true + } + } + }, + "node_modules/nightwatch-axe-verbose": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/nightwatch-axe-verbose/-/nightwatch-axe-verbose-2.5.1.tgz", + "integrity": "sha512-vvLUMyIbGHB8CA5XEGfliPstNCplcHeMn/CWi4cyg0CWMqWypGrV2IgP+WmiWpUgs0qvPmqVHeRHf0BTT7Ez2Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "axe-core": "^4.11.1" + } + }, + "node_modules/nightwatch/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/nightwatch/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/nightwatch/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/nightwatch/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/nightwatch/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nightwatch/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nightwatch/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/nightwatch/node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/nightwatch/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/nightwatch/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nightwatch/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nightwatch/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/nightwatch/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/node-forge": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", + "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-md6": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/node-md6/-/node-md6-0.1.0.tgz", + "integrity": "sha512-n+s6dhxfV2JCRFgNGzdX0SxxL/SyUwR68uGR/rlNVbXhrdti4M1xKHO+PzXtYLUo1DEsWFZe29B3Z9y5JgpfvA==", + "license": "CC0-1.0" + }, + "node_modules/node-releases": { + "version": "2.0.38", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz", + "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha512-TkCET/3rr9mUuRp+CpO7qfgT++aAxfDRaalQhwPFzI9BY/2rCDn6OfpZOVggi1AXfTPpfkTrg5f5WQx5G1uLxA==", + "deprecated": "Use uuid module instead", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/nodom": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/nodom/-/nodom-2.4.0.tgz", + "integrity": "sha512-qhfYgpoCSi37HLiViMlf94YqMQdvk3n3arI1uGbAWZK9NKCYRSI42W8lATeGloYGLYxb8us1C5rTvtsXjwdWQg==", + "license": "ISC" + }, + "node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "license": "MIT", + "engines": { + "node": ">=12.19" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/normalize-url/node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/normalize-url/node_modules/sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/notepack.io": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/notepack.io/-/notepack.io-3.0.1.tgz", + "integrity": "sha512-TKC/8zH5pXIAMVQio2TvVDTtPRX+DJPHDqjRbxogtFiByHyzKmy96RA0JtCQJ+WouyyL4A10xomQzgbUT+1jCg==", + "license": "MIT" + }, + "node_modules/now-and-later": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-3.0.0.tgz", + "integrity": "sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "license": "MIT", + "optional": true, + "dependencies": { + "config-chain": "^1.1.11", + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-conf/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "license": "MIT", + "optional": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/ntlm": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ntlm/-/ntlm-0.1.3.tgz", + "integrity": "sha512-pPlHxhAegZP4QAaOYd51vRd6VXTGfF7VLKJwuwN0iEB1aIi3SnqXYuS/bH/6wWBOq+Ehdil49mHm1Nseon085w==", + "engines": [ + "node" + ] + }, + "node_modules/nwmatcher": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz", + "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==", + "license": "MIT" + }, + "node_modules/nwsapi": { + "version": "2.2.23", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", + "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==", + "license": "MIT", + "dependencies": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true, + "license": "MIT" + }, + "node_modules/omggif": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz", + "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==", + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "license": "MIT", + "bin": { + "opencollective-postinstall": "index.js" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/optipng-bin": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/optipng-bin/-/optipng-bin-7.0.1.tgz", + "integrity": "sha512-W99mpdW7Nt2PpFiaO+74pkht7KEqkXkeRomdWXfEz3SALZ6hns81y/pm1dsGZ6ItUIfchiNIP6ORDr1zETU1jA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bin-build": "^3.0.0", + "bin-wrapper": "^4.0.0" + }, + "bin": { + "optipng": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/os-filter-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-2.0.0.tgz", + "integrity": "sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==", + "license": "MIT", + "optional": true, + "dependencies": { + "arch": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/otpauth": { + "version": "9.3.6", + "resolved": "https://registry.npmjs.org/otpauth/-/otpauth-9.3.6.tgz", + "integrity": "sha512-eIcCvuEvcAAPHxUKC9Q4uCe0Fh/yRc5jv9z+f/kvyIF2LPrhgAOuLB7J9CssGYhND/BL8M9hlHBTFmffpoQlMQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.6.1" + }, + "funding": { + "url": "https://github.com/hectorm/otpauth?sponsor=1" + } + }, + "node_modules/ow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ow/-/ow-2.0.0.tgz", + "integrity": "sha512-ESUigmGrdhUZ2nQSFNkeKSl6ZRPupXzprMs3yF9DYlNVpJ8XAjM/fI9RUZxA7PI1K9HQDCCvBo1jr/GEIo9joQ==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^6.3.0", + "callsites": "^4.1.0", + "dot-prop": "^8.0.2", + "environment": "^1.0.0", + "fast-equals": "^5.0.1", + "is-identifier": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-cancelable": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-0.3.0.tgz", + "integrity": "sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-event": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-1.3.0.tgz", + "integrity": "sha512-hV1zbA7gwqPVFcapfeATaNjQ3J0NuzorHPyG8GPL9g/Y/TplWVBVoCKCXL6Ej2zscrCEv195QNWJXuBH6XZuzA==", + "license": "MIT", + "optional": true, + "dependencies": { + "p-timeout": "^1.1.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-is-promise": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-1.1.0.tgz", + "integrity": "sha512-zL7VE4JVS2IFSkR2GQKDSPEVxkoH43/p7oEnwpdCndKYJO0HVeRB7fA8TJwuLOTBREtK0ea8eHaxdwcpob5dmg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-map-series/-/p-map-series-1.0.0.tgz", + "integrity": "sha512-4k9LlvY6Bo/1FcIdV33wqZQES0Py+iKISU9Uc8p8AjWoZPnFKMpVIVD3s0EYn4jzLh1I+WeUZkJ0Yoa4Qfw3Kg==", + "license": "MIT", + "optional": true, + "dependencies": { + "p-reduce": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-pipe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-4.0.0.tgz", + "integrity": "sha512-HkPfFklpZQPUKBFXzKFB6ihLriIHxnmuQdK9WmLDwe4hf2PdhhfWT/FJa+pc3bA1ywvKXtedxIRmd4Y7BTXE4w==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-reduce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha512-3Tx1T3oM1xO/Y8Gj0sWyE78EIJZ+t+aEmXUdvQgvGmSMri7aPTHoovbXEreWKkL5j21Er60XAWLTzKbAKYOujQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-retry": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz", + "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.2", + "is-network-error": "^1.0.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=16.17" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-1.2.1.tgz", + "integrity": "sha512-gb0ryzr+K2qFqFv6qi3khoeqMZF/+ajxQipEF6NteZVnvz9tzdsfAVj3lYtn1gAXvH5lfLwfxEII799gt/mRIA==", + "license": "MIT", + "optional": true, + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "dev": true, + "license": "MIT", + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/pad-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pad-stream/-/pad-stream-2.0.0.tgz", + "integrity": "sha512-3QeQw19K48BQzUGZ9dEf/slX5Jbfy5ZeBTma2XICketO7kFNK7omF00riVcecOKN+DSiJZcK2em1eYKaVOeXKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "pumpify": "^1.3.3", + "split2": "^2.1.1", + "through2": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "license": "(MIT AND Zlib)" + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-2.0.0.tgz", + "integrity": "sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/parent-module/node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.9.tgz", + "integrity": "sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==", + "license": "ISC", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "pbkdf2": "^3.1.5", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse-bmfont-ascii": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz", + "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==", + "license": "MIT" + }, + "node_modules/parse-bmfont-binary": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz", + "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==", + "license": "MIT" + }, + "node_modules/parse-bmfont-xml": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz", + "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==", + "license": "MIT", + "dependencies": { + "xml-parse-from-string": "^1.0.0", + "xml2js": "^0.5.0" + } + }, + "node_modules/parse-filepath": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", + "license": "MIT", + "dependencies": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/parse-imports": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.2.1.tgz", + "integrity": "sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==", + "dev": true, + "license": "Apache-2.0 AND MIT", + "dependencies": { + "es-module-lexer": "^1.5.3", + "slashes": "^3.0.12" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5/node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==", + "license": "MIT", + "dependencies": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", + "license": "MIT", + "dependencies": { + "path-root-regex": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC" + }, + "node_modules/path/node_modules/util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "license": "MIT", + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", + "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", + "license": "MIT", + "dependencies": { + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "ripemd160": "^2.0.3", + "safe-buffer": "^5.2.1", + "sha.js": "^2.4.12", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/peek-readable": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.4.2.tgz", + "integrity": "sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/pgp-utils": { + "version": "0.0.35", + "resolved": "https://registry.npmjs.org/pgp-utils/-/pgp-utils-0.0.35.tgz", + "integrity": "sha512-gCT6EbSTgljgycVa5qGpfRITaLOLbIKsEVRTdsNRgmLMAJpuJNNdrTn/95r8IWo9rFLlccfmGMJXkG9nVDwmrA==", + "dependencies": { + "iced-error": ">=0.0.8", + "iced-runtime": ">=0.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "license": "MIT", + "optional": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/piscina": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/piscina/-/piscina-4.9.2.tgz", + "integrity": "sha512-Fq0FERJWFEUpB4eSY59wSNwXD4RYqR+nR/WiEVcZW8IWfVBxJJafcgTEZDQo8k3w0sUarJ8RyVbbUF4GQ2LGbQ==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "@napi-rs/nice": "^1.0.1" + } + }, + "node_modules/pixelmatch": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz", + "integrity": "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==", + "license": "ISC", + "dependencies": { + "pngjs": "^6.0.0" + }, + "bin": { + "pixelmatch": "bin/pixelmatch" + } + }, + "node_modules/pixelmatch/node_modules/pngjs": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz", + "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==", + "license": "MIT", + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/plur": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", + "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", + "license": "MIT", + "dependencies": { + "irregular-plurals": "^3.3.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pngjs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", + "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", + "license": "MIT", + "engines": { + "node": ">=14.19.0" + } + }, + "node_modules/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/portscanner": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz", + "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "async": "^2.6.0", + "is-number-like": "^1.0.3" + }, + "engines": { + "node": ">=0.4", + "npm": ">=1.0.0" + } + }, + "node_modules/portscanner/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-css-variables": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/postcss-css-variables/-/postcss-css-variables-0.19.0.tgz", + "integrity": "sha512-Hr0WEYKLK9VCrY15anHXOd4RCvJy/xRvCnWdplGBeLInwEj6Z14hgzTb2W/39dYTCnS8hnHUfU4/F1zxX0IZuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "escape-string-regexp": "^1.0.3", + "extend": "^3.0.1" + }, + "peerDependencies": { + "postcss": "^8.2.6" + } + }, + "node_modules/postcss-import": { + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.1.tgz", + "integrity": "sha512-2xVS1NCZAfjtVdvXiyegxzJ447GyqCeEI5V7ApgQVOWnros1p5lGNovJNapwPpMombyFBfqDwt7AD3n2l0KOfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-loader": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-8.2.1.tgz", + "integrity": "sha512-k98jtRzthjj3f76MYTs9JTpRqV1RaaMhEU0Lpw9OTmQZQdppg4B30VZ74BojuBHt3F4KyubHJoXCMUeM8Bqeow==", + "dev": true, + "license": "MIT", + "dependencies": { + "cosmiconfig": "^9.0.0", + "jiti": "^2.5.1", + "semver": "^7.6.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/postcss-loader/node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz", + "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz", + "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==", + "dev": true, + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", + "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pretty-bytes": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", + "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", + "license": "MIT", + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha512-UdA8mJ4weIkUBO224tIarHzuHs4HuYiJvsuGT7j/SPQiUJVjYvNDBIPa0hAorduOfjGohB/qHWRa/lrrWX/mXw==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/prompt": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", + "integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@colors/colors": "1.5.0", + "async": "3.2.3", + "read": "1.0.x", + "revalidator": "0.1.x", + "winston": "2.x" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/prompt/node_modules/async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "license": "ISC", + "optional": true + }, + "node_modules/protobufjs": { + "version": "7.5.7", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.7.tgz", + "integrity": "sha512-NGnrxS/nLKUo5nkbVQxlC71sB4hdfImdYIbFeSCidxtwATx0AHRPcANSLd0q5Bb2BkoSWo2iisQhGg5/r+ihbA==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.5", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.1", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.1", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-agent": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz", + "integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.6", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.1.0", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "dev": true, + "license": "MIT" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "license": "ISC", + "optional": true + }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.3.tgz", + "integrity": "sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/purepack": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/purepack/-/purepack-1.0.6.tgz", + "integrity": "sha512-L/e3qq/3m/TrYtINo2aBB98oz6w8VHGyFy+arSKwPMZDUNNw2OaQxYnZO6UIZZw2OnRl2qkxGmuSOEfsuHXJdA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/qr-image": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/qr-image/-/qr-image-3.2.0.tgz", + "integrity": "sha512-rXKDS5Sx3YipVsqmlMJsJsk6jXylEpiHRC2+nJy66fxA5ExYyGa4PqwteW69SaVmAb2OQ18HbYriT7cGQMbduw==", + "license": "MIT" + }, + "node_modules/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "license": "MIT", + "optional": true, + "dependencies": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "license": "MIT", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-1.1.7.tgz", + "integrity": "sha512-WmJJU2e9Y6M5UzTOkHaM7xJGAPQD8PNzx3bAd2+uhZAim6wDk6dAZxPVYLF67XhbR4hmKGh33Lpmh4XWrCH5Mg==", + "deprecated": "No longer maintained. Please upgrade to a stable version.", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "1", + "string_decoder": "0.10" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/raw-body/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz", + "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", + "license": "Apache-2.0" + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "license": "MIT" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.1.tgz", + "integrity": "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", + "license": "ISC" + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/renderkid/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dev": true, + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/renderkid/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/renderkid/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha512-AFBWBy9EVRTa/LhEcG8QDP3FvpwZqmvN2QFDuJswFeaVhWnZMp8q3E6Zd90SR04PlIwfGdyVjNyLPyen/ek5CQ==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/replace-homedir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-2.0.0.tgz", + "integrity": "sha512-bgEuQQ/BHW0XkkJtawzrfzHFSN70f/3cNOiHa2QsYxqrjaC30X1k74FJ6xswVBP0sr0SpGIdVFuPwfrYziVeyw==", + "license": "MIT", + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/reserved-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/reserved-identifiers/-/reserved-identifiers-1.2.0.tgz", + "integrity": "sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", + "license": "MIT", + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-options": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-2.0.0.tgz", + "integrity": "sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==", + "license": "MIT", + "dependencies": { + "value-or-function": "^4.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/revalidator": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", + "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==", + "dev": true, + "license": "Apache 2.0", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "devOptional": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ripemd160": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.3.tgz", + "integrity": "sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==", + "license": "MIT", + "dependencies": { + "hash-base": "^3.1.2", + "inherits": "^2.0.4" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/ripemd160/node_modules/hash-base": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.2.tgz", + "integrity": "sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rison": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/rison/-/rison-0.1.1.tgz", + "integrity": "sha512-8C+/PKKTaAYE2quDtOUwny/eQpNn9YGby7T80wntbVWSGvw0aUT9M0YgLdLkUgIQzQwaB1ZTr80rwLVKyohHig==", + "license": "Apache-2.0" + }, + "node_modules/robust-predicates": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.3.tgz", + "integrity": "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==", + "license": "Unlicense" + }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==", + "license": "BSD-3-Clause" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-json-parse": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-json-parse/-/safe-json-parse-1.0.1.tgz", + "integrity": "sha512-o0JmTu17WGUaUOHa1l0FPGXKBfijbxK6qoHzlkihsDXxzBHvJcA7zgviKR92Xs841rX9pK16unfphLq0/KqX7A==", + "dev": true + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/scryptsy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/scryptsy/-/scryptsy-2.1.0.tgz", + "integrity": "sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==", + "license": "MIT" + }, + "node_modules/seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "commander": "^2.8.1" + }, + "bin": { + "seek-bunzip": "bin/seek-bunzip", + "seek-table": "bin/seek-bzip-table" + } + }, + "node_modules/seek-bzip/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT", + "optional": true + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "dev": true, + "license": "MIT" + }, + "node_modules/selenium-webdriver": { + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.27.0.tgz", + "integrity": "sha512-LkTJrNz5socxpPnWPODQ2bQ65eYx9JK+DQMYNihpTjMCqHwgWGYQnQTCAAche2W3ZP87alA+1zYPvgS8tHNzMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/SeleniumHQ" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/selenium" + } + ], + "license": "Apache-2.0", + "dependencies": { + "@bazel/runfiles": "^6.3.1", + "jszip": "^3.10.1", + "tmp": "^0.2.3", + "ws": "^8.18.0" + }, + "engines": { + "node": ">= 14.21.0" + } + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-greatest-satisfied-range": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-2.0.0.tgz", + "integrity": "sha512-lH3f6kMbwyANB7HuOWRMlLCa2itaCrZJ+SAqqkSZrZKO/cAsk2EOyaKHUtNkVLFyFW9pct22SFesFp3Z7zpA0g==", + "license": "MIT", + "dependencies": { + "sver": "^1.8.3" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/semver-truncate": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz", + "integrity": "sha512-V1fGg9i4CL3qesB6U0L6XAm4xOJiHmt4QAacazumuasc03BvtFGIMCduv01JWQ69Nv+JST9TqhSCiJoxoY031w==", + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^5.3.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/semver-truncate/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-index": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.2.tgz", + "integrity": "sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.8.0", + "mime-types": "~2.1.35", + "parseurl": "~1.3.3" + }, + "engines": { + "node": ">= 0.8.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/sha.js": { + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" + }, + "bin": { + "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shelljs": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.5.3.tgz", + "integrity": "sha512-C2FisSSW8S6TIYHHiMHN0NqzdjWfTekdMpA2FJTbRWnQMLO1RRIXEB9eVZYOlofYmjZA7fY3ChoFu09MeI3wlQ==", + "dev": true, + "license": "BSD*", + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/simple-xml-to-json": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/simple-xml-to-json/-/simple-xml-to-json-1.2.7.tgz", + "integrity": "sha512-mz9VXphOxQWX3eQ/uXCtm6upltoN0DLx8Zb5T4TFC4FHB7S9FDPGre8CfLWqPWQQH/GrQYd2AXhhVM5LDpYx6Q==", + "license": "MIT", + "engines": { + "node": ">=20.12.2" + } + }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sitemap": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-8.0.3.tgz", + "integrity": "sha512-9Ew1tR2WYw8RGE2XLy7GjkusvYXy8Rg6y8TYuBuQMfIEdGcWoJpY2Wr5DzsEiL/TKCw56+YKTCCUHglorEYK+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.4.1" + }, + "bin": { + "sitemap": "dist/cli.js" + }, + "engines": { + "node": ">=14.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/sitemap/node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/slashes": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz", + "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==", + "dev": true, + "license": "ISC" + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/snackbarjs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/snackbarjs/-/snackbarjs-1.1.0.tgz", + "integrity": "sha512-WIMYor1cy6Q2r1GdfvKG4F+Rg9VpQM5/DiemAQFMlVEpnPA7HSk7dBoYam195+y3rMfzhg87v7SW5J0QGoMj2g==", + "license": "ISC" + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sockjs/node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/socks": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.9.tgz", + "integrity": "sha512-LJhUYUvItdQ0LkJTmPeaEObWXAqFyfmP85x0tch/ez9cahmhlBBLbIqDFnvBnUJGagb0JbIQrkBs1wJ+yRYpEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^10.1.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==", + "license": "MIT", + "optional": true, + "dependencies": { + "sort-keys": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sortablejs": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.7.tgz", + "integrity": "sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==", + "license": "MIT" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sparkles": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-2.1.0.tgz", + "integrity": "sha512-r7iW1bDw8R/cFifrD3JnQJX0K1jqT0kprL48BiBpLZLJPmAm34zsVBsK5lc7HirZYZqMW65dOXZgbAGt/I6frg==", + "license": "MIT", + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/split.js": { + "version": "1.6.5", + "resolved": "https://registry.npmjs.org/split.js/-/split.js-1.6.5.tgz", + "integrity": "sha512-mPTnGCiS/RiuTNsVhCm9De9cCAUsrNFFviRbADdKiiV+Kk8HKp/0fWu7Kr8pi3/yBmsqLFHuXGT9UUZ+CNLwFw==", + "license": "MIT" + }, + "node_modules/split2": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/split2/-/split2-2.2.0.tgz", + "integrity": "sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==", + "dev": true, + "license": "ISC", + "dependencies": { + "through2": "^2.0.2" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/ssdeep.js": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/ssdeep.js/-/ssdeep.js-0.0.3.tgz", + "integrity": "sha512-QXKADMuEsOmRYGlB9JvrulcF5NLAjAvYLg3qDHUrEEilUFLKoL4fUQDw1s7hF+mOL96jwcdyXpnmCqyNu7Wm3Q==" + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", + "license": "MIT", + "optional": true + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/stacktrace-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", + "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stacktrace-parser/node_modules/type-fest": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", + "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-browserify/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/stream-composer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-composer/-/stream-composer-1.0.2.tgz", + "integrity": "sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==", + "license": "MIT", + "dependencies": { + "streamx": "^2.13.2" + } + }, + "node_modules/stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", + "license": "MIT" + }, + "node_modules/stream-shift": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz", + "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/streamx": { + "version": "2.25.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.25.0.tgz", + "integrity": "sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==", + "license": "MIT", + "dependencies": { + "events-universal": "^1.0.0", + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + } + }, + "node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/string-template": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-template/-/string-template-0.2.1.tgz", + "integrity": "sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-natural-number": "^4.0.1" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/strtok3": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-9.1.1.tgz", + "integrity": "sha512-FhwotcEqjr241ZbjFzjlIYg6c5/L/s4yBGWSMvJ9UoExiSqL+FnFA/CaeZx17WGaZMS/4SOZp8wH18jSS4R4lw==", + "license": "MIT", + "dependencies": { + "@tokenizer/token": "^0.3.0", + "peek-readable": "^5.3.1" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/style-mod": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", + "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/super-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/super-regex/-/super-regex-1.1.0.tgz", + "integrity": "sha512-WHkws2ZflZe41zj6AolvvmaTrWds/VuyeYr9iPVv/oQeaIoVxMKaushfFWpOGDT+GuBrM/sVqF8KUCYQlSSTdQ==", + "license": "MIT", + "dependencies": { + "function-timeout": "^1.0.1", + "make-asynchronous": "^1.0.1", + "time-span": "^5.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sver": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/sver/-/sver-1.8.4.tgz", + "integrity": "sha512-71o1zfzyawLfIWBOmw8brleKyvnbn73oVHNCsu51uPMz/HWiKkkXsI31JjHW5zqXEqnPYkIiHd8ZmL7FCimLEA==", + "license": "MIT", + "optionalDependencies": { + "semver": "^6.3.0" + } + }, + "node_modules/svgo": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.2.tgz", + "integrity": "sha512-TyzE4NVGLUFy+H/Uy4N6c3G0HEeprsVfge6Lmq+0FdQQ/zqoVYB62IsBZORsiL+o96s6ff/V6/3UQo/C0cgCAA==", + "license": "MIT", + "optional": true, + "dependencies": { + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "sax": "^1.5.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/synckit": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.3.tgz", + "integrity": "sha512-JJoOEKTfL1urb1mDoEblhD9NhEbWmq9jHEMEnxoC4ujUaZ4itA8vKgwkFAyNClgxplLi9tsUKX+EduK0p/l7sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "license": "MIT", + "optional": true, + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/tar-stream/node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "license": "MIT", + "optional": true, + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/tcp-port-used": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-1.0.2.tgz", + "integrity": "sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4.3.1", + "is2": "^2.0.6" + } + }, + "node_modules/tcp-port-used/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/tcp-port-used/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/teex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz", + "integrity": "sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==", + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + } + }, + "node_modules/temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tempfile": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", + "integrity": "sha512-ZOn6nJUgvgC09+doCEF3oB+r3ag7kUvlsXEGX069QRD60p+P3uP7XG9N2/at+EyIRGSN//ZY3LyEotA1YpmjuA==", + "license": "MIT", + "optional": true, + "dependencies": { + "temp-dir": "^1.0.0", + "uuid": "^3.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tempfile/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "license": "MIT", + "optional": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/terser": { + "version": "5.47.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.47.1.tgz", + "integrity": "sha512-tPbLXTI6ohPASb/1YViL428oEHu6/qv1OxqYnfaonVCFHqx4+wCd95pHrQWsL5X4pl90CTyW9piSAsS2L0VoMw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-Eum+5ajkaOhf5KbM26osvv21kLD7BaGqQ1UA4Ami4arYwylmGUQTgHFpHDdmJod1q4QXa66p0to/FBKID+J1vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/tesseract.js": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-5.1.1.tgz", + "integrity": "sha512-lzVl/Ar3P3zhpUT31NjqeCo1f+D5+YfpZ5J62eo2S14QNVOmHBTtbchHm/YAbOOOzCegFnKf4B3Qih9LuldcYQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "bmp-js": "^0.1.0", + "idb-keyval": "^6.2.0", + "is-electron": "^2.2.2", + "is-url": "^1.2.4", + "node-fetch": "^2.6.9", + "opencollective-postinstall": "^2.0.3", + "regenerator-runtime": "^0.13.3", + "tesseract.js-core": "^5.1.1", + "wasm-feature-detect": "^1.2.11", + "zlibjs": "^0.3.1" + } + }, + "node_modules/tesseract.js-core": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-5.1.1.tgz", + "integrity": "sha512-KX3bYSU5iGcO1XJa+QGPbi+Zjo2qq6eBhNjSGR5E5q0JtzkoipJKOUQD7ph8kFyteCEfEQ0maWLu8MCXtvX5uQ==", + "license": "Apache-2.0" + }, + "node_modules/text-decoder": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.7.tgz", + "integrity": "sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/text-hex": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-0.0.0.tgz", + "integrity": "sha512-RpZDSt2VIQnsPVDiOySPfi/RTRBbPyJj2fikmH5O2H5Zc/MC6ZPVcc4GYGcnbTS/j2v1HZOmy6F4CimfiLPMRg==", + "license": "MIT" + }, + "node_modules/thingies": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/thingies/-/thingies-2.6.0.tgz", + "integrity": "sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "^2" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "license": "MIT", + "optional": true + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true, + "license": "MIT" + }, + "node_modules/time-span": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/time-span/-/time-span-5.1.0.tgz", + "integrity": "sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==", + "license": "MIT", + "dependencies": { + "convert-hrtime": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/timers-ext": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.8.tgz", + "integrity": "sha512-wFH7+SEAcKfJpfLPkrgMPvvwnEtj8W4IurvEyrKsDleXnKLCDw71w8jltvfLa8Rm4qQxxT4jmDBYbJG/z7qoww==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/tiny-lr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-1.1.1.tgz", + "integrity": "sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "body": "^5.1.0", + "debug": "^3.1.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.3.0", + "object-assign": "^4.1.0", + "qs": "^6.4.0" + } + }, + "node_modules/tiny-lr/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "license": "MIT", + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/to-buffer/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/to-through": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-3.0.0.tgz", + "integrity": "sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==", + "license": "MIT", + "dependencies": { + "streamx": "^2.12.5" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/toastr": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/toastr/-/toastr-2.1.4.tgz", + "integrity": "sha512-LIy77F5n+sz4tefMmFOntcJ6HL0Fv3k1TDnNmFZ0bU/GcvIIfy6eG2v7zQmMiYgaalAiUv75ttFrPn5s0gyqlA==", + "dependencies": { + "jquery": ">=1.12.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/token-types": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.2.tgz", + "integrity": "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==", + "license": "MIT", + "dependencies": { + "@borewit/text-codec": "^0.2.1", + "@tokenizer/token": "^0.3.0", + "ieee754": "^1.2.1" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Borewit" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tree-dump": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.1.0.tgz", + "integrity": "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/streamich" + }, + "peerDependencies": { + "tslib": "2" + } + }, + "node_modules/trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/triplesec": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/triplesec/-/triplesec-4.0.3.tgz", + "integrity": "sha512-fug70e1nJoCMxsXQJlETisAALohm84vl++IiTTHEqM7Lgqwz62jrlwqOC/gJEAJjO/ByN127sEcioB56HW3wIw==", + "dependencies": { + "iced-error": ">=0.0.9", + "iced-lock": "^1.0.1", + "iced-runtime": "^1.0.2", + "more-entropy": ">=0.0.7", + "progress": "~1.1.2", + "uglify-js": "^3.1.9" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz", + "integrity": "sha512-iNWodk4oBsZ03Qfw/Yvv0KB90uYrJqvL4Je7Gy4C5t/GS3sCXPRmIT1lxmId4RzvUp0XG62bcxJ2CBu/3L5DSg==", + "license": "Public domain" + }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", + "license": "ISC" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ua-parser-js": { + "version": "1.0.41", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.41.tgz", + "integrity": "sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "license": "MIT", + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, + "node_modules/uglify-js": { + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", + "license": "BSD-2-Clause", + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uint64be": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uint64be/-/uint64be-1.0.1.tgz", + "integrity": "sha512-w+VZSp8hSZ/xWZfZNMppWNF6iqY+dcMYtG5CpwRDgxi94HIE6ematSdkzHGzVC4SDEaTsG65zrajN+oKoWG6ew==", + "license": "MIT" + }, + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/unbzip2-stream/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/underscore.string": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.6.tgz", + "integrity": "sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "^1.1.1", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/undertaker": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-2.0.0.tgz", + "integrity": "sha512-tO/bf30wBbTsJ7go80j0RzA2rcwX6o7XPBpeFcb+jzoeb4pfMM2zUeSDIkY1AWqeZabWxaQZ/h8N9t35QKDLPQ==", + "license": "MIT", + "dependencies": { + "bach": "^2.0.1", + "fast-levenshtein": "^3.0.0", + "last-run": "^2.0.0", + "undertaker-registry": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/undertaker-registry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-2.0.0.tgz", + "integrity": "sha512-+hhVICbnp+rlzZMgxXenpvTxpuvA67Bfgtt+O9WOE5jo7w/dyiF1VmoZVIHvP2EkUjsyKyTwYKlLhA+j47m1Ew==", + "license": "MIT", + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/undertaker/node_modules/fast-levenshtein": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-3.0.0.tgz", + "integrity": "sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==", + "license": "MIT", + "dependencies": { + "fastest-levenshtein": "^1.0.7" + } + }, + "node_modules/undici-types": { + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", + "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/universalify": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unorm": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/unorm/-/unorm-1.6.0.tgz", + "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", + "license": "MIT or GPL-2.0", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/untildify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", + "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "license": "MIT", + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==", + "license": "MIT", + "optional": true, + "dependencies": { + "prepend-http": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha512-0kQLIzG4fdk/G5NONku64rSH/x32NOA39LVQqlK8Le6lvTF6GGRJpqaQFGgU+CLwySIqBSMdwYM0sYcW9f6P4A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "license": "MIT" + }, + "node_modules/urlsafe-base64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/urlsafe-base64/-/urlsafe-base64-1.0.0.tgz", + "integrity": "sha512-RtuPeMy7c1UrHwproMZN9gN6kiZ0SvJwRaEzwZY0j9MypEkFqyBaKv176jvlPtg58Zh36bOkS0NFABXMHvvGCA==" + }, + "node_modules/utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", + "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "license": "MIT" + }, + "node_modules/utif2": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz", + "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==", + "license": "MIT", + "dependencies": { + "pako": "^1.0.11" + } + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.2.tgz", + "integrity": "sha512-vzi9uRZ926x4XV73S/4qQaTwPXM2JBj6/6lI/byHH1jOpCzb0zDbfytgA9LcN/hzb2l7WQSQnxITOVx5un/wGw==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/v8flags": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-4.0.1.tgz", + "integrity": "sha512-fcRLaS4H/hrZk9hYwbdRM35D0U8IYMfEClhXxCivOojl+yTRAZH3Zy2sSy6qVCiGbV9YAtPssP6jaChqC9vPCg==", + "license": "MIT", + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/value-or-function": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz", + "integrity": "sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==", + "license": "MIT", + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vinyl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.1.tgz", + "integrity": "sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==", + "license": "MIT", + "dependencies": { + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vinyl-bufferstream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz", + "integrity": "sha512-yCCIoTf26Q9SQ0L9cDSavSL7Nt6wgQw8TU1B/bb9b9Z4A3XTypXCGdc5BvXl4ObQvVY8JrDkFnWa/UqBqwM2IA==", + "dependencies": { + "bufferstreams": "1.0.1" + } + }, + "node_modules/vinyl-contents": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-contents/-/vinyl-contents-2.0.0.tgz", + "integrity": "sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==", + "license": "MIT", + "dependencies": { + "bl": "^5.0.0", + "vinyl": "^3.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-contents/node_modules/bl": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", + "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/vinyl-contents/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/vinyl-contents/node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/vinyl-contents/node_modules/vinyl": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", + "license": "MIT", + "dependencies": { + "clone": "^2.1.2", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-fs": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-4.0.2.tgz", + "integrity": "sha512-XRFwBLLTl8lRAOYiBqxY279wY46tVxLaRhSwo3GzKEuLz1giffsOquWWboD/haGf5lx+JyTigCFfe7DWHoARIA==", + "license": "MIT", + "dependencies": { + "fs-mkdirp-stream": "^2.0.1", + "glob-stream": "^8.0.3", + "graceful-fs": "^4.2.11", + "iconv-lite": "^0.6.3", + "is-valid-glob": "^1.0.0", + "lead": "^4.0.0", + "normalize-path": "3.0.0", + "resolve-options": "^2.0.0", + "stream-composer": "^1.0.2", + "streamx": "^2.14.0", + "to-through": "^3.0.0", + "value-or-function": "^4.0.0", + "vinyl": "^3.0.1", + "vinyl-sourcemap": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-fs/node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/vinyl-fs/node_modules/vinyl": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", + "license": "MIT", + "dependencies": { + "clone": "^2.1.2", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-sourcemap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-2.0.0.tgz", + "integrity": "sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==", + "license": "MIT", + "dependencies": { + "convert-source-map": "^2.0.0", + "graceful-fs": "^4.2.10", + "now-and-later": "^3.0.0", + "streamx": "^2.12.5", + "vinyl": "^3.0.0", + "vinyl-contents": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-sourcemap/node_modules/replace-ext": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-2.0.0.tgz", + "integrity": "sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/vinyl-sourcemap/node_modules/vinyl": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-3.0.1.tgz", + "integrity": "sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==", + "license": "MIT", + "dependencies": { + "clone": "^2.1.2", + "remove-trailing-separator": "^1.1.0", + "replace-ext": "^2.0.0", + "teex": "^1.0.1" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha512-+oDh3KYZBoZC8hfocrbrxbLUeaYtQK7J5WU5Br9VqWqmCll3tFJqKp97GC9GmMsVIL0qnx2DgEDVxdo5EZ5sSw==", + "license": "ISC", + "dependencies": { + "source-map": "^0.5.1" + } + }, + "node_modules/vinyl-sourcemaps-apply/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vinyl/node_modules/replace-ext": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz", + "integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vkbeautify": { + "version": "0.99.3", + "resolved": "https://registry.npmjs.org/vkbeautify/-/vkbeautify-0.99.3.tgz", + "integrity": "sha512-2ozZEFfmVvQcHWoHLNuiKlUfDKlhh4KGsy54U0UrlLMR1SO+XKAIDqBxtBwHgNrekurlJwE8A9K6L49T78ZQ9Q==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/wasm-feature-detect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz", + "integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==", + "license": "Apache-2.0" + }, + "node_modules/watchpack": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-worker": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.5.0.tgz", + "integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==", + "license": "Apache-2.0" + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/webpack": { + "version": "5.106.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.106.2.tgz", + "integrity": "sha512-wGN3qcrBQIFmQ/c0AiOAQBvrZ5lmY8vbbMv4Mxfgzqd/B6+9pXtLo73WuS1dSGXM5QYY3hZnIbvx+K1xxe6FyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.16.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.20.0", + "es-module-lexer": "^2.0.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "loader-runner": "^4.3.1", + "mime-db": "^1.54.0", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.17", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.4" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", + "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware": { + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.5.tgz", + "integrity": "sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^4.43.1", + "mime-types": "^3.0.1", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + } + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/webpack-dev-middleware/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webpack-dev-server": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.0.4.tgz", + "integrity": "sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/bonjour": "^3.5.13", + "@types/connect-history-api-fallback": "^1.5.4", + "@types/express": "^4.17.21", + "@types/serve-index": "^1.9.4", + "@types/serve-static": "^1.15.5", + "@types/sockjs": "^0.3.36", + "@types/ws": "^8.5.10", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.2.1", + "chokidar": "^3.6.0", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.4.0", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.1.0", + "launch-editor": "^2.6.1", + "open": "^10.0.3", + "p-retry": "^6.2.0", + "rimraf": "^5.0.5", + "schema-utils": "^4.2.0", + "selfsigned": "^2.4.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^7.1.0", + "ws": "^8.16.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/webpack-dev-server/node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/webpack-dev-server/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/webpack-dev-server/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/webpack-dev-server/node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/webpack-dev-server/node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/webpack-node-externals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", + "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-sources": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.1.tgz", + "integrity": "sha512-eACpxRN02yaawnt+uUNIF7Qje6A9zArxBbcAJjK1PK3S9Ycg5jIuJ8pW4q8EMnwNZCEGltcjkRx1QzOxOkKD8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz", + "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/winston": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", + "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "async": "^2.6.4", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "stack-trace": "0.0.x" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/winston/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/winston/node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "license": "MIT" + }, + "node_modules/worker-loader": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/worker-loader/-/worker-loader-3.0.8.tgz", + "integrity": "sha512-XQyQkIFeRVC7f7uRhFdNMe/iJOdO6zxAaR3EWbDp45v3mDhrTi+++oswKNxShUNjPC/1xUp5DB29YKLhFo129g==", + "dev": true, + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/worker-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/workerpool": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz", + "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wsl-utils/node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xml-parse-from-string": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz", + "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==", + "license": "MIT" + }, + "node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/xpath": { + "version": "0.0.34", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.34.tgz", + "integrity": "sha512-FxF6+rkr1rNSQrhUNYrAFJpRXNzlDoMxeXN5qI84939ylEv3qqPFKa85Oxr6tDaJKqwW6KKyo2v26TSv3k6LeA==", + "license": "MIT", + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/xregexp": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-5.1.2.tgz", + "integrity": "sha512-6hGgEMCGhqCTFEJbqmWrNIPqfpdirdGWkqshu7fFZddmTSfgv5Sn9D2SaKloR79s5VUiUlpwzg3CM3G6D3VIlw==", + "license": "MIT", + "dependencies": { + "@babel/runtime-corejs3": "^7.26.9" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.4.tgz", + "integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/yargs-unparser/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zip-stream": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/archiver-utils": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/zip-stream/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/zlibjs": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/zlibjs/-/zlibjs-0.3.1.tgz", + "integrity": "sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + } +} diff --git a/plugins/srktoolbox/package.json b/plugins/srktoolbox/package.json new file mode 100644 index 00000000..f153e8d7 --- /dev/null +++ b/plugins/srktoolbox/package.json @@ -0,0 +1,215 @@ +{ + "name": "srktoolbox", + "version": "10.22.1", + "description": "SRK Toolbox - a web app (based on CyberChef) for encryption, encoding, compression and data analysis, translated to Chinese locale", + "author": "Raka-loah&&LAOBILAXI233", + "homepage": "https://github.com/Raka-loah/SRK-Toolbox", + "copyright": "Crown copyright 2016 / Zack Zhou copyright 2026", + "license": "Apache-2.0", + "keywords": [ + "cipher", + "cypher", + "encode", + "decode", + "encrypt", + "decrypt", + "base64", + "xor", + "charset", + "hex", + "encoding", + "format", + "cybersecurity", + "data manipulation", + "data analysis" + ], + "repository": { + "type": "git", + "url": "https://github.com/Raka-loah/SRK-Toolbox" + }, + "main": "src/node/wrapper.js", + "exports": { + "import": "./src/node/index.mjs", + "require": "./src/node/wrapper.js" + }, + "bugs": "https://github.com/Raka-loah/SRK-Toolbox/issues", + "browserslist": [ + "Chrome >= 50", + "Firefox >= 38", + "node >= 16" + ], + "devDependencies": { + "@babel/core": "^7.29.0", + "@babel/eslint-parser": "^7.28.6", + "@babel/plugin-syntax-import-assertions": "^7.28.6", + "@babel/plugin-transform-runtime": "^7.29.0", + "@babel/preset-env": "^7.29.0", + "@babel/runtime": "^7.28.6", + "@codemirror/commands": "^6.10.2", + "@codemirror/language": "^6.12.1", + "@codemirror/search": "^6.6.0", + "@codemirror/state": "^6.5.4", + "@codemirror/view": "^6.39.15", + "autoprefixer": "^10.4.24", + "babel-loader": "^10.0.0", + "babel-plugin-dynamic-import-node": "^2.3.3", + "babel-plugin-transform-builtin-extend": "1.1.2", + "base64-loader": "^1.0.0", + "chromedriver": "^143.0.4", + "cli-progress": "^3.12.0", + "colors": "^1.4.0", + "compression-webpack-plugin": "^11.1.0", + "copy-webpack-plugin": "^13.0.1", + "core-js": "^3.48.0", + "cspell": "^8.19.4", + "css-loader": "7.1.4", + "eslint": "^9.39.3", + "eslint-plugin-jsdoc": "^48.11.0", + "globals": "^15.15.0", + "grunt": "^1.6.1", + "grunt-chmod": "~1.1.1", + "grunt-concurrent": "^3.0.0", + "grunt-contrib-clean": "~2.0.1", + "grunt-contrib-connect": "^5.0.1", + "grunt-contrib-copy": "~1.0.0", + "grunt-contrib-watch": "^1.1.0", + "grunt-eslint": "^25.0.0", + "grunt-exec": "~3.0.0", + "grunt-webpack": "^6.0.0", + "grunt-zip": "^1.0.0", + "html-webpack-plugin": "^5.6.6", + "imports-loader": "^5.0.0", + "mini-css-extract-plugin": "2.10.0", + "modify-source-webpack-plugin": "^4.1.0", + "nightwatch": "^3.15.0", + "postcss": "^8.5.6", + "postcss-css-variables": "^0.19.0", + "postcss-import": "^16.1.1", + "postcss-loader": "^8.2.1", + "prompt": "^1.3.0", + "sitemap": "^8.0.2", + "terser": "^5.46.0", + "webpack": "^5.105.2", + "webpack-bundle-analyzer": "^4.10.2", + "webpack-dev-server": "5.0.4", + "webpack-node-externals": "^3.0.0", + "worker-loader": "^3.0.8" + }, + "dependencies": { + "14": "^3.1.6", + "@astronautlabs/amf": "^0.0.6", + "@babel/polyfill": "^7.12.1", + "@blu3r4y/lzma": "^2.3.3", + "@wavesenterprise/crypto-gost-js": "^2.1.0-RC1", + "@xmldom/xmldom": "^0.8.11", + "argon2-browser": "^1.18.0", + "arrive": "^2.5.2", + "assert": "^2.1.0", + "avsc": "^5.7.9", + "bcryptjs": "^2.4.3", + "bignumber.js": "^9.3.1", + "blakejs": "^1.2.1", + "bootstrap": "4.6.2", + "bootstrap-colorpicker": "^3.4.0", + "bootstrap-material-design": "^4.1.3", + "browserify-zlib": "^0.2.0", + "bson": "^4.7.2", + "buffer": "^6.0.3", + "cbor": "9.0.2", + "chi-squared": "^1.1.0", + "codepage": "^1.15.0", + "crypto-api": "^0.8.5", + "crypto-browserify": "^3.12.1", + "crypto-js": "^4.2.0", + "ctph.js": "0.0.5", + "d3": "7.9.0", + "d3-hexbin": "^0.2.2", + "diff": "^5.2.2", + "dompurify": "^3.3.1", + "es6-promisify": "^7.0.0", + "escodegen": "^2.1.0", + "esprima": "^4.0.1", + "events": "^3.3.0", + "exif-parser": "^0.1.12", + "fernet": "^0.3.3", + "file-saver": "^2.0.5", + "flat": "^6.0.1", + "geodesy": "1.1.3", + "handlebars": "^4.7.8", + "hash-wasm": "^4.12.0", + "highlight.js": "^11.11.1", + "ieee754": "^1.2.1", + "jimp": "^1.6.0", + "jq-web": "^0.6.2", + "jquery": "3.7.1", + "js-sha3": "^0.9.3", + "jsesc": "^3.1.0", + "json5": "^2.2.3", + "jsonata": "^2.1.0", + "jsonpath-plus": "^10.4.0", + "jsonwebtoken": "8.5.1", + "jsqr": "^1.4.0", + "jsrsasign": "^11.1.1", + "kbpgp": "^2.1.17", + "libbzip2-wasm": "0.0.4", + "libyara-wasm": "^1.2.1", + "lodash": "^4.17.23", + "loglevel": "^1.9.2", + "loglevel-message-prefix": "^3.0.0", + "lz-string": "^1.5.0", + "lz4js": "^0.2.0", + "markdown-it": "^14.1.1", + "moment": "^2.30.1", + "moment-timezone": "^0.6.0", + "ngeohash": "^0.6.3", + "node-forge": "^1.3.3", + "node-md6": "^0.1.0", + "nodom": "^2.4.0", + "notepack.io": "^3.0.1", + "ntlm": "^0.1.3", + "nwmatcher": "^1.4.4", + "otpauth": "9.3.6", + "path": "^0.12.7", + "popper.js": "^1.16.1", + "process": "^0.11.10", + "protobufjs": "^7.5.4", + "qr-image": "^3.2.0", + "reflect-metadata": "^0.2.2", + "rison": "^0.1.1", + "scryptsy": "^2.1.0", + "snackbarjs": "^1.1.0", + "sortablejs": "^1.15.7", + "split.js": "^1.6.5", + "ssdeep.js": "0.0.3", + "stream-browserify": "^3.0.0", + "tesseract.js": "5.1.1", + "toastr": "^2.1.4", + "ua-parser-js": "^1.0.41", + "unorm": "^1.6.0", + "url": "^0.11.4", + "utf8": "^3.0.0", + "uuid": "^13.0.0", + "vkbeautify": "^0.99.3", + "xpath": "0.0.34", + "xregexp": "^5.1.2", + "zlibjs": "^0.3.1" + }, + "scripts": { + "start": "npx grunt dev", + "build": "npx grunt prod", + "node": "npx grunt node", + "repl": "node --experimental-modules --experimental-json-modules --experimental-specifier-resolution=node --no-experimental-fetch --no-warnings src/node/repl.mjs", + "test": "npx grunt configTests && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation --openssl-legacy-provider --no-experimental-fetch tests/node/index.mjs && node --experimental-modules --experimental-json-modules --no-warnings --no-deprecation --openssl-legacy-provider --no-experimental-fetch --trace-uncaught tests/operations/index.mjs", + "testnodeconsumer": "npx grunt testnodeconsumer", + "testui": "npx grunt testui", + "testuidev": "npx nightwatch --env=dev", + "lint": "npx grunt lint", + "lint:grammar": "cspell ./src", + "postinstall": "npx grunt exec:fixCryptoApiImports && npx grunt exec:fixSnackbarMarkup", + "newop": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newOperation.mjs", + "minor": "node --experimental-modules --experimental-json-modules src/core/config/scripts/newMinorVersion.mjs && npm version minor --git-tag-version=false && echo \"Updated to version v$(npm pkg get version | xargs), please create a pull request and once merged use 'npm run tag'\"", + "tag": "git tag -s \"v$(npm pkg get version | xargs)\" -m \"$(npm pkg get version | xargs)\" && echo \"Created v$(npm pkg get version | xargs), now check and push the tag\"", + "getheapsize": "node -e 'console.log(`node heap limit = ${require(\"v8\").getHeapStatistics().heap_size_limit / (1024 * 1024)} Mb`)'", + "setheapsize": "export NODE_OPTIONS=--max_old_space_size=2048" + } +} diff --git a/plugins/srktoolbox/plugin.json b/plugins/srktoolbox/plugin.json new file mode 100644 index 00000000..19878db7 --- /dev/null +++ b/plugins/srktoolbox/plugin.json @@ -0,0 +1,31 @@ +{ + "name": "srktoolbox", + "title": "SRK Toolbox for Ztools", + "description": "基于 CyberChef 的中文安全工具箱,支持编码、加密、压缩和数据分析。", + "author": "Raka-loah&&LAOBILAXI233", + "version": "10.22.1", + "main": "index.html", + "logo": "logo.png", + "pluginSetting": { + "height": 900 + }, + "development": { + "main": "http://localhost:54333" + }, + "features": [ + { + "code": "srk-toolbox", + "explain": "打开 SRK Toolbox 工具箱", + "icon": "logo.png", + "cmds": [ + "SRK Toolbox", + "srk", + "toolbox", + "工具箱", + "密码工具", + "编码转换", + "CyberChef" + ] + } + ] +} diff --git a/plugins/srktoolbox/pnpm-lock.yaml b/plugins/srktoolbox/pnpm-lock.yaml new file mode 100644 index 00000000..ec5a0c9c --- /dev/null +++ b/plugins/srktoolbox/pnpm-lock.yaml @@ -0,0 +1,12457 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@astronautlabs/amf': + specifier: ^0.0.6 + version: 0.0.6(reflect-metadata@0.2.2) + '@babel/polyfill': + specifier: ^7.12.1 + version: 7.12.1 + '@blu3r4y/lzma': + specifier: ^2.3.3 + version: 2.3.3 + '@wavesenterprise/crypto-gost-js': + specifier: ^2.1.0-RC1 + version: 2.1.0-RC1 + '@xmldom/xmldom': + specifier: ^0.8.11 + version: 0.8.11 + argon2-browser: + specifier: ^1.18.0 + version: 1.18.0 + arrive: + specifier: ^2.5.2 + version: 2.5.3 + assert: + specifier: ^2.1.0 + version: 2.1.0 + avsc: + specifier: ^5.7.9 + version: 5.7.9 + bcryptjs: + specifier: ^2.4.3 + version: 2.4.3 + bignumber.js: + specifier: ^9.3.1 + version: 9.3.1 + blakejs: + specifier: ^1.2.1 + version: 1.2.1 + bootstrap: + specifier: 4.6.2 + version: 4.6.2(jquery@3.7.1)(popper.js@1.16.1) + bootstrap-colorpicker: + specifier: ^3.4.0 + version: 3.4.0 + bootstrap-material-design: + specifier: ^4.1.3 + version: 4.1.3 + browserify-zlib: + specifier: ^0.2.0 + version: 0.2.0 + bson: + specifier: ^4.7.2 + version: 4.7.2 + buffer: + specifier: ^6.0.3 + version: 6.0.3 + cbor: + specifier: 9.0.2 + version: 9.0.2 + chi-squared: + specifier: ^1.1.0 + version: 1.1.0 + codepage: + specifier: ^1.15.0 + version: 1.15.0 + crypto-api: + specifier: ^0.8.5 + version: 0.8.5 + crypto-browserify: + specifier: ^3.12.1 + version: 3.12.1 + crypto-js: + specifier: ^4.2.0 + version: 4.2.0 + ctph.js: + specifier: 0.0.5 + version: 0.0.5 + d3: + specifier: 7.9.0 + version: 7.9.0 + d3-hexbin: + specifier: ^0.2.2 + version: 0.2.2 + diff: + specifier: ^5.2.2 + version: 5.2.2 + dompurify: + specifier: ^3.3.1 + version: 3.3.3 + es6-promisify: + specifier: ^7.0.0 + version: 7.0.0 + escodegen: + specifier: ^2.1.0 + version: 2.1.0 + esprima: + specifier: ^4.0.1 + version: 4.0.1 + events: + specifier: ^3.3.0 + version: 3.3.0 + exif-parser: + specifier: ^0.1.12 + version: 0.1.12 + fernet: + specifier: ^0.3.3 + version: 0.3.3 + file-saver: + specifier: ^2.0.5 + version: 2.0.5 + flat: + specifier: ^6.0.1 + version: 6.0.1 + geodesy: + specifier: 1.1.3 + version: 1.1.3 + handlebars: + specifier: ^4.7.8 + version: 4.7.9 + hash-wasm: + specifier: ^4.12.0 + version: 4.12.0 + highlight.js: + specifier: ^11.11.1 + version: 11.11.1 + ieee754: + specifier: ^1.2.1 + version: 1.2.1 + jimp: + specifier: ^1.6.0 + version: 1.6.0 + jq-web: + specifier: ^0.6.2 + version: 0.6.2 + jquery: + specifier: 3.7.1 + version: 3.7.1 + js-sha3: + specifier: ^0.9.3 + version: 0.9.3 + jsesc: + specifier: ^3.1.0 + version: 3.1.0 + json5: + specifier: ^2.2.3 + version: 2.2.3 + jsonata: + specifier: ^2.1.0 + version: 2.1.0 + jsonpath-plus: + specifier: ^10.4.0 + version: 10.4.0 + jsonwebtoken: + specifier: 8.5.1 + version: 8.5.1 + jsqr: + specifier: ^1.4.0 + version: 1.4.0 + jsrsasign: + specifier: ^11.1.1 + version: 11.1.1 + kbpgp: + specifier: ^2.1.17 + version: 2.1.17 + libbzip2-wasm: + specifier: 0.0.4 + version: 0.0.4 + libyara-wasm: + specifier: ^1.2.1 + version: 1.2.1 + lodash: + specifier: ^4.17.23 + version: 4.17.23 + loglevel: + specifier: ^1.9.2 + version: 1.9.2 + loglevel-message-prefix: + specifier: ^3.0.0 + version: 3.0.0 + lz-string: + specifier: ^1.5.0 + version: 1.5.0 + lz4js: + specifier: ^0.2.0 + version: 0.2.0 + markdown-it: + specifier: ^14.1.1 + version: 14.1.1 + moment: + specifier: ^2.30.1 + version: 2.30.1 + moment-timezone: + specifier: ^0.6.0 + version: 0.6.1 + ngeohash: + specifier: ^0.6.3 + version: 0.6.3 + node-forge: + specifier: ^1.3.3 + version: 1.4.0 + node-md6: + specifier: ^0.1.0 + version: 0.1.0 + nodom: + specifier: ^2.4.0 + version: 2.4.0 + notepack.io: + specifier: ^3.0.1 + version: 3.0.1 + ntlm: + specifier: ^0.1.3 + version: 0.1.3 + nwmatcher: + specifier: ^1.4.4 + version: 1.4.4 + otpauth: + specifier: 9.3.6 + version: 9.3.6 + path: + specifier: ^0.12.7 + version: 0.12.7 + popper.js: + specifier: ^1.16.1 + version: 1.16.1 + process: + specifier: ^0.11.10 + version: 0.11.10 + protobufjs: + specifier: ^7.5.4 + version: 7.5.4 + qr-image: + specifier: ^3.2.0 + version: 3.2.0 + reflect-metadata: + specifier: ^0.2.2 + version: 0.2.2 + rison: + specifier: ^0.1.1 + version: 0.1.1 + scryptsy: + specifier: ^2.1.0 + version: 2.1.0 + snackbarjs: + specifier: ^1.1.0 + version: 1.1.0 + sortablejs: + specifier: ^1.15.7 + version: 1.15.7 + split.js: + specifier: ^1.6.5 + version: 1.6.5 + ssdeep.js: + specifier: 0.0.3 + version: 0.0.3 + stream-browserify: + specifier: ^3.0.0 + version: 3.0.0 + tesseract.js: + specifier: 5.1.1 + version: 5.1.1 + toastr: + specifier: ^2.1.4 + version: 2.1.4 + ua-parser-js: + specifier: ^1.0.41 + version: 1.0.41 + unorm: + specifier: ^1.6.0 + version: 1.6.0 + url: + specifier: ^0.11.4 + version: 0.11.4 + utf8: + specifier: ^3.0.0 + version: 3.0.0 + uuid: + specifier: ^13.0.0 + version: 13.0.0 + vkbeautify: + specifier: ^0.99.3 + version: 0.99.3 + xpath: + specifier: 0.0.34 + version: 0.0.34 + xregexp: + specifier: ^5.1.2 + version: 5.1.2 + zlibjs: + specifier: ^0.3.1 + version: 0.3.1 + devDependencies: + '@babel/core': + specifier: ^7.29.0 + version: 7.29.0 + '@babel/eslint-parser': + specifier: ^7.28.6 + version: 7.28.6(@babel/core@7.29.0)(eslint@9.39.4(jiti@2.6.1)) + '@babel/plugin-syntax-import-assertions': + specifier: ^7.28.6 + version: 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-runtime': + specifier: ^7.29.0 + version: 7.29.0(@babel/core@7.29.0) + '@babel/preset-env': + specifier: ^7.29.0 + version: 7.29.2(@babel/core@7.29.0) + '@babel/runtime': + specifier: ^7.28.6 + version: 7.29.2 + '@codemirror/commands': + specifier: ^6.10.2 + version: 6.10.3 + '@codemirror/language': + specifier: ^6.12.1 + version: 6.12.3 + '@codemirror/search': + specifier: ^6.6.0 + version: 6.6.0 + '@codemirror/state': + specifier: ^6.5.4 + version: 6.6.0 + '@codemirror/view': + specifier: ^6.39.15 + version: 6.40.0 + autoprefixer: + specifier: ^10.4.24 + version: 10.4.27(postcss@8.5.8) + babel-loader: + specifier: ^10.0.0 + version: 10.1.1(@babel/core@7.29.0)(webpack@5.105.4) + babel-plugin-dynamic-import-node: + specifier: ^2.3.3 + version: 2.3.3 + babel-plugin-transform-builtin-extend: + specifier: 1.1.2 + version: 1.1.2 + base64-loader: + specifier: ^1.0.0 + version: 1.0.0 + chromedriver: + specifier: ^143.0.4 + version: 143.0.4 + cli-progress: + specifier: ^3.12.0 + version: 3.12.0 + colors: + specifier: ^1.4.0 + version: 1.4.0 + compression-webpack-plugin: + specifier: ^11.1.0 + version: 11.1.0(webpack@5.105.4) + copy-webpack-plugin: + specifier: ^13.0.1 + version: 13.0.1(webpack@5.105.4) + core-js: + specifier: ^3.48.0 + version: 3.49.0 + cspell: + specifier: ^8.19.4 + version: 8.19.4 + css-loader: + specifier: 7.1.4 + version: 7.1.4(webpack@5.105.4) + eslint: + specifier: ^9.39.3 + version: 9.39.4(jiti@2.6.1) + eslint-plugin-jsdoc: + specifier: ^48.11.0 + version: 48.11.0(eslint@9.39.4(jiti@2.6.1)) + globals: + specifier: ^15.15.0 + version: 15.15.0 + grunt: + specifier: ^1.6.1 + version: 1.6.1 + grunt-chmod: + specifier: ~1.1.1 + version: 1.1.1 + grunt-concurrent: + specifier: ^3.0.0 + version: 3.0.0(grunt@1.6.1) + grunt-contrib-clean: + specifier: ~2.0.1 + version: 2.0.1(grunt@1.6.1) + grunt-contrib-connect: + specifier: ^5.0.1 + version: 5.0.1 + grunt-contrib-copy: + specifier: ~1.0.0 + version: 1.0.0 + grunt-contrib-watch: + specifier: ^1.1.0 + version: 1.1.0 + grunt-eslint: + specifier: ^25.0.0 + version: 25.0.0(grunt@1.6.1)(jiti@2.6.1) + grunt-exec: + specifier: ~3.0.0 + version: 3.0.0(grunt@1.6.1) + grunt-webpack: + specifier: ^6.0.0 + version: 6.0.0(webpack@5.105.4) + grunt-zip: + specifier: ^1.0.0 + version: 1.0.0 + html-webpack-plugin: + specifier: ^5.6.6 + version: 5.6.6(webpack@5.105.4) + imports-loader: + specifier: ^5.0.0 + version: 5.0.0(webpack@5.105.4) + mini-css-extract-plugin: + specifier: 2.10.0 + version: 2.10.0(webpack@5.105.4) + modify-source-webpack-plugin: + specifier: ^4.1.0 + version: 4.1.0(webpack@5.105.4) + nightwatch: + specifier: ^3.15.0 + version: 3.15.0(chromedriver@143.0.4) + postcss: + specifier: ^8.5.6 + version: 8.5.8 + postcss-css-variables: + specifier: ^0.19.0 + version: 0.19.0(postcss@8.5.8) + postcss-import: + specifier: ^16.1.1 + version: 16.1.1(postcss@8.5.8) + postcss-loader: + specifier: ^8.2.1 + version: 8.2.1(postcss@8.5.8)(webpack@5.105.4) + prompt: + specifier: ^1.3.0 + version: 1.3.0 + sitemap: + specifier: ^8.0.2 + version: 8.0.3 + terser: + specifier: ^5.46.0 + version: 5.46.1 + webpack: + specifier: ^5.105.2 + version: 5.105.4 + webpack-bundle-analyzer: + specifier: ^4.10.2 + version: 4.10.2 + webpack-dev-server: + specifier: 5.0.4 + version: 5.0.4(tslib@2.8.1)(webpack@5.105.4) + webpack-node-externals: + specifier: ^3.0.0 + version: 3.0.0 + worker-loader: + specifier: ^3.0.8 + version: 3.0.8(webpack@5.105.4) + +packages: + + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + + '@astronautlabs/amf@0.0.6': + resolution: {integrity: sha512-cJgbXW45TIDLQf2hiHqDoRfmeRy5u9Z4npr7sZfBThvbp5cbqDieTWaJTu91cUAj35/u87OHZijLTbMO18ZIow==} + engines: {node: ^14} + + '@astronautlabs/bitstream@4.2.2': + resolution: {integrity: sha512-/D18Aua0Er95TkulkVBXK5oweh55tXlgpug7g2cKdUvVBT91k2YD9n1RYnbrfaaHIN+KVDaBIrf3j9dS3DhzXw==} + peerDependencies: + reflect-metadata: ^0.1.13 + + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + engines: {node: '>=6.9.0'} + + '@babel/eslint-parser@7.28.6': + resolution: {integrity: sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==} + engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} + peerDependencies: + '@babel/core': ^7.11.0 + eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.28.6': + resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.28.5': + resolution: {integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.8': + resolution: {integrity: sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.28.5': + resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.27.1': + resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.28.6': + resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.28.6': + resolution: {integrity: sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.2': + resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': + resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1': + resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1': + resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1': + resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6': + resolution: {integrity: sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-assertions@7.28.6': + resolution: {integrity: sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.28.6': + resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-arrow-functions@7.27.1': + resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.29.0': + resolution: {integrity: sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.28.6': + resolution: {integrity: sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoped-functions@7.27.1': + resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.28.6': + resolution: {integrity: sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.28.6': + resolution: {integrity: sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.28.6': + resolution: {integrity: sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.28.6': + resolution: {integrity: sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-computed-properties@7.28.6': + resolution: {integrity: sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.28.5': + resolution: {integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-dotall-regex@7.28.6': + resolution: {integrity: sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-keys@7.27.1': + resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0': + resolution: {integrity: sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.27.1': + resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-explicit-resource-management@7.28.6': + resolution: {integrity: sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-exponentiation-operator@7.28.6': + resolution: {integrity: sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.27.1': + resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.27.1': + resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-function-name@7.27.1': + resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-json-strings@7.28.6': + resolution: {integrity: sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-literals@7.27.1': + resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.28.6': + resolution: {integrity: sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-member-expression-literals@7.27.1': + resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-amd@7.27.1': + resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.28.6': + resolution: {integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-systemjs@7.29.0': + resolution: {integrity: sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-umd@7.27.1': + resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0': + resolution: {integrity: sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-new-target@7.27.1': + resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6': + resolution: {integrity: sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.28.6': + resolution: {integrity: sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.28.6': + resolution: {integrity: sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.27.1': + resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.28.6': + resolution: {integrity: sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.28.6': + resolution: {integrity: sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.27.7': + resolution: {integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.28.6': + resolution: {integrity: sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.28.6': + resolution: {integrity: sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.27.1': + resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.29.0': + resolution: {integrity: sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regexp-modifiers@7.28.6': + resolution: {integrity: sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.27.1': + resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-runtime@7.29.0': + resolution: {integrity: sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.27.1': + resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.28.6': + resolution: {integrity: sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.27.1': + resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.27.1': + resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.27.1': + resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.27.1': + resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.28.6': + resolution: {integrity: sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.27.1': + resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.28.6': + resolution: {integrity: sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/polyfill@7.12.1': + resolution: {integrity: sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==} + deprecated: 🚨 This package has been deprecated in favor of separate inclusion of a polyfill and regenerator-runtime (when needed). See the @babel/polyfill docs (https://babeljs.io/docs/en/babel-polyfill) for more information. + + '@babel/preset-env@7.29.2': + resolution: {integrity: sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-modules@0.1.6-no-external-plugins': + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + + '@babel/runtime-corejs3@7.29.2': + resolution: {integrity: sha512-Lc94FOD5+0aXhdb0Tdg3RUtqT6yWbI/BbFWvlaSJ3gAb9Ks+99nHRDKADVqC37er4eCB0fHyWT+y+K3QOvJKbw==} + engines: {node: '>=6.9.0'} + + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@bazel/runfiles@6.5.0': + resolution: {integrity: sha512-RzahvqTkfpY2jsDxo8YItPX+/iZ6hbiikw1YhE0bA9EKBR5Og8Pa6FHn9PO9M0zaXRVsr0GFQLKbB/0rzy9SzA==} + + '@blu3r4y/lzma@2.3.3': + resolution: {integrity: sha512-2ckRSsYewLAgq/s8tUW3o5gurtCNYga1f9l0egV4QlT8hgVEilQHRt18s+behmPL2M/BPBxUINaOz67u++r0wA==} + hasBin: true + + '@codemirror/commands@6.10.3': + resolution: {integrity: sha512-JFRiqhKu+bvSkDLI+rUhJwSxQxYb759W5GBezE8Uc8mHLqC9aV/9aTC7yJSqCtB3F00pylrLCwnyS91Ap5ej4Q==} + + '@codemirror/language@6.12.3': + resolution: {integrity: sha512-QwCZW6Tt1siP37Jet9Tb02Zs81TQt6qQrZR2H+eGMcFsL1zMrk2/b9CLC7/9ieP1fjIUMgviLWMmgiHoJrj+ZA==} + + '@codemirror/search@6.6.0': + resolution: {integrity: sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==} + + '@codemirror/state@6.6.0': + resolution: {integrity: sha512-4nbvra5R5EtiCzr9BTHiTLc+MLXK2QGiAVYMyi8PkQd3SR+6ixar/Q/01Fa21TBIDOZXgeWV4WppsQolSreAPQ==} + + '@codemirror/view@6.40.0': + resolution: {integrity: sha512-WA0zdU7xfF10+5I3HhUUq3kqOx3KjqmtQ9lqZjfK7jtYk4G72YW9rezcSywpaUMCWOMlq+6E0pO1IWg1TNIhtg==} + + '@colors/colors@1.5.0': + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + + '@cspell/cspell-bundled-dicts@8.19.4': + resolution: {integrity: sha512-2ZRcZP/ncJ5q953o8i+R0fb8+14PDt5UefUNMrFZZHvfTI0jukAASOQeLY+WT6ASZv6CgbPrApAdbppy9FaXYQ==} + engines: {node: '>=18'} + + '@cspell/cspell-json-reporter@8.19.4': + resolution: {integrity: sha512-pOlUtLUmuDdTIOhDTvWxxta0Wm8RCD/p1V0qUqeP6/Ups1ajBI4FWEpRFd7yMBTUHeGeSNicJX5XeX7wNbAbLQ==} + engines: {node: '>=18'} + + '@cspell/cspell-pipe@8.19.4': + resolution: {integrity: sha512-GNAyk+7ZLEcL2fCMT5KKZprcdsq3L1eYy3e38/tIeXfbZS7Sd1R5FXUe6CHXphVWTItV39TvtLiDwN/2jBts9A==} + engines: {node: '>=18'} + + '@cspell/cspell-resolver@8.19.4': + resolution: {integrity: sha512-S8vJMYlsx0S1D60glX8H2Jbj4mD8519VjyY8lu3fnhjxfsl2bDFZvF3ZHKsLEhBE+Wh87uLqJDUJQiYmevHjDg==} + engines: {node: '>=18'} + + '@cspell/cspell-service-bus@8.19.4': + resolution: {integrity: sha512-uhY+v8z5JiUogizXW2Ft/gQf3eWrh5P9036jN2Dm0UiwEopG/PLshHcDjRDUiPdlihvA0RovrF0wDh4ptcrjuQ==} + engines: {node: '>=18'} + + '@cspell/cspell-types@8.19.4': + resolution: {integrity: sha512-ekMWuNlFiVGfsKhfj4nmc8JCA+1ZltwJgxiKgDuwYtR09ie340RfXFF6YRd2VTW5zN7l4F1PfaAaPklVz6utSg==} + engines: {node: '>=18'} + + '@cspell/dict-ada@4.1.1': + resolution: {integrity: sha512-E+0YW9RhZod/9Qy2gxfNZiHJjCYFlCdI69br1eviQQWB8yOTJX0JHXLs79kOYhSW0kINPVUdvddEBe6Lu6CjGQ==} + + '@cspell/dict-al@1.1.1': + resolution: {integrity: sha512-sD8GCaZetgQL4+MaJLXqbzWcRjfKVp8x+px3HuCaaiATAAtvjwUQ5/Iubiqwfd1boIh2Y1/3EgM3TLQ7Q8e0wQ==} + + '@cspell/dict-aws@4.0.17': + resolution: {integrity: sha512-ORcblTWcdlGjIbWrgKF+8CNEBQiLVKdUOFoTn0KPNkAYnFcdPP0muT4892h7H4Xafh3j72wqB4/loQ6Nti9E/w==} + + '@cspell/dict-bash@4.2.2': + resolution: {integrity: sha512-kyWbwtX3TsCf5l49gGQIZkRLaB/P8g73GDRm41Zu8Mv51kjl2H7Au0TsEvHv7jzcsRLS6aUYaZv6Zsvk1fOz+Q==} + + '@cspell/dict-companies@3.2.11': + resolution: {integrity: sha512-0cmafbcz2pTHXLd59eLR1gvDvN6aWAOM0+cIL4LLF9GX9yB2iKDNrKsvs4tJRqutoaTdwNFBbV0FYv+6iCtebQ==} + + '@cspell/dict-cpp@6.0.15': + resolution: {integrity: sha512-N7MKK3llRNoBncygvrnLaGvmjo4xzVr5FbtAc9+MFGHK6/LeSySBupr1FM72XDaVSIsmBEe7sDYCHHwlI9Jb2w==} + + '@cspell/dict-cryptocurrencies@5.0.5': + resolution: {integrity: sha512-R68hYYF/rtlE6T/dsObStzN5QZw+0aQBinAXuWCVqwdS7YZo0X33vGMfChkHaiCo3Z2+bkegqHlqxZF4TD3rUA==} + + '@cspell/dict-csharp@4.0.8': + resolution: {integrity: sha512-qmk45pKFHSxckl5mSlbHxmDitSsGMlk/XzFgt7emeTJWLNSTUK//MbYAkBNRtfzB4uD7pAFiKgpKgtJrTMRnrQ==} + + '@cspell/dict-css@4.1.1': + resolution: {integrity: sha512-y/Vgo6qY08e1t9OqR56qjoFLBCpi4QfWMf2qzD1l9omRZwvSMQGRPz4x0bxkkkU4oocMAeztjzCsmLew//c/8w==} + + '@cspell/dict-dart@2.3.2': + resolution: {integrity: sha512-sUiLW56t9gfZcu8iR/5EUg+KYyRD83Cjl3yjDEA2ApVuJvK1HhX+vn4e4k4YfjpUQMag8XO2AaRhARE09+/rqw==} + + '@cspell/dict-data-science@2.0.13': + resolution: {integrity: sha512-l1HMEhBJkPmw4I2YGVu2eBSKM89K9pVF+N6qIr5Uo5H3O979jVodtuwP8I7LyPrJnC6nz28oxeGRCLh9xC5CVA==} + + '@cspell/dict-django@4.1.6': + resolution: {integrity: sha512-SdbSFDGy9ulETqNz15oWv2+kpWLlk8DJYd573xhIkeRdcXOjskRuxjSZPKfW7O3NxN/KEf3gm3IevVOiNuFS+w==} + + '@cspell/dict-docker@1.1.17': + resolution: {integrity: sha512-OcnVTIpHIYYKhztNTyK8ShAnXTfnqs43hVH6p0py0wlcwRIXe5uj4f12n7zPf2CeBI7JAlPjEsV0Rlf4hbz/xQ==} + + '@cspell/dict-dotnet@5.0.13': + resolution: {integrity: sha512-xPp7jMnFpOri7tzmqmm/dXMolXz1t2bhNqxYkOyMqXhvs08oc7BFs+EsbDY0X7hqiISgeFZGNqn0dOCr+ncPYw==} + + '@cspell/dict-elixir@4.0.8': + resolution: {integrity: sha512-CyfphrbMyl4Ms55Vzuj+mNmd693HjBFr9hvU+B2YbFEZprE5AG+EXLYTMRWrXbpds4AuZcvN3deM2XVB80BN/Q==} + + '@cspell/dict-en-common-misspellings@2.1.12': + resolution: {integrity: sha512-14Eu6QGqyksqOd4fYPuRb58lK1Va7FQK9XxFsRKnZU8LhL3N+kj7YKDW+7aIaAN/0WGEqslGP6lGbQzNti8Akw==} + + '@cspell/dict-en-gb@1.1.33': + resolution: {integrity: sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g==} + + '@cspell/dict-en_us@4.4.33': + resolution: {integrity: sha512-zWftVqfUStDA37wO1ZNDN1qMJOfcxELa8ucHW8W8wBAZY3TK5Nb6deLogCK/IJi/Qljf30dwwuqqv84Qqle9Tw==} + + '@cspell/dict-filetypes@3.0.18': + resolution: {integrity: sha512-yU7RKD/x1IWmDLzWeiItMwgV+6bUcU/af23uS0+uGiFUbsY1qWV/D4rxlAAO6Z7no3J2z8aZOkYIOvUrJq0Rcw==} + + '@cspell/dict-flutter@1.1.1': + resolution: {integrity: sha512-UlOzRcH2tNbFhZmHJN48Za/2/MEdRHl2BMkCWZBYs+30b91mWvBfzaN4IJQU7dUZtowKayVIF9FzvLZtZokc5A==} + + '@cspell/dict-fonts@4.0.6': + resolution: {integrity: sha512-aR/0csY01dNb0A1tw/UmN9rKgHruUxsYsvXu6YlSBJFu60s26SKr/k1o4LavpHTQ+lznlYMqAvuxGkE4Flliqw==} + + '@cspell/dict-fsharp@1.1.1': + resolution: {integrity: sha512-imhs0u87wEA4/cYjgzS0tAyaJpwG7vwtC8UyMFbwpmtw+/bgss+osNfyqhYRyS/ehVCWL17Ewx2UPkexjKyaBA==} + + '@cspell/dict-fullstack@3.2.9': + resolution: {integrity: sha512-diZX+usW5aZ4/b2T0QM/H/Wl9aNMbdODa1Jq0ReBr/jazmNeWjd+PyqeVgzd1joEaHY+SAnjrf/i9CwKd2ZtWQ==} + + '@cspell/dict-gaming-terms@1.1.2': + resolution: {integrity: sha512-9XnOvaoTBscq0xuD6KTEIkk9hhdfBkkvJAIsvw3JMcnp1214OCGW8+kako5RqQ2vTZR3Tnf3pc57o7VgkM0q1Q==} + + '@cspell/dict-git@3.1.0': + resolution: {integrity: sha512-KEt9zGkxqGy2q1nwH4CbyqTSv5nadpn8BAlDnzlRcnL0Xb3LX9xTgSGShKvzb0bw35lHoYyLWN2ZKAqbC4pgGQ==} + + '@cspell/dict-golang@6.0.26': + resolution: {integrity: sha512-YKA7Xm5KeOd14v5SQ4ll6afe9VSy3a2DWM7L9uBq4u3lXToRBQ1W5PRa+/Q9udd+DTURyVVnQ+7b9cnOlNxaRg==} + + '@cspell/dict-google@1.0.9': + resolution: {integrity: sha512-biL65POqialY0i4g6crj7pR6JnBkbsPovB2WDYkj3H4TuC/QXv7Pu5pdPxeUJA6TSCHI7T5twsO4VSVyRxD9CA==} + + '@cspell/dict-haskell@4.0.6': + resolution: {integrity: sha512-ib8SA5qgftExpYNjWhpYIgvDsZ/0wvKKxSP+kuSkkak520iPvTJumEpIE+qPcmJQo4NzdKMN8nEfaeci4OcFAQ==} + + '@cspell/dict-html-symbol-entities@4.0.5': + resolution: {integrity: sha512-429alTD4cE0FIwpMucvSN35Ld87HCyuM8mF731KU5Rm4Je2SG6hmVx7nkBsLyrmH3sQukTcr1GaiZsiEg8svPA==} + + '@cspell/dict-html@4.0.15': + resolution: {integrity: sha512-GJYnYKoD9fmo2OI0aySEGZOjThnx3upSUvV7mmqUu8oG+mGgzqm82P/f7OqsuvTaInZZwZbo+PwJQd/yHcyFIw==} + + '@cspell/dict-java@5.0.12': + resolution: {integrity: sha512-qPSNhTcl7LGJ5Qp6VN71H8zqvRQK04S08T67knMq9hTA8U7G1sTKzLmBaDOFhq17vNX/+rT+rbRYp+B5Nwza1A==} + + '@cspell/dict-julia@1.1.1': + resolution: {integrity: sha512-WylJR9TQ2cgwd5BWEOfdO3zvDB+L7kYFm0I9u0s9jKHWQ6yKmfKeMjU9oXxTBxIufhCXm92SKwwVNAC7gjv+yA==} + + '@cspell/dict-k8s@1.0.12': + resolution: {integrity: sha512-2LcllTWgaTfYC7DmkMPOn9GsBWsA4DZdlun4po8s2ysTP7CPEnZc1ZfK6pZ2eI4TsZemlUQQ+NZxMe9/QutQxg==} + + '@cspell/dict-kotlin@1.1.1': + resolution: {integrity: sha512-J3NzzfgmxRvEeOe3qUXnSJQCd38i/dpF9/t3quuWh6gXM+krsAXP75dY1CzDmS8mrJAlBdVBeAW5eAZTD8g86Q==} + + '@cspell/dict-latex@4.0.4': + resolution: {integrity: sha512-YdTQhnTINEEm/LZgTzr9Voz4mzdOXH7YX+bSFs3hnkUHCUUtX/mhKgf1CFvZ0YNM2afjhQcmLaR9bDQVyYBvpA==} + + '@cspell/dict-lorem-ipsum@4.0.5': + resolution: {integrity: sha512-9a4TJYRcPWPBKkQAJ/whCu4uCAEgv/O2xAaZEI0n4y1/l18Yyx8pBKoIX5QuVXjjmKEkK7hi5SxyIsH7pFEK9Q==} + + '@cspell/dict-lua@4.0.8': + resolution: {integrity: sha512-N4PkgNDMu9JVsRu7JBS/3E/dvfItRgk9w5ga2dKq+JupP2Y3lojNaAVFhXISh4Y0a6qXDn2clA6nvnavQ/jjLA==} + + '@cspell/dict-makefile@1.0.5': + resolution: {integrity: sha512-4vrVt7bGiK8Rx98tfRbYo42Xo2IstJkAF4tLLDMNQLkQ86msDlYSKG1ZCk8Abg+EdNcFAjNhXIiNO+w4KflGAQ==} + + '@cspell/dict-markdown@2.0.16': + resolution: {integrity: sha512-976RRqKv6cwhrxdFCQP2DdnBVB86BF57oQtPHy4Zbf4jF/i2Oy29MCrxirnOBalS1W6KQeto7NdfDXRAwkK4PQ==} + peerDependencies: + '@cspell/dict-css': ^4.1.1 + '@cspell/dict-html': ^4.0.15 + '@cspell/dict-html-symbol-entities': ^4.0.5 + '@cspell/dict-typescript': ^3.2.3 + + '@cspell/dict-monkeyc@1.0.12': + resolution: {integrity: sha512-MN7Vs11TdP5mbdNFQP5x2Ac8zOBm97ARg6zM5Sb53YQt/eMvXOMvrep7+/+8NJXs0jkp70bBzjqU4APcqBFNAw==} + + '@cspell/dict-node@5.0.9': + resolution: {integrity: sha512-hO+ga+uYZ/WA4OtiMEyKt5rDUlUyu3nXMf8KVEeqq2msYvAPdldKBGH7lGONg6R/rPhv53Rb+0Y1SLdoK1+7wQ==} + + '@cspell/dict-npm@5.2.38': + resolution: {integrity: sha512-21ucGRPYYhr91C2cDBoMPTrcIOStQv33xOqJB0JLoC5LAs2Sfj9EoPGhGb+gIFVHz6Ia7JQWE2SJsOVFJD1wmg==} + + '@cspell/dict-php@4.1.1': + resolution: {integrity: sha512-EXelI+4AftmdIGtA8HL8kr4WlUE11OqCSVlnIgZekmTkEGSZdYnkFdiJ5IANSALtlQ1mghKjz+OFqVs6yowgWA==} + + '@cspell/dict-powershell@5.0.15': + resolution: {integrity: sha512-l4S5PAcvCFcVDMJShrYD0X6Huv9dcsQPlsVsBGbH38wvuN7gS7+GxZFAjTNxDmTY1wrNi1cCatSg6Pu2BW4rgg==} + + '@cspell/dict-public-licenses@2.0.16': + resolution: {integrity: sha512-EQRrPvEOmwhwWezV+W7LjXbIBjiy6y/shrET6Qcpnk3XANTzfvWflf9PnJ5kId/oKWvihFy0za0AV1JHd03pSQ==} + + '@cspell/dict-python@4.2.26': + resolution: {integrity: sha512-hbjN6BjlSgZOG2dA2DtvYNGBM5Aq0i0dHaZjMOI9K/9vRicVvKbcCiBSSrR3b+jwjhQL5ff7HwG5xFaaci0GQA==} + + '@cspell/dict-r@2.1.1': + resolution: {integrity: sha512-71Ka+yKfG4ZHEMEmDxc6+blFkeTTvgKbKAbwiwQAuKl3zpqs1Y0vUtwW2N4b3LgmSPhV3ODVY0y4m5ofqDuKMw==} + + '@cspell/dict-ruby@5.1.1': + resolution: {integrity: sha512-LHrp84oEV6q1ZxPPyj4z+FdKyq1XAKYPtmGptrd+uwHbrF/Ns5+fy6gtSi7pS+uc0zk3JdO9w/tPK+8N1/7WUA==} + + '@cspell/dict-rust@4.1.2': + resolution: {integrity: sha512-O1FHrumYcO+HZti3dHfBPUdnDFkI+nbYK3pxYmiM1sr+G0ebOd6qchmswS0Wsc6ZdEVNiPYJY/gZQR6jfW3uOg==} + + '@cspell/dict-scala@5.0.9': + resolution: {integrity: sha512-AjVcVAELgllybr1zk93CJ5wSUNu/Zb5kIubymR/GAYkMyBdYFCZ3Zbwn4Zz8GJlFFAbazABGOu0JPVbeY59vGg==} + + '@cspell/dict-shell@1.1.2': + resolution: {integrity: sha512-WqOUvnwcHK1X61wAfwyXq04cn7KYyskg90j4lLg3sGGKMW9Sq13hs91pqrjC44Q+lQLgCobrTkMDw9Wyl9nRFA==} + + '@cspell/dict-software-terms@5.2.2': + resolution: {integrity: sha512-0CaYd6TAsKtEoA7tNswm1iptEblTzEe3UG8beG2cpSTHk7afWIVMtJLgXDv0f/Li67Lf3Z1Jf3JeXR7GsJ2TRw==} + + '@cspell/dict-sql@2.2.1': + resolution: {integrity: sha512-qDHF8MpAYCf4pWU8NKbnVGzkoxMNrFqBHyG/dgrlic5EQiKANCLELYtGlX5auIMDLmTf1inA0eNtv74tyRJ/vg==} + + '@cspell/dict-svelte@1.0.7': + resolution: {integrity: sha512-hGZsGqP0WdzKkdpeVLBivRuSNzOTvN036EBmpOwxH+FTY2DuUH7ecW+cSaMwOgmq5JFSdTcbTNFlNC8HN8lhaQ==} + + '@cspell/dict-swift@2.0.6': + resolution: {integrity: sha512-PnpNbrIbex2aqU1kMgwEKvCzgbkHtj3dlFLPMqW1vSniop7YxaDTtvTUO4zA++ugYAEL+UK8vYrBwDPTjjvSnA==} + + '@cspell/dict-terraform@1.1.3': + resolution: {integrity: sha512-gr6wxCydwSFyyBKhBA2xkENXtVFToheqYYGFvlMZXWjviynXmh+NK/JTvTCk/VHk3+lzbO9EEQKee6VjrAUSbA==} + + '@cspell/dict-typescript@3.2.3': + resolution: {integrity: sha512-zXh1wYsNljQZfWWdSPYwQhpwiuW0KPW1dSd8idjMRvSD0aSvWWHoWlrMsmZeRl4qM4QCEAjua8+cjflm41cQBg==} + + '@cspell/dict-vue@3.0.5': + resolution: {integrity: sha512-Mqutb8jbM+kIcywuPQCCaK5qQHTdaByoEO2J9LKFy3sqAdiBogNkrplqUK0HyyRFgCfbJUgjz3N85iCMcWH0JA==} + + '@cspell/dynamic-import@8.19.4': + resolution: {integrity: sha512-0LLghC64+SiwQS20Sa0VfFUBPVia1rNyo0bYeIDoB34AA3qwguDBVJJkthkpmaP1R2JeR/VmxmJowuARc4ZUxA==} + engines: {node: '>=18.0'} + + '@cspell/filetypes@8.19.4': + resolution: {integrity: sha512-D9hOCMyfKtKjjqQJB8F80PWsjCZhVGCGUMiDoQpcta0e+Zl8vHgzwaC0Ai4QUGBhwYEawHGiWUd7Y05u/WXiNQ==} + engines: {node: '>=18'} + + '@cspell/strong-weak-map@8.19.4': + resolution: {integrity: sha512-MUfFaYD8YqVe32SQaYLI24/bNzaoyhdBIFY5pVrvMo1ZCvMl8AlfI2OcBXvcGb5aS5z7sCNCJm11UuoYbLI1zw==} + engines: {node: '>=18'} + + '@cspell/url@8.19.4': + resolution: {integrity: sha512-Pa474iBxS+lxsAL4XkETPGIq3EgMLCEb9agj3hAd2VGMTCApaiUvamR4b+uGXIPybN70piFxvzrfoxsG2uIP6A==} + engines: {node: '>=18.0'} + + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + + '@discoveryjs/json-ext@0.5.7': + resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} + engines: {node: '>=10.0.0'} + + '@es-joy/jsdoccomment@0.46.0': + resolution: {integrity: sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==} + engines: {node: '>=16'} + + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.2': + resolution: {integrity: sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.4.2': + resolution: {integrity: sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.17.0': + resolution: {integrity: sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.5': + resolution: {integrity: sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.39.4': + resolution: {integrity: sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.7': + resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.4.1': + resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jimp/core@1.6.0': + resolution: {integrity: sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==} + engines: {node: '>=18'} + + '@jimp/diff@1.6.0': + resolution: {integrity: sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==} + engines: {node: '>=18'} + + '@jimp/file-ops@1.6.0': + resolution: {integrity: sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==} + engines: {node: '>=18'} + + '@jimp/js-bmp@1.6.0': + resolution: {integrity: sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==} + engines: {node: '>=18'} + + '@jimp/js-gif@1.6.0': + resolution: {integrity: sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==} + engines: {node: '>=18'} + + '@jimp/js-jpeg@1.6.0': + resolution: {integrity: sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==} + engines: {node: '>=18'} + + '@jimp/js-png@1.6.0': + resolution: {integrity: sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==} + engines: {node: '>=18'} + + '@jimp/js-tiff@1.6.0': + resolution: {integrity: sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==} + engines: {node: '>=18'} + + '@jimp/plugin-blit@1.6.0': + resolution: {integrity: sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==} + engines: {node: '>=18'} + + '@jimp/plugin-blur@1.6.0': + resolution: {integrity: sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==} + engines: {node: '>=18'} + + '@jimp/plugin-circle@1.6.0': + resolution: {integrity: sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==} + engines: {node: '>=18'} + + '@jimp/plugin-color@1.6.0': + resolution: {integrity: sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==} + engines: {node: '>=18'} + + '@jimp/plugin-contain@1.6.0': + resolution: {integrity: sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==} + engines: {node: '>=18'} + + '@jimp/plugin-cover@1.6.0': + resolution: {integrity: sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==} + engines: {node: '>=18'} + + '@jimp/plugin-crop@1.6.0': + resolution: {integrity: sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==} + engines: {node: '>=18'} + + '@jimp/plugin-displace@1.6.0': + resolution: {integrity: sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==} + engines: {node: '>=18'} + + '@jimp/plugin-dither@1.6.0': + resolution: {integrity: sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==} + engines: {node: '>=18'} + + '@jimp/plugin-fisheye@1.6.0': + resolution: {integrity: sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==} + engines: {node: '>=18'} + + '@jimp/plugin-flip@1.6.0': + resolution: {integrity: sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==} + engines: {node: '>=18'} + + '@jimp/plugin-hash@1.6.0': + resolution: {integrity: sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==} + engines: {node: '>=18'} + + '@jimp/plugin-mask@1.6.0': + resolution: {integrity: sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==} + engines: {node: '>=18'} + + '@jimp/plugin-print@1.6.0': + resolution: {integrity: sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==} + engines: {node: '>=18'} + + '@jimp/plugin-quantize@1.6.0': + resolution: {integrity: sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==} + engines: {node: '>=18'} + + '@jimp/plugin-resize@1.6.0': + resolution: {integrity: sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==} + engines: {node: '>=18'} + + '@jimp/plugin-rotate@1.6.0': + resolution: {integrity: sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==} + engines: {node: '>=18'} + + '@jimp/plugin-threshold@1.6.0': + resolution: {integrity: sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==} + engines: {node: '>=18'} + + '@jimp/types@1.6.0': + resolution: {integrity: sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==} + engines: {node: '>=18'} + + '@jimp/utils@1.6.0': + resolution: {integrity: sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==} + engines: {node: '>=18'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@jsep-plugin/assignment@1.3.0': + resolution: {integrity: sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==} + engines: {node: '>= 10.16.0'} + peerDependencies: + jsep: ^0.4.0||^1.0.0 + + '@jsep-plugin/regex@1.0.4': + resolution: {integrity: sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==} + engines: {node: '>= 10.16.0'} + peerDependencies: + jsep: ^0.4.0||^1.0.0 + + '@jsonjoy.com/base64@1.1.2': + resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/base64@17.67.0': + resolution: {integrity: sha512-5SEsJGsm15aP8TQGkDfJvz9axgPwAEm98S5DxOuYe8e1EbfajcDmgeXXzccEjh+mLnjqEKrkBdjHWS5vFNwDdw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/buffers@1.2.1': + resolution: {integrity: sha512-12cdlDwX4RUM3QxmUbVJWqZ/mrK6dFQH4Zxq6+r1YXKXYBNgZXndx2qbCJwh3+WWkCSn67IjnlG3XYTvmvYtgA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/buffers@17.67.0': + resolution: {integrity: sha512-tfExRpYxBvi32vPs9ZHaTjSP4fHAfzSmcahOfNxtvGHcyJel+aibkPlGeBB+7AoC6hL7lXIE++8okecBxx7lcw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/codegen@1.0.0': + resolution: {integrity: sha512-E8Oy+08cmCf0EK/NMxpaJZmOxPqM+6iSe2S4nlSBrPZOORoDJILxtbSUEDKQyTamm/BVAhIGllOBNU79/dwf0g==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/codegen@17.67.0': + resolution: {integrity: sha512-idnkUplROpdBOV0HMcwhsCUS5TRUi9poagdGs70A6S4ux9+/aPuKbh8+UYRTLYQHtXvAdNfQWXDqZEx5k4Dj2Q==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-core@4.57.1': + resolution: {integrity: sha512-YrEi/ZPmgc+GfdO0esBF04qv8boK9Dg9WpRQw/+vM8Qt3nnVIJWIa8HwZ/LXVZ0DB11XUROM8El/7yYTJX+WtA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-fsa@4.57.1': + resolution: {integrity: sha512-ooEPvSW/HQDivPDPZMibHGKZf/QS4WRir1czGZmXmp3MsQqLECZEpN0JobrD8iV9BzsuwdIv+PxtWX9WpPLsIA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-builtins@4.57.1': + resolution: {integrity: sha512-XHkFKQ5GSH3uxm8c3ZYXVrexGdscpWKIcMWKFQpMpMJc8gA3AwOMBJXJlgpdJqmrhPyQXxaY9nbkNeYpacC0Og==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-to-fsa@4.57.1': + resolution: {integrity: sha512-pqGHyWWzNck4jRfaGV39hkqpY5QjRUQ/nRbNT7FYbBa0xf4bDG+TE1Gt2KWZrSkrkZZDE3qZUjYMbjwSliX6pg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node-utils@4.57.1': + resolution: {integrity: sha512-vp+7ZzIB8v43G+GLXTS4oDUSQmhAsRz532QmmWBbdYA20s465JvwhkSFvX9cVTqRRAQg+vZ7zWDaIEh0lFe2gw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-node@4.57.1': + resolution: {integrity: sha512-3YaKhP8gXEKN+2O49GLNfNb5l2gbnCFHyAaybbA2JkkbQP3dpdef7WcUaHAulg/c5Dg4VncHsA3NWAUSZMR5KQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-print@4.57.1': + resolution: {integrity: sha512-Ynct7ZJmfk6qoXDOKfpovNA36ITUx8rChLmRQtW08J73VOiuNsU8PB6d/Xs7fxJC2ohWR3a5AqyjmLojfrw5yw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/fs-snapshot@4.57.1': + resolution: {integrity: sha512-/oG8xBNFMbDXTq9J7vepSA1kerS5vpgd3p5QZSPd+nX59uwodGJftI51gDYyHRpP57P3WCQf7LHtBYPqwUg2Bg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@1.21.0': + resolution: {integrity: sha512-+AKG+R2cfZMShzrF2uQw34v3zbeDYUqnQ+jg7ORic3BGtfw9p/+N6RJbq/kkV8JmYZaINknaEQ2m0/f693ZPpg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@17.67.0': + resolution: {integrity: sha512-t0ejURcGaZsn1ClbJ/3kFqSOjlryd92eQY465IYrezsXmPcfHPE/av4twRSxf6WE+TkZgLY+71vCZbiIiFKA/w==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pointer@1.0.2': + resolution: {integrity: sha512-Fsn6wM2zlDzY1U+v4Nc8bo3bVqgfNTGcn6dMgs6FjrEnt4ZCe60o6ByKRjOGlI2gow0aE/Q41QOigdTqkyK5fg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pointer@17.67.0': + resolution: {integrity: sha512-+iqOFInH+QZGmSuaybBUNdh7yvNrXvqR+h3wjXm0N/3JK1EyyFAeGJvqnmQL61d1ARLlk/wJdFKSL+LHJ1eaUA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@1.9.0': + resolution: {integrity: sha512-pLuQo+VPRnN8hfPqUTLTHk126wuYdXVxE6aDmjSeV4NCAgyxWbiOIeNJVtID3h1Vzpoi9m4jXezf73I6LgabgQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@17.67.0': + resolution: {integrity: sha512-6+8xBaz1rLSohlGh68D1pdw3AwDi9xydm8QNlAFkvnavCJYSze+pxoW2VKP8p308jtlMRLs5NTHfPlZLd4w7ew==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@leichtgewicht/ip-codec@2.0.5': + resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} + + '@lezer/common@1.5.1': + resolution: {integrity: sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw==} + + '@lezer/highlight@1.2.3': + resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==} + + '@lezer/lr@1.4.8': + resolution: {integrity: sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA==} + + '@marijn/find-cluster-break@1.0.2': + resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} + + '@napi-rs/nice-android-arm-eabi@1.1.1': + resolution: {integrity: sha512-kjirL3N6TnRPv5iuHw36wnucNqXAO46dzK9oPb0wj076R5Xm8PfUVA9nAFB5ZNMmfJQJVKACAPd/Z2KYMppthw==} + engines: {node: '>= 10'} + cpu: [arm] + os: [android] + + '@napi-rs/nice-android-arm64@1.1.1': + resolution: {integrity: sha512-blG0i7dXgbInN5urONoUCNf+DUEAavRffrO7fZSeoRMJc5qD+BJeNcpr54msPF6qfDD6kzs9AQJogZvT2KD5nw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [android] + + '@napi-rs/nice-darwin-arm64@1.1.1': + resolution: {integrity: sha512-s/E7w45NaLqTGuOjC2p96pct4jRfo61xb9bU1unM/MJ/RFkKlJyJDx7OJI/O0ll/hrfpqKopuAFDV8yo0hfT7A==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@napi-rs/nice-darwin-x64@1.1.1': + resolution: {integrity: sha512-dGoEBnVpsdcC+oHHmW1LRK5eiyzLwdgNQq3BmZIav+9/5WTZwBYX7r5ZkQC07Nxd3KHOCkgbHSh4wPkH1N1LiQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@napi-rs/nice-freebsd-x64@1.1.1': + resolution: {integrity: sha512-kHv4kEHAylMYmlNwcQcDtXjklYp4FCf0b05E+0h6nDHsZ+F0bDe04U/tXNOqrx5CmIAth4vwfkjjUmp4c4JktQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [freebsd] + + '@napi-rs/nice-linux-arm-gnueabihf@1.1.1': + resolution: {integrity: sha512-E1t7K0efyKXZDoZg1LzCOLxgolxV58HCkaEkEvIYQx12ht2pa8hoBo+4OB3qh7e+QiBlp1SRf+voWUZFxyhyqg==} + engines: {node: '>= 10'} + cpu: [arm] + os: [linux] + + '@napi-rs/nice-linux-arm64-gnu@1.1.1': + resolution: {integrity: sha512-CIKLA12DTIZlmTaaKhQP88R3Xao+gyJxNWEn04wZwC2wmRapNnxCUZkVwggInMJvtVElA+D4ZzOU5sX4jV+SmQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-arm64-musl@1.1.1': + resolution: {integrity: sha512-+2Rzdb3nTIYZ0YJF43qf2twhqOCkiSrHx2Pg6DJaCPYhhaxbLcdlV8hCRMHghQ+EtZQWGNcS2xF4KxBhSGeutg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@napi-rs/nice-linux-ppc64-gnu@1.1.1': + resolution: {integrity: sha512-4FS8oc0GeHpwvv4tKciKkw3Y4jKsL7FRhaOeiPei0X9T4Jd619wHNe4xCLmN2EMgZoeGg+Q7GY7BsvwKpL22Tg==} + engines: {node: '>= 10'} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-riscv64-gnu@1.1.1': + resolution: {integrity: sha512-HU0nw9uD4FO/oGCCk409tCi5IzIZpH2agE6nN4fqpwVlCn5BOq0MS1dXGjXaG17JaAvrlpV5ZeyZwSon10XOXw==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-s390x-gnu@1.1.1': + resolution: {integrity: sha512-2YqKJWWl24EwrX0DzCQgPLKQBxYDdBxOHot1KWEq7aY2uYeX+Uvtv4I8xFVVygJDgf6/92h9N3Y43WPx8+PAgQ==} + engines: {node: '>= 10'} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-x64-gnu@1.1.1': + resolution: {integrity: sha512-/gaNz3R92t+dcrfCw/96pDopcmec7oCcAQ3l/M+Zxr82KT4DljD37CpgrnXV+pJC263JkW572pdbP3hP+KjcIg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@napi-rs/nice-linux-x64-musl@1.1.1': + resolution: {integrity: sha512-xScCGnyj/oppsNPMnevsBe3pvNaoK7FGvMjT35riz9YdhB2WtTG47ZlbxtOLpjeO9SqqQ2J2igCmz6IJOD5JYw==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@napi-rs/nice-openharmony-arm64@1.1.1': + resolution: {integrity: sha512-6uJPRVwVCLDeoOaNyeiW0gp2kFIM4r7PL2MczdZQHkFi9gVlgm+Vn+V6nTWRcu856mJ2WjYJiumEajfSm7arPQ==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [openharmony] + + '@napi-rs/nice-win32-arm64-msvc@1.1.1': + resolution: {integrity: sha512-uoTb4eAvM5B2aj/z8j+Nv8OttPf2m+HVx3UjA5jcFxASvNhQriyCQF1OB1lHL43ZhW+VwZlgvjmP5qF3+59atA==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@napi-rs/nice-win32-ia32-msvc@1.1.1': + resolution: {integrity: sha512-CNQqlQT9MwuCsg1Vd/oKXiuH+TcsSPJmlAFc5frFyX/KkOh0UpBLEj7aoY656d5UKZQMQFP7vJNa1DNUNORvug==} + engines: {node: '>= 10'} + cpu: [ia32] + os: [win32] + + '@napi-rs/nice-win32-x64-msvc@1.1.1': + resolution: {integrity: sha512-vB+4G/jBQCAh0jelMTY3+kgFy00Hlx2f2/1zjMoH821IbplbWZOkLiTYXQkygNTzQJTq5cvwBDgn2ppHD+bglQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@napi-rs/nice@1.1.1': + resolution: {integrity: sha512-xJIPs+bYuc9ASBl+cvGsKbGrJmS6fAKaSZCnT0lhahT5rhA2VVy9/EcIgd2JhtEuFOJNx7UHNn/qiTPTY4nrQw==} + engines: {node: '>= 10'} + + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} + + '@nightwatch/chai@5.0.3': + resolution: {integrity: sha512-1OIkOf/7jswOC3/t+Add/HVQO8ib75kz6BVYSNeWGghTlmHUqYEfNJ6vcACbXrn/4v3+9iRlWixuhFkxXkU/RQ==} + engines: {node: '>=12'} + + '@nightwatch/html-reporter-template@0.3.0': + resolution: {integrity: sha512-Mze1z6pmUz2O8N9w1/h3QWz1lzMig45PGyh8PrL9ERs3FxVnIX0RCn37vjZUYiV4wgjZOg41JjdcpriZ3dJxkA==} + + '@nightwatch/nightwatch-inspector@1.0.1': + resolution: {integrity: sha512-/ax11EOB4eJXT5VioMztcalbCtsNeuFn6icfT75qPLBmkxLvThePSfyGTys+t9AULUR0ug0wMDMiLV1Oy586Fg==} + + '@noble/hashes@1.6.1': + resolution: {integrity: sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==} + engines: {node: ^14.21.3 || >=16} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pkgr/core@0.1.2': + resolution: {integrity: sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + + '@testim/chrome-version@1.1.4': + resolution: {integrity: sha512-kIhULpw9TrGYnHp/8VfdcneIcxKnLixmADtukQRtJUmsVlMg0niMkwV0xZmi8hqa57xqilIHjWFA0GKvEjVU5g==} + + '@tokenizer/token@0.3.0': + resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + + '@tootallnate/quickjs-emscripten@0.23.0': + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + + '@types/body-parser@1.19.6': + resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} + + '@types/bonjour@3.5.13': + resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} + + '@types/chai@4.3.20': + resolution: {integrity: sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==} + + '@types/connect-history-api-fallback@1.5.4': + resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/eslint-scope@3.7.7': + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/express-serve-static-core@4.19.8': + resolution: {integrity: sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==} + + '@types/express-serve-static-core@5.1.1': + resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==} + + '@types/express@4.17.25': + resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} + + '@types/html-minifier-terser@6.1.0': + resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} + + '@types/http-errors@2.0.5': + resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} + + '@types/http-proxy@1.17.17': + resolution: {integrity: sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + + '@types/node-forge@1.3.14': + resolution: {integrity: sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==} + + '@types/node@16.9.1': + resolution: {integrity: sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==} + + '@types/node@17.0.45': + resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + + '@types/node@25.5.0': + resolution: {integrity: sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==} + + '@types/qs@6.15.0': + resolution: {integrity: sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + + '@types/retry@0.12.2': + resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} + + '@types/sax@1.2.7': + resolution: {integrity: sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==} + + '@types/selenium-webdriver@4.35.5': + resolution: {integrity: sha512-wCQCjWmahRkUAO7S703UAvBFkxz4o/rjX4T2AOSWKXSi0sTQPsrXxR0GjtFUT0ompedLkYH4R5HO5Urz0hyeog==} + + '@types/send@0.17.6': + resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} + + '@types/send@1.2.1': + resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} + + '@types/serve-index@1.9.4': + resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} + + '@types/serve-static@1.15.10': + resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} + + '@types/sockjs@0.3.36': + resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + + '@wavesenterprise/crypto-gost-js@2.1.0-RC1': + resolution: {integrity: sha512-liAR3/T/vxnEgNUE00Llt+sDvKYqo+sm/L7tqkJorg2ha3SsplOSXAqpH0t4Ya0gRj8qN8zXqO+WwLCxXXuQcw==} + + '@webassemblyjs/ast@1.14.1': + resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} + + '@webassemblyjs/floating-point-hex-parser@1.13.2': + resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} + + '@webassemblyjs/helper-api-error@1.13.2': + resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} + + '@webassemblyjs/helper-buffer@1.14.1': + resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} + + '@webassemblyjs/helper-numbers@1.13.2': + resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': + resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} + + '@webassemblyjs/helper-wasm-section@1.14.1': + resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} + + '@webassemblyjs/ieee754@1.13.2': + resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} + + '@webassemblyjs/leb128@1.13.2': + resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} + + '@webassemblyjs/utf8@1.13.2': + resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} + + '@webassemblyjs/wasm-edit@1.14.1': + resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} + + '@webassemblyjs/wasm-gen@1.14.1': + resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} + + '@webassemblyjs/wasm-opt@1.14.1': + resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} + + '@webassemblyjs/wasm-parser@1.14.1': + resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} + + '@webassemblyjs/wast-printer@1.14.1': + resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} + + '@xmldom/xmldom@0.8.11': + resolution: {integrity: sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==} + engines: {node: '>=10.0.0'} + + '@xtuc/ieee754@1.2.0': + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + + '@xtuc/long@4.2.2': + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-import-phases@1.0.4: + resolution: {integrity: sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==} + engines: {node: '>=10.13.0'} + peerDependencies: + acorn: ^8.14.0 + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} + engines: {node: '>=0.4.0'} + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-keywords@3.5.2: + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + + ajv-keywords@5.1.0: + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + + ajv@6.14.0: + resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} + + ajv@8.18.0: + resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==} + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-html-community@0.0.8: + resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} + engines: {'0': node >= 0.8.0} + hasBin: true + + ansi-regex@2.1.1: + resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} + engines: {node: '>=0.10.0'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.2.2: + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} + + ansi-styles@2.2.1: + resolution: {integrity: sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==} + engines: {node: '>=0.10.0'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} + + ansi-to-html@0.7.2: + resolution: {integrity: sha512-v6MqmEpNlxF+POuyhKkidusCHWWkaLcGRURzivcU3I9tv7k4JVhFcnukrM5Rlk2rUywdZuzYAZ+kbZqWCnfN3g==} + engines: {node: '>=8.0.0'} + hasBin: true + + any-base@1.1.0: + resolution: {integrity: sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + archiver-utils@2.1.0: + resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} + engines: {node: '>= 6'} + + archiver-utils@3.0.4: + resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==} + engines: {node: '>= 10'} + + archiver@5.3.2: + resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} + engines: {node: '>= 10'} + + are-docs-informative@0.0.2: + resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} + engines: {node: '>=14'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argon2-browser@1.18.0: + resolution: {integrity: sha512-ImVAGIItnFnvET1exhsQB7apRztcoC5TnlSqernMJDUjbc/DLq3UEYeXFrLPrlaIl8cVfwnXb6wX2KpFf2zxHw==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-each@1.0.1: + resolution: {integrity: sha512-zHjL5SZa68hkKHBFBK6DJCTtr9sfTCPCaph/L7tMSLcTFgy+zX7E+6q5UArbtOtMBCtxdICpfTCspRse+ywyXA==} + engines: {node: '>=0.10.0'} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + array-slice@1.1.0: + resolution: {integrity: sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==} + engines: {node: '>=0.10.0'} + + array-timsort@1.0.3: + resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} + + arrify@2.0.1: + resolution: {integrity: sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==} + engines: {node: '>=8'} + + arrive@2.5.3: + resolution: {integrity: sha512-FsZjDDxS2BZ1TuGvqhTf8KbGaH0hOx+DS7HhYIvsreCkAuSUFgJ9NUhIC4f3SM3c5T/1he1KAn566GZjzqJarA==} + + asn1.js@4.10.1: + resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} + + assert@2.1.0: + resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} + + assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + + async@2.6.4: + resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} + + async@3.2.3: + resolution: {integrity: sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + autoprefixer@10.4.27: + resolution: {integrity: sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + avsc@5.7.9: + resolution: {integrity: sha512-yOA4wFeI7ET3v32Di/sUybQ+ttP20JHSW3mxLuNGeO0uD6PPcvLrIQXSvy/rhJOWU5JrYh7U4OHplWMmtAtjMg==} + engines: {node: '>=0.11'} + + await-to-js@3.0.0: + resolution: {integrity: sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==} + engines: {node: '>=6.0.0'} + + axe-core@4.11.1: + resolution: {integrity: sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==} + engines: {node: '>=4'} + + axios@1.14.0: + resolution: {integrity: sha512-3Y8yrqLSwjuzpXuZ0oIYZ/XGgLwUIBU3uLvbcpb0pidD9ctpShJd43KSlEEkVQg6DS0G9NKyzOvBfUtDKEyHvQ==} + + babel-code-frame@6.26.0: + resolution: {integrity: sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g==} + + babel-loader@10.1.1: + resolution: {integrity: sha512-JwKSzk2kjIe7mgPK+/lyZ2QAaJcpahNAdM+hgR2HI8D0OJVkdj8Rl6J3kaLYki9pwF7P2iWnD8qVv80Lq1ABtg==} + engines: {node: ^18.20.0 || ^20.10.0 || >=22.0.0} + peerDependencies: + '@babel/core': ^7.12.0 || ^8.0.0-beta.1 + '@rspack/core': ^1.0.0 || ^2.0.0-0 + webpack: '>=5.61.0' + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + babel-messages@6.23.0: + resolution: {integrity: sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w==} + + babel-plugin-dynamic-import-node@2.3.3: + resolution: {integrity: sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==} + + babel-plugin-polyfill-corejs2@0.4.17: + resolution: {integrity: sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.13.0: + resolution: {integrity: sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.14.2: + resolution: {integrity: sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.8: + resolution: {integrity: sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-transform-builtin-extend@1.1.2: + resolution: {integrity: sha512-foUQxHjMiLNynzJaBKrIoZfoRY22S620MLafGC5UfnBEwqcBODIFcgwqqzHE8Hj590lbUJCQ2uBo9y08+sYIkQ==} + + babel-runtime@6.26.0: + resolution: {integrity: sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==} + + babel-template@6.26.0: + resolution: {integrity: sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg==} + + babel-traverse@6.26.0: + resolution: {integrity: sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA==} + + babel-types@6.26.0: + resolution: {integrity: sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g==} + + babylon@6.18.0: + resolution: {integrity: sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==} + hasBin: true + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + base64-loader@1.0.0: + resolution: {integrity: sha512-p32+F8dg+ANGx7s8QsZS74ZPHfIycmC2yZcoerzFgbersIYWitPbbF39G6SBx3gyvzyLH5nt1ooocxr0IHuWKA==} + + baseline-browser-mapping@2.10.12: + resolution: {integrity: sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + basic-auth@2.0.1: + resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} + engines: {node: '>= 0.8'} + + basic-ftp@5.2.0: + resolution: {integrity: sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==} + engines: {node: '>=10.0.0'} + + batch@0.6.1: + resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} + + bcryptjs@2.4.3: + resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==} + + big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + + bignumber.js@9.3.1: + resolution: {integrity: sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + blakejs@1.2.1: + resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} + + bmp-js@0.1.0: + resolution: {integrity: sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==} + + bmp-ts@1.0.9: + resolution: {integrity: sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==} + + bn.js@4.12.3: + resolution: {integrity: sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==} + + bn.js@5.2.3: + resolution: {integrity: sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==} + + bn@1.0.5: + resolution: {integrity: sha512-7TvGbqbZb6lDzsBtNz1VkdXXV0BVmZKPPViPmo2IpvwaryF7P+QKYKACyVkwo2mZPr2CpFiz7EtgPEcc3o/JFQ==} + + body-parser@1.20.4: + resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + body@5.1.0: + resolution: {integrity: sha512-chUsBxGRtuElD6fmw1gHLpvnKdVLK302peeFa9ZqAEk8TyzZ3fygLyUEDDPTJvL9+Bor0dIwn6ePOsRM2y0zQQ==} + + bonjour-service@1.3.0: + resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + bootstrap-colorpicker@3.4.0: + resolution: {integrity: sha512-7vA0hvLrat3ptobEKlT9+6amzBUJcDAoh6hJRQY/AD+5dVZYXXf1ivRfrTwmuwiVLJo9rZwM8YB4lYzp6agzqg==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + bootstrap-material-design@4.1.3: + resolution: {integrity: sha512-jOB9io76BKLxwF+IAgObFH9f88ityqOiYsQe9Aa8m88h7sSP3eFL1K8ygb0FsYyIiVm194iodg9i4GMOSlLeRA==} + + bootstrap@4.6.2: + resolution: {integrity: sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==} + deprecated: This version of Bootstrap is no longer supported. Please upgrade to the latest version. + peerDependencies: + jquery: 1.9.1 - 3 + popper.js: ^1.16.1 + + boxen@5.1.2: + resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} + engines: {node: '>=10'} + + brace-expansion@1.1.13: + resolution: {integrity: sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==} + + brace-expansion@2.0.3: + resolution: {integrity: sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + + browser-stdout@1.3.1: + resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + + browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + + browserify-cipher@1.0.1: + resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} + + browserify-des@1.0.2: + resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} + + browserify-rsa@4.1.1: + resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} + engines: {node: '>= 0.10'} + + browserify-sign@4.2.5: + resolution: {integrity: sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==} + engines: {node: '>= 0.10'} + + browserify-zlib@0.2.0: + resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} + + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bson@4.7.2: + resolution: {integrity: sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==} + engines: {node: '>=6.9.0'} + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + + bytes@1.0.0: + resolution: {integrity: sha512-/x68VkHLeTl3/Ll8IvxdwzhrT+IyKc52e/oyHhA2RwqPqswSnjVbSddfPRwAsJtbilMAPSRWwAlpxdYsSWOTKQ==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + bzip-deflate@1.0.0: + resolution: {integrity: sha512-9RMnpiJqMYMJcLdr4pxwowZ8Zh3P+tVswE/bnX6tZ14UGKNcdV5WVK2P+lGp2As+RCjl+i3SFJ117HyCaaHNDA==} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001781: + resolution: {integrity: sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==} + + cbor@9.0.2: + resolution: {integrity: sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==} + engines: {node: '>=16'} + + chai-nightwatch@0.5.3: + resolution: {integrity: sha512-38ixH/mqpY6IwnZkz6xPqx8aB5/KVR+j6VPugcir3EGOsphnWXrPH/mUt8Jp+ninL6ghY0AaJDQ10hSfCPGy/g==} + engines: {node: '>= 12.0.0'} + + chalk-template@1.1.2: + resolution: {integrity: sha512-2bxTP2yUH7AJj/VAXfcA+4IcWGdQ87HwBANLt5XxGTeomo8yG0y95N1um9i5StvhT/Bl0/2cARA5v1PpPXUxUA==} + engines: {node: '>=14.16'} + + chalk@1.1.3: + resolution: {integrity: sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==} + engines: {node: '>=0.10.0'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + check-error@1.0.2: + resolution: {integrity: sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==} + + chi-squared@1.1.0: + resolution: {integrity: sha512-IFJA5igW44wzi7VHSsBcuHQ1+sF6noKRK6eFb+so4v9A/dH23RElM+8UBCi6+kWSINB/hDPNH+KDBCazPuKVwg==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} + engines: {node: '>=6.0'} + + chromedriver@143.0.4: + resolution: {integrity: sha512-mE++40DprY2n4d3OPxzW7ujIFRY9eLYwJf4uBgQtMaJQkapSVXRzUrLzSMcRaybrt47Y1t8xW5AKoaUIL3aYZw==} + engines: {node: '>=20'} + hasBin: true + + ci-info@3.3.0: + resolution: {integrity: sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==} + + cipher-base@1.0.7: + resolution: {integrity: sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==} + engines: {node: '>= 0.10'} + + clean-css@5.3.3: + resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} + engines: {node: '>= 10.0'} + + clear-module@4.1.2: + resolution: {integrity: sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw==} + engines: {node: '>=8'} + + cli-boxes@2.2.1: + resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} + engines: {node: '>=6'} + + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + + cli-progress@3.12.0: + resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==} + engines: {node: '>=4'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-table3@0.6.5: + resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==} + engines: {node: 10.* || >= 12.*} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + codepage@1.15.0: + resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==} + engines: {node: '>=0.8'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + colors@1.0.3: + resolution: {integrity: sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==} + engines: {node: '>=0.1.90'} + + colors@1.1.2: + resolution: {integrity: sha512-ENwblkFQpqqia6b++zLD/KUWafYlVY/UNnAp7oz7LY7E924wmpye416wBOmvv/HMWzl8gL1kJlfvId/1Dg176w==} + engines: {node: '>=0.1.90'} + + colors@1.4.0: + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} + engines: {node: '>=0.1.90'} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@13.1.0: + resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} + engines: {node: '>=18'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + + comment-json@4.6.2: + resolution: {integrity: sha512-R2rze/hDX30uul4NZoIZ76ImSJLFxn/1/ZxtKC1L77y2X1k+yYu1joKbAtMA2Fg3hZrTOiw0I5mwVMo0cf250w==} + engines: {node: '>= 6'} + + comment-parser@1.4.1: + resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} + engines: {node: '>= 12.0.0'} + + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + + compress-commons@4.1.2: + resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} + engines: {node: '>= 10'} + + compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + + compression-webpack-plugin@11.1.0: + resolution: {integrity: sha512-zDOQYp10+upzLxW+VRSjEpRRwBXJdsb5lBMlRxx1g8hckIFBpe3DTI0en2w7h+beuq89576RVzfiXrkdPGrHhA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + webpack: ^5.1.0 + + compression@1.8.1: + resolution: {integrity: sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==} + engines: {node: '>= 0.8.0'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + connect-history-api-fallback@2.0.0: + resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} + engines: {node: '>=0.8'} + + connect-livereload@0.6.1: + resolution: {integrity: sha512-3R0kMOdL7CjJpU66fzAkCe6HNtd3AavCS4m+uW4KtJjrdGPT0SQEZieAYd+cm+lJoBznNQ4lqipYWkhBMgk00g==} + + connect@3.7.0: + resolution: {integrity: sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==} + engines: {node: '>= 0.10.0'} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + continuable-cache@0.3.1: + resolution: {integrity: sha512-TF30kpKhTH8AGCG3dut0rdd/19B7Z+qCnrMoBLpyQu/2drZdNrrpcjPEoJeSVsQM+8KmWG5O56oPDjSSUsuTyA==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-signature@1.0.7: + resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + copy-webpack-plugin@13.0.1: + resolution: {integrity: sha512-J+YV3WfhY6W/Xf9h+J1znYuqTye2xkBUIGyTPWuBAT27qajBa5mR4f8WBmfDY3YjRftT2kqZZiLi1qf0H+UOFw==} + engines: {node: '>= 18.12.0'} + peerDependencies: + webpack: ^5.1.0 + + core-js-compat@3.49.0: + resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==} + + core-js-pure@3.49.0: + resolution: {integrity: sha512-XM4RFka59xATyJv/cS3O3Kml72hQXUeGRuuTmMYFxwzc9/7C8OYTaIR/Ji+Yt8DXzsFLNhat15cE/JP15HrCgw==} + + core-js@2.6.12: + resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==} + deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. + + core-js@3.49.0: + resolution: {integrity: sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cosmiconfig@9.0.1: + resolution: {integrity: sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + crc32-stream@4.0.3: + resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} + engines: {node: '>= 10'} + + create-ecdh@4.0.4: + resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} + + create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + + create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + + crelt@1.0.6: + resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crypto-api@0.8.5: + resolution: {integrity: sha512-kcif7fCeYZpUsA3Y1VidFrK4HRf2Lsx9X4cnl7pauTXjgnXfEjaTyUGxzIBJ6DZwEPgX/VyKkhAeBV+vXHwX2Q==} + + crypto-browserify@3.12.1: + resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} + engines: {node: '>= 0.10'} + + crypto-js@4.2.0: + resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} + + cspell-config-lib@8.19.4: + resolution: {integrity: sha512-LtFNZEWVrnpjiTNgEDsVN05UqhhJ1iA0HnTv4jsascPehlaUYVoyucgNbFeRs6UMaClJnqR0qT9lnPX+KO1OLg==} + engines: {node: '>=18'} + + cspell-dictionary@8.19.4: + resolution: {integrity: sha512-lr8uIm7Wub8ToRXO9f6f7in429P1Egm3I+Ps3ZGfWpwLTCUBnHvJdNF/kQqF7PL0Lw6acXcjVWFYT7l2Wdst2g==} + engines: {node: '>=18'} + + cspell-gitignore@8.19.4: + resolution: {integrity: sha512-KrViypPilNUHWZkMV0SM8P9EQVIyH8HvUqFscI7+cyzWnlglvzqDdV4N5f+Ax5mK+IqR6rTEX8JZbCwIWWV7og==} + engines: {node: '>=18'} + hasBin: true + + cspell-glob@8.19.4: + resolution: {integrity: sha512-042uDU+RjAz882w+DXKuYxI2rrgVPfRQDYvIQvUrY1hexH4sHbne78+OMlFjjzOCEAgyjnm1ktWUCCmh08pQUw==} + engines: {node: '>=18'} + + cspell-grammar@8.19.4: + resolution: {integrity: sha512-lzWgZYTu/L7DNOHjxuKf8H7DCXvraHMKxtFObf8bAzgT+aBmey5fW2LviXUkZ2Lb2R0qQY+TJ5VIGoEjNf55ow==} + engines: {node: '>=18'} + hasBin: true + + cspell-io@8.19.4: + resolution: {integrity: sha512-W48egJqZ2saEhPWf5ftyighvm4mztxEOi45ILsKgFikXcWFs0H0/hLwqVFeDurgELSzprr12b6dXsr67dV8amg==} + engines: {node: '>=18'} + + cspell-lib@8.19.4: + resolution: {integrity: sha512-NwfdCCYtIBNQuZcoMlMmL3HSv2olXNErMi/aOTI9BBAjvCHjhgX5hbHySMZ0NFNynnN+Mlbu5kooJ5asZeB3KA==} + engines: {node: '>=18'} + + cspell-trie-lib@8.19.4: + resolution: {integrity: sha512-yIPlmGSP3tT3j8Nmu+7CNpkPh/gBO2ovdnqNmZV+LNtQmVxqFd2fH7XvR1TKjQyctSH1ip0P5uIdJmzY1uhaYg==} + engines: {node: '>=18'} + + cspell@8.19.4: + resolution: {integrity: sha512-toaLrLj3usWY0Bvdi661zMmpKW2DVLAG3tcwkAv4JBTisdIRn15kN/qZDrhSieUEhVgJgZJDH4UKRiq29mIFxA==} + engines: {node: '>=18'} + hasBin: true + + css-loader@7.1.4: + resolution: {integrity: sha512-vv3J9tlOl04WjiMvHQI/9tmIrCxVrj6PFbHemBB1iihpeRbi/I4h033eoFIhwxBBqLhI0KYFS7yvynBFhIZfTw==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': 0.x || ^1.0.0 || ^2.0.0-0 + webpack: ^5.27.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + + css-what@6.2.2: + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + cssstyle@4.6.0: + resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} + engines: {node: '>=18'} + + ctph.js@0.0.5: + resolution: {integrity: sha512-xcgQ6zzamT6ESHBhFPZHjkcpjzv4rtWw9GLoeNwvQwQQdXNR49xKBF5/Nt1oLsE3X1JM8QHktbGknp5cH20PTA==} + + cycle@1.0.3: + resolution: {integrity: sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==} + engines: {node: '>=0.4.0'} + + d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + + d3-axis@3.0.0: + resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} + engines: {node: '>=12'} + + d3-brush@3.0.0: + resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} + engines: {node: '>=12'} + + d3-chord@3.0.1: + resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} + engines: {node: '>=12'} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-contour@4.0.2: + resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} + engines: {node: '>=12'} + + d3-delaunay@6.0.4: + resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} + engines: {node: '>=12'} + + d3-dispatch@3.0.1: + resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} + engines: {node: '>=12'} + + d3-drag@3.0.0: + resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} + engines: {node: '>=12'} + + d3-dsv@3.0.1: + resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} + engines: {node: '>=12'} + hasBin: true + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-fetch@3.0.1: + resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} + engines: {node: '>=12'} + + d3-force@3.0.0: + resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} + engines: {node: '>=12'} + + d3-format@3.1.2: + resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==} + engines: {node: '>=12'} + + d3-geo@3.1.1: + resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} + engines: {node: '>=12'} + + d3-hexbin@0.2.2: + resolution: {integrity: sha512-KS3fUT2ReD4RlGCjvCEm1RgMtp2NFZumdMu4DBzQK8AZv3fXRM6Xm8I4fSU07UXvH4xxg03NwWKWdvxfS/yc4w==} + + d3-hierarchy@3.1.2: + resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + + d3-polygon@3.0.1: + resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} + engines: {node: '>=12'} + + d3-quadtree@3.0.1: + resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} + engines: {node: '>=12'} + + d3-random@3.0.1: + resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} + engines: {node: '>=12'} + + d3-scale-chromatic@3.1.0: + resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} + engines: {node: '>=12'} + + d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + + d3-selection@3.0.0: + resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} + engines: {node: '>=12'} + + d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + + d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + + d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + d3-transition@3.0.1: + resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} + engines: {node: '>=12'} + peerDependencies: + d3-selection: 2 - 3 + + d3-zoom@3.0.0: + resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} + engines: {node: '>=12'} + + d3@7.9.0: + resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} + engines: {node: '>=12'} + + data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + + dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + + debounce@1.2.1: + resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.1: + resolution: {integrity: sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@4.0.0: + resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} + engines: {node: '>=10'} + + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + + deep-eql@4.0.1: + resolution: {integrity: sha512-D/Oxqobjr+kxaHsgiQBZq9b6iAWdEj5W/JdJm8deNduAPc9CwXQ3BJJCuEqlrPXcy45iOMkGPZ0T81Dnz7UDCA==} + engines: {node: '>=6'} + + deep-equal@1.1.2: + resolution: {integrity: sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==} + engines: {node: '>= 0.4'} + + deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + + deep-for-each@3.0.0: + resolution: {integrity: sha512-pPN+0f8jlnNP+z90qqOdxGghJU5XM6oBDhvAR+qdQzjCg5pk/7VPPvKK1GqoXEFkHza6ZS+Otzzvmr0g3VUaKw==} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + default-browser-id@5.0.1: + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} + engines: {node: '>=18'} + + default-browser@5.5.0: + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + engines: {node: '>=18'} + + default-gateway@6.0.3: + resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} + engines: {node: '>= 10'} + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + + delaunator@5.1.0: + resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + des.js@1.1.0: + resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-file@1.0.0: + resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} + engines: {node: '>=0.10.0'} + + detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + + devtools-protocol@0.0.1140464: + resolution: {integrity: sha512-I1jXnjpQh/6TBFyQ0A9dB2kXXk6DprpPFZoI8pUsxHtlNuOTQEdv9fUqYBsFtf8tOJCbdsZZyQrWeXu6GfK+Bw==} + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + diff@5.2.2: + resolution: {integrity: sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==} + engines: {node: '>=0.3.1'} + + diffie-hellman@5.0.3: + resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} + + dns-packet@5.6.1: + resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} + engines: {node: '>=6'} + + dom-converter@0.2.0: + resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} + + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + + dompurify@3.3.3: + resolution: {integrity: sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + + dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + + dotenv@16.3.1: + resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + + duplexify@3.7.1: + resolution: {integrity: sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-to-chromium@1.5.328: + resolution: {integrity: sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w==} + + elliptic@6.6.1: + resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + enhanced-resolve@5.20.1: + resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==} + engines: {node: '>=10.13.0'} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + env-paths@3.0.0: + resolution: {integrity: sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + envinfo@7.11.0: + resolution: {integrity: sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==} + engines: {node: '>=4'} + hasBin: true + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + error@7.2.1: + resolution: {integrity: sha512-fo9HBvWnx3NGUKMvMwB/CBCMMrfEJgbDTVDEkPygA3Bdd3lM1OyCd+rbQ8BwnpF6GdVeOLDNmyL4N5Bg80ZvdA==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + es-module-lexer@2.0.0: + resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es6-object-assign@1.1.0: + resolution: {integrity: sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw==} + + es6-polyfills@2.0.0: + resolution: {integrity: sha512-daIt/MHqdYmxnuo5KcwAU9EqSxvaDRyajYOUU9fy+CLuU5+RFhpNCnL3oPsq7n+g673F3z/Vb+FXo/EmQjlkbw==} + deprecated: Use @natlibfi/es6-polyfills instead + + es6-promise-polyfill@1.2.0: + resolution: {integrity: sha512-HHb0vydCpoclpd0ySPkRXMmBw80MRt1wM4RBJBlXkux97K7gleabZdsR0gvE1nNPM9mgOZIBTzjjXiPxf4lIqQ==} + + es6-promisify@7.0.0: + resolution: {integrity: sha512-ginqzK3J90Rd4/Yz7qRrqUeIpe3TwSXTPPZtPne7tGBPeAaQiU8qt4fpKApnxHcq1AwtUdHVg5P77x/yrggG8Q==} + engines: {node: '>=6'} + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + eslint-plugin-jsdoc@48.11.0: + resolution: {integrity: sha512-d12JHJDPNo7IFwTOAItCeJY1hcqoIxE0lHA8infQByLilQ9xkqrRa6laWCnsuCrf+8rUnvxXY1XuTbibRBNylA==} + engines: {node: '>=18'} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.39.4: + resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.7.0: + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + eventemitter2@0.4.14: + resolution: {integrity: sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + exif-parser@0.1.12: + resolution: {integrity: sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==} + + exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + + expand-tilde@2.0.2: + resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} + engines: {node: '>=0.10.0'} + + express@4.22.1: + resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} + engines: {node: '>= 0.10.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + + eyes@0.1.8: + resolution: {integrity: sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==} + engines: {node: '> 0.1.90'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-equals@5.4.0: + resolution: {integrity: sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==} + engines: {node: '>=6.0.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + + faye-websocket@0.10.0: + resolution: {integrity: sha512-Xhj93RXbMSq8urNCUq4p9l0P6hnySJ/7YNRhYNug0bLOuii7pKO7xQFb5mx9xZXWCar88pLPb805PvUkwrLZpQ==} + engines: {node: '>=0.4.0'} + + faye-websocket@0.11.4: + resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} + engines: {node: '>=0.8.0'} + + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fernet@0.3.3: + resolution: {integrity: sha512-DvvqouVhv3VCor83wkQbSycekYUKDRQ1IKqcInaF5n5BSKgWBVfYLbSf7RRxojwQO0DZySiz5MlM2vO4MG3SUg==} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + file-entry-cache@9.1.0: + resolution: {integrity: sha512-/pqPFG+FdxWQj+/WSuzXSDaNzxgTLr/OrR1QuqfEZzDakpdYE70PwUxL7BPUa8hpjbvY1+qvCl8k+8Tq34xJgg==} + engines: {node: '>=18'} + + file-saver@2.0.5: + resolution: {integrity: sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==} + + file-sync-cmp@0.1.1: + resolution: {integrity: sha512-0k45oWBokCqh2MOexeYKpyqmGKG+8mQ2Wd8iawx+uWd/weWJQAZ6SoPybagdCI4xFisag8iAR77WPm4h3pTfxA==} + + file-type@16.5.4: + resolution: {integrity: sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==} + engines: {node: '>=10'} + + filelist@1.0.6: + resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@1.1.2: + resolution: {integrity: sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==} + engines: {node: '>= 0.8'} + + finalhandler@1.3.2: + resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} + engines: {node: '>= 0.8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + findup-sync@4.0.0: + resolution: {integrity: sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==} + engines: {node: '>= 8'} + + findup-sync@5.0.0: + resolution: {integrity: sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==} + engines: {node: '>= 10.13.0'} + + fined@1.2.0: + resolution: {integrity: sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==} + engines: {node: '>= 0.10'} + + flagged-respawn@1.0.1: + resolution: {integrity: sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==} + engines: {node: '>= 0.10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flat-cache@5.0.0: + resolution: {integrity: sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==} + engines: {node: '>=18'} + + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + + flat@6.0.1: + resolution: {integrity: sha512-/3FfIa8mbrg3xE7+wAhWeV+bd7L2Mof+xtZb5dRDKZ+wDvYJK4WDYeIOuOhre5Yv5aQObZrlbRmk3RTSiuQBtw==} + engines: {node: '>=18'} + hasBin: true + + flatted@3.4.2: + resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} + + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + for-in@1.0.2: + resolution: {integrity: sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==} + engines: {node: '>=0.10.0'} + + for-own@1.0.0: + resolution: {integrity: sha512-0OABksIGrxKK8K4kynWkQ7y1zounQxP+CWnyclVwj81KW3vlLlGUx57DKGcP/LH216GzqnstnPocF16Nxs0Ycg==} + engines: {node: '>=0.10.0'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fraction.js@5.3.4: + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + gamma@1.0.0: + resolution: {integrity: sha512-bPI4QJKNe/PfuO6PZU7ckMkBk0wEe3iQWx3DadEp5ceiAkJwc8CRukwncOZ5Hk5rc6nNTbIfByZKGz7Vv+xXdw==} + + gaze@1.1.3: + resolution: {integrity: sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==} + engines: {node: '>= 4.0.0'} + + generator-function@2.0.1: + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} + + gensequence@7.0.0: + resolution: {integrity: sha512-47Frx13aZh01afHJTB3zTtKIlFI6vWY+MYCN9Qpew6i52rfKjnhCF/l1YlC8UmEMvvntZZ6z4PiCcmyuedR2aQ==} + engines: {node: '>=18'} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + geodesy@1.1.3: + resolution: {integrity: sha512-H/0XSd1KjKZGZ2YGZcOYzRyY/foYAawwTEumNSo+YUwf+u5d4CfvBRg2i2Qimrx9yUEjWR8hLvMnhghuVFN0Zg==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-uri@6.0.5: + resolution: {integrity: sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==} + engines: {node: '>= 14'} + + getobject@1.0.2: + resolution: {integrity: sha512-2zblDBaFcb3rB4rF77XVnuINOE2h2k/OnqXAiy0IrTxUfV1iFp3la33oAQVY9pCpWU268WFYVt2t71hlMuLsOg==} + engines: {node: '>=10'} + + gifwrap@0.10.1: + resolution: {integrity: sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob-to-regex.js@1.2.0: + resolution: {integrity: sha512-QMwlOQKU/IzqMUOAZWubUOT8Qft+Y0KQWnX9nK3ch0CJg0tTp4TvGZsTfudYKv2NzoQSyPcnA6TYeIQ3jGichQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + glob@7.1.7: + resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + + global-modules@1.0.0: + resolution: {integrity: sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==} + engines: {node: '>=0.10.0'} + + global-prefix@1.0.2: + resolution: {integrity: sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==} + engines: {node: '>=0.10.0'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@15.15.0: + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} + engines: {node: '>=18'} + + globals@9.18.0: + resolution: {integrity: sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==} + engines: {node: '>=0.10.0'} + + globule@1.3.4: + resolution: {integrity: sha512-OPTIfhMBh7JbBYDpa5b+Q5ptmMWKwcNcFSR/0c6t8V4f3ZAVBEsKNY37QdVqmLRYSMhOUGYrY0QhSoEpzGr/Eg==} + engines: {node: '>= 0.10'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + grunt-chmod@1.1.1: + resolution: {integrity: sha512-f807W/VOIhhaOW85JyeRd4DgB0RcbsGQV/4IvtcKctOWGvPJns4AqN7xW73PG9+RwDnSGxApS+6Xov5L2LeNXg==} + engines: {node: '>= 0.8.0'} + + grunt-cli@1.4.3: + resolution: {integrity: sha512-9Dtx/AhVeB4LYzsViCjUQkd0Kw0McN2gYpdmGYKtE2a5Yt7v1Q+HYZVWhqXc/kGnxlMtqKDxSwotiGeFmkrCoQ==} + engines: {node: '>=10'} + hasBin: true + + grunt-concurrent@3.0.0: + resolution: {integrity: sha512-AgXtjUJESHEGeGX8neL3nmXBTHSj1QC48ABQ3ng2/vjuSBpDD8gKcVHSlXP71pFkIR8TQHf+eomOx6OSYSgfrA==} + engines: {node: '>=8'} + peerDependencies: + grunt: '>=1' + + grunt-contrib-clean@2.0.1: + resolution: {integrity: sha512-uRvnXfhiZt8akb/ZRDHJpQQtkkVkqc/opWO4Po/9ehC2hPxgptB9S6JHDC/Nxswo4CJSM0iFPT/Iym3cEMWzKA==} + engines: {node: '>=12'} + peerDependencies: + grunt: '>=0.4.5' + + grunt-contrib-connect@5.0.1: + resolution: {integrity: sha512-Hfq/0QJl3ddD2N/a/1cDJHkKEOGk6m7W6uxNe0AmYwtf6v0F/4+8q9rvPJ1tl+mrI90lU/89I9T/h48qqeMfQA==} + engines: {node: '>=16'} + + grunt-contrib-copy@1.0.0: + resolution: {integrity: sha512-gFRFUB0ZbLcjKb67Magz1yOHGBkyU6uL29hiEW1tdQ9gQt72NuMKIy/kS6dsCbV0cZ0maNCb0s6y+uT1FKU7jA==} + engines: {node: '>=0.10.0'} + + grunt-contrib-watch@1.1.0: + resolution: {integrity: sha512-yGweN+0DW5yM+oo58fRu/XIRrPcn3r4tQx+nL7eMRwjpvk+rQY6R8o94BPK0i2UhTg9FN21hS+m8vR8v9vXfeg==} + engines: {node: '>=0.10.0'} + + grunt-eslint@25.0.0: + resolution: {integrity: sha512-JIV5IPgOuacorFLmYtUTq0n+0qGIL9FSQJ4KVnNfCg/8Fm+K1t6OWrzXXI8TxWTwq2K9E3parFVXCpn1sGLbKQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + grunt: '>=1' + + grunt-exec@3.0.0: + resolution: {integrity: sha512-cgAlreXf3muSYS5LzW0Cc4xHK03BjFOYk0MqCQ/MZ3k1Xz2GU7D+IAJg4UKicxpO+XdONJdx/NJ6kpy2wI+uHg==} + engines: {node: '>=0.8.0'} + peerDependencies: + grunt: '>=0.4' + + grunt-known-options@2.0.0: + resolution: {integrity: sha512-GD7cTz0I4SAede1/+pAbmJRG44zFLPipVtdL9o3vqx9IEyb7b4/Y3s7r6ofI3CchR5GvYJ+8buCSioDv5dQLiA==} + engines: {node: '>=0.10.0'} + + grunt-legacy-log-utils@2.1.0: + resolution: {integrity: sha512-lwquaPXJtKQk0rUM1IQAop5noEpwFqOXasVoedLeNzaibf/OPWjKYvvdqnEHNmU+0T0CaReAXIbGo747ZD+Aaw==} + engines: {node: '>=10'} + + grunt-legacy-log@3.0.0: + resolution: {integrity: sha512-GHZQzZmhyq0u3hr7aHW4qUH0xDzwp2YXldLPZTCjlOeGscAOWWPftZG3XioW8MasGp+OBRIu39LFx14SLjXRcA==} + engines: {node: '>= 0.10.0'} + + grunt-legacy-util@2.0.1: + resolution: {integrity: sha512-2bQiD4fzXqX8rhNdXkAywCadeqiPiay0oQny77wA2F3WF4grPJXCvAcyoWUJV+po/b15glGkxuSiQCK299UC2w==} + engines: {node: '>=10'} + + grunt-retro@0.6.4: + resolution: {integrity: sha512-kqnvNUAngOhkDckEQPYFDqNcRlculVp/Sy+gCe4ey7utM4BCaENVf2JfDeK488mj/0cgmAZyXwpW6w9l1OAxMg==} + engines: {node: '>= 0.8.0'} + + grunt-webpack@6.0.0: + resolution: {integrity: sha512-FtRVTGJGuV9Ic/OrCR80p5u601e0ekvTyHo7vnwVo3XlvRh5wR1ATAVT9FnnobHqZnQ/DeF84W97si5+roUWEA==} + engines: {node: '>=16.13.0'} + peerDependencies: + webpack: ^5.0.0 + + grunt-zip@1.0.0: + resolution: {integrity: sha512-e5HOzf+BLFR6rXM67oGrFcVgfVbLDPBnv29YdWTupthwNg/1y91B0xXx667E6dKin8YvrwDShtQy48D1NRzn7g==} + engines: {node: '>= 8.0.0'} + hasBin: true + + grunt@1.6.1: + resolution: {integrity: sha512-/ABUy3gYWu5iBmrUSRBP97JLpQUm0GgVveDCp6t3yRNIoltIYw7rEj3g5y1o2PGPR2vfTRGa7WC/LZHLTXnEzA==} + engines: {node: '>=16'} + hasBin: true + + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + + handle-thing@2.0.1: + resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} + + handlebars@4.7.9: + resolution: {integrity: sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + has-ansi@2.0.0: + resolution: {integrity: sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==} + engines: {node: '>=0.10.0'} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hash-base@3.0.5: + resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} + engines: {node: '>= 0.10'} + + hash-base@3.1.2: + resolution: {integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==} + engines: {node: '>= 0.8'} + + hash-wasm@4.12.0: + resolution: {integrity: sha512-+/2B2rYLb48I/evdOIhP+K/DD2ca2fgBjp6O+GBEnCDk2e4rpeXIK8GvIyRPjTezgmWn9gmKwkQjjx6BtqDHVQ==} + + hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + highlight.js@11.11.1: + resolution: {integrity: sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==} + engines: {node: '>=12.0.0'} + + hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + + homedir-polyfill@1.0.3: + resolution: {integrity: sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==} + engines: {node: '>=0.10.0'} + + hooker@0.2.3: + resolution: {integrity: sha512-t+UerCsQviSymAInD01Pw+Dn/usmz1sRO+3Zk1+lx8eg+WKpD2ulcwWqHHL0+aseRBr+3+vIhiG1K1JTwaIcTA==} + + hpack.js@2.1.6: + resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} + + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + + html-entities@2.6.0: + resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + html-minifier-terser@6.1.0: + resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} + engines: {node: '>=12'} + hasBin: true + + html-webpack-plugin@5.6.6: + resolution: {integrity: sha512-bLjW01UTrvoWTJQL5LsMRo1SypHW80FTm12OJRSnr3v6YHNhfe+1r0MYUZJMACxnCHURVnBWRwAsWs2yPU9Ezw==} + engines: {node: '>=10.13.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + webpack: ^5.20.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + htmlparser2@6.1.0: + resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} + + http-deceiver@1.2.7: + resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} + + http-errors@1.8.1: + resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} + engines: {node: '>= 0.6'} + + http-errors@2.0.1: + resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} + engines: {node: '>= 0.8'} + + http-parser-js@0.5.10: + resolution: {integrity: sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + http-proxy-middleware@2.0.9: + resolution: {integrity: sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + + http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + + http2-wrapper@2.2.1: + resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} + engines: {node: '>=10.19.0'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + hyperdyperid@1.2.0: + resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} + engines: {node: '>=10.18'} + + iced-error@0.0.13: + resolution: {integrity: sha512-yEEaG8QfyyRL0SsbNNDw3rVgTyqwHFMCuV6jDvD43f/2shmdaFXkqvFLGhDlsYNSolzYHwVLM/CrXt9GygYopA==} + + iced-lock@1.1.0: + resolution: {integrity: sha512-J9UMVitgTMYrkUil5EB9/Q4BPWiMpFH156yjDlmMoMRKs3s3PnXj/6G0UlzIOGnNi5JVNk/zVYLXVnuo+1QnqQ==} + + iced-runtime@1.0.4: + resolution: {integrity: sha512-rgiJXNF6ZgF2Clh/TKUlBDW3q51YPDJUXmxGQXx1b8tbZpVpTn+1RX9q1sjNkujXIIaVxZByQzPHHORg7KV51g==} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + icss-utils@5.1.0: + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + idb-keyval@6.2.2: + resolution: {integrity: sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + image-q@4.0.0: + resolution: {integrity: sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==} + + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-meta-resolve@4.2.0: + resolution: {integrity: sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==} + + imports-loader@5.0.0: + resolution: {integrity: sha512-tXgL8xxZFjOjQLLiE7my00UUQfktg4G8fdpXcZphL0bJWbk9eCxKKFaCwmFRcwyRJQl95GXBL1DoE1rCS/tcPw==} + engines: {node: '>= 18.12.0'} + peerDependencies: + webpack: ^5.0.0 + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + + interpret@1.1.0: + resolution: {integrity: sha512-CLM8SNMDu7C5psFCn6Wg/tgpj/bKAg7hc2gWqcuR9OD5Ft9PhBpIu8PLicPeis+xDd6YX2ncI8MCA64I9tftIA==} + + invariant@2.2.4: + resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + + ip-address@10.1.0: + resolution: {integrity: sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==} + engines: {node: '>= 12'} + + ip-regex@4.3.0: + resolution: {integrity: sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==} + engines: {node: '>=8'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + ipaddr.js@2.3.0: + resolution: {integrity: sha512-Zv/pA+ciVFbCSBBjGfaKUya/CcGmUHzTydLMaTwrUUEM2DIEO3iZvueGxmacvmN50fGpGVKeTXpb2LcYQxeVdg==} + engines: {node: '>= 10'} + + is-absolute@1.0.0: + resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==} + engines: {node: '>=0.10.0'} + + is-arguments@1.2.0: + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-electron@2.2.2: + resolution: {integrity: sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg==} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-function@1.1.2: + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-nan@1.3.2: + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} + + is-network-error@1.3.1: + resolution: {integrity: sha512-6QCxa49rQbmUWLfk0nuGqzql9U8uaV2H6279bRErPBHe/109hCzsLUBUHfbEtvLIHBd6hyXbgedBSHevm43Edw==} + engines: {node: '>=16'} + + is-number-like@1.0.8: + resolution: {integrity: sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + + is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + + is-plain-object@2.0.4: + resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} + engines: {node: '>=0.10.0'} + + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-relative@1.0.0: + resolution: {integrity: sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==} + engines: {node: '>=0.10.0'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-unc-path@1.0.0: + resolution: {integrity: sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==} + engines: {node: '>=0.10.0'} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + is-url@1.2.4: + resolution: {integrity: sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} + + is2@2.0.9: + resolution: {integrity: sha512-rZkHeBn9Zzq52sd9IUIV3a5mfwBY+o2HePMh0wkGBM4z4qjvy2GwVxQ6nNXSfw6MmVP6gf1QIlWjiOavhM3x5g==} + engines: {node: '>=v0.10.0'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + isobject@3.0.1: + resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} + engines: {node: '>=0.10.0'} + + isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jake@10.9.4: + resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} + engines: {node: '>=10'} + hasBin: true + + jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + + jimp@1.6.0: + resolution: {integrity: sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg==} + engines: {node: '>=18'} + + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + + jpeg-js@0.4.4: + resolution: {integrity: sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==} + + jq-web@0.6.2: + resolution: {integrity: sha512-+7XvjBYwTx4vP5PYkf6Q6orubO/v+UgMU6By1GritrmShr9QpT3UKa4ANzXWQfhdqtBnQYXsm7ZNbdIHT6tYpQ==} + + jquery@3.7.1: + resolution: {integrity: sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==} + + js-sha3@0.9.3: + resolution: {integrity: sha512-BcJPCQeLg6WjEx3FE591wVAevlli8lxsxm9/FzV4HXkV49TmBH38Yvrpce6fjbADGMKFrBMGTqrVz3qPIZ88Gg==} + + js-tokens@3.0.2: + resolution: {integrity: sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.2: + resolution: {integrity: sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==} + hasBin: true + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsdoc-type-pratt-parser@4.0.0: + resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} + engines: {node: '>=12.0.0'} + + jsdom@24.1.3: + resolution: {integrity: sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^2.11.2 + peerDependenciesMeta: + canvas: + optional: true + + jsep@1.4.0: + resolution: {integrity: sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==} + engines: {node: '>= 10.16.0'} + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonata@2.1.0: + resolution: {integrity: sha512-OCzaRMK8HobtX8fp37uIVmL8CY1IGc/a6gLsDqz3quExFR09/U78HUzWYr7T31UEB6+Eu0/8dkVD5fFDOl9a8w==} + engines: {node: '>= 8'} + + jsonpath-plus@10.4.0: + resolution: {integrity: sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA==} + engines: {node: '>=18.0.0'} + hasBin: true + + jsonwebtoken@8.5.1: + resolution: {integrity: sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==} + engines: {node: '>=4', npm: '>=1.4.28'} + + jsqr@1.4.0: + resolution: {integrity: sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A==} + + jsrsasign@11.1.1: + resolution: {integrity: sha512-6w95OOXH8DNeGxakqLndBEqqwQ6A70zGaky1oxfg8WVLWOnghTfJsc5Tknx+Z88MHSb1bGLcqQHImOF8Lk22XA==} + + jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + + jwa@1.4.2: + resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==} + + jws@3.2.3: + resolution: {integrity: sha512-byiJ0FLRdLdSVSReO/U4E7RoEyOCKnEnEPMjq3HxWtvzLsV08/i5RQKsFVNkCldrCaPr2vDNAOMsfs8T/Hze7g==} + + kbpgp@2.1.17: + resolution: {integrity: sha512-pnjH7amyg6dZLXyF42BKbCTST0l0r1ErunqtFRrJCkHkGJb83cZZmx1pnqNFr+d/ls+5gvcHrZLPfUG5q7oRYw==} + + keybase-ecurve@1.0.1: + resolution: {integrity: sha512-2GlVxDsNF+52LtYjgFsjoKuN7MQQgiVeR4HRdJxLuN8fm4mf4stGKPUjDJjky15c/98UsZseLjp7Ih5X0Sy1jQ==} + + keybase-nacl@1.1.4: + resolution: {integrity: sha512-7TFyWLq42CQs7JES9arR+Vnv/eMk5D6JT1Y8samrEA5ff3FOmaiRcXIVrwJQd3KJduxmSjgAjdkXlQK7Q437xQ==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + launch-editor@2.13.2: + resolution: {integrity: sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg==} + + lazystream@1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + libbzip2-wasm@0.0.4: + resolution: {integrity: sha512-RqscTx95+RTKhFAyjedsboR0Lmo3zd8//EuRwQXkdWmsCwYlzarVRaiYg6kS1O8m10MCQkGdrnlK9L4eAmZUwA==} + + libyara-wasm@1.2.1: + resolution: {integrity: sha512-PNqUNWnwjZLe55iA8Rv6vLQRjSdO2OnVg24aRE8v+ytR8CRB8agIG6pS9h2VQejuJP1A/uR4pwcBggUxoNC7DA==} + + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + + liftup@3.0.1: + resolution: {integrity: sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==} + engines: {node: '>=10'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + + livereload-js@2.4.0: + resolution: {integrity: sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw==} + + loader-runner@4.3.1: + resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==} + engines: {node: '>=6.11.5'} + + loader-utils@2.0.4: + resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} + engines: {node: '>=8.9.0'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.difference@4.5.0: + resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} + + lodash.flatten@4.4.0: + resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + + lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + + lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + + lodash.isfinite@3.3.2: + resolution: {integrity: sha512-7FGG40uhC8Mm633uKW1r58aElFlBlxCrg9JfSi3P6aYiWmfiWF0PgMd86ZUsxE5GwWPdHoS2+48bwTh2VPkIQA==} + + lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + + lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + + lodash.union@4.6.0: + resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} + + lodash@4.17.23: + resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + loglevel-message-prefix@3.0.0: + resolution: {integrity: sha512-/cBEOqsuU0vJsFm4n92R7h6mkiKqt8vh+JOmW722DTZVVD7egEpVOx66re3vWxO7pii3B4eQuqm2qfqq5cAs0w==} + deprecated: Use @natlibfi/loglevel-message-prefix instead + + loglevel@1.9.2: + resolution: {integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==} + engines: {node: '>= 0.6.0'} + + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + lz4js@0.2.0: + resolution: {integrity: sha512-gY2Ia9Lm7Ep8qMiuGRhvUq0Q7qUereeldZPP1PMEJxPtEWHJLqw9pgX68oHajBH0nzJK4MaZEA/YNV3jT8u8Bg==} + + make-iterator@1.0.1: + resolution: {integrity: sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==} + engines: {node: '>=0.10.0'} + + map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + + markdown-it@14.1.1: + resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==} + hasBin: true + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + memfs@4.57.1: + resolution: {integrity: sha512-WvzrWPwMQT+PtbX2Et64R4qXKK0fj/8pO85MrUCzymX3twwCiJCdvntW3HdhG1teLJcHDDLIKx5+c3HckWYZtQ==} + peerDependencies: + tslib: '2' + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + miller-rabin@4.0.1: + resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} + hasBin: true + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.54.0: + resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime-types@3.0.2: + resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} + engines: {node: '>=18'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mime@3.0.0: + resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} + engines: {node: '>=10.0.0'} + hasBin: true + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + mini-css-extract-plugin@2.10.0: + resolution: {integrity: sha512-540P2c5dYnJlyJxTaSloliZexv8rji6rY8FhQN+WF/82iHQfA23j/xtJx97L+mXOML27EqksSek/g4eK7jaL3g==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + + minimatch@3.0.8: + resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@3.1.5: + resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + + minimatch@5.1.9: + resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} + engines: {node: '>=10'} + + minimatch@9.0.9: + resolution: {integrity: sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.6: + resolution: {integrity: sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + mocha@10.8.2: + resolution: {integrity: sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==} + engines: {node: '>= 14.0.0'} + hasBin: true + + modify-source-webpack-plugin@4.1.0: + resolution: {integrity: sha512-UaLQyFXoPWpWxkNUBFo9BotC20CCAGe7HEX9iKtB0P0MgNXgURf9TXUgNGuY5iVV5lDDQtcMjT2vneQWnNmwEw==} + peerDependencies: + webpack: ^4.37.0 || ^5.0.0 + + moment-timezone@0.6.1: + resolution: {integrity: sha512-1B9lmAhB9D9/sHaPC1N7wLFEVUoFldxOpOO96lOD1PvJ43vCd0ozDPbu0FEL3++VvawOlDkq8YD373tJmP5JHw==} + + moment@2.30.1: + resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + + more-entropy@0.0.7: + resolution: {integrity: sha512-e0TxQtU1F6/ZA8WnEA2JLQwwDqBTtZFLJSW7rWgUsQou35wx1IOL0g2O7q7oGoMgIJto+jHMnNGHLfSiylHRrw==} + + morgan@1.10.1: + resolution: {integrity: sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==} + engines: {node: '>= 0.8.0'} + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + multicast-dns@7.2.5: + resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} + hasBin: true + + mute-stream@0.0.8: + resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + + ngeohash@0.6.3: + resolution: {integrity: sha512-kltF0cOxgx1AbmVzKxYZaoB0aj7mOxZeHaerEtQV0YaqnkXNq26WWqMmJ6lTqShYxVRWZ/mwvvTrNeOwdslWiw==} + engines: {node: '>=v0.2.0'} + + nightwatch-axe-verbose@2.5.1: + resolution: {integrity: sha512-vvLUMyIbGHB8CA5XEGfliPstNCplcHeMn/CWi4cyg0CWMqWypGrV2IgP+WmiWpUgs0qvPmqVHeRHf0BTT7Ez2Q==} + + nightwatch@3.15.0: + resolution: {integrity: sha512-Vvh7TsDyEN1YzOsDNoafEUPJDQ6jfnmJPAsWo/EmygljZiRk1Ja/pEqNAhE5UdYJzF38SNO46gJS8IRk9mUNfA==} + engines: {node: '>= 16'} + hasBin: true + peerDependencies: + '@cucumber/cucumber': '*' + chromedriver: '*' + geckodriver: '*' + peerDependenciesMeta: + '@cucumber/cucumber': + optional: true + chromedriver: + optional: true + geckodriver: + optional: true + + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-forge@1.4.0: + resolution: {integrity: sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==} + engines: {node: '>= 6.13.0'} + + node-md6@0.1.0: + resolution: {integrity: sha512-n+s6dhxfV2JCRFgNGzdX0SxxL/SyUwR68uGR/rlNVbXhrdti4M1xKHO+PzXtYLUo1DEsWFZe29B3Z9y5JgpfvA==} + + node-releases@2.0.36: + resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} + + nodom@2.4.0: + resolution: {integrity: sha512-qhfYgpoCSi37HLiViMlf94YqMQdvk3n3arI1uGbAWZK9NKCYRSI42W8lATeGloYGLYxb8us1C5rTvtsXjwdWQg==} + + nofilter@3.1.0: + resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} + engines: {node: '>=12.19'} + + nopt@3.0.6: + resolution: {integrity: sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==} + hasBin: true + + nopt@4.0.3: + resolution: {integrity: sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + notepack.io@3.0.1: + resolution: {integrity: sha512-TKC/8zH5pXIAMVQio2TvVDTtPRX+DJPHDqjRbxogtFiByHyzKmy96RA0JtCQJ+WouyyL4A10xomQzgbUT+1jCg==} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + ntlm@0.1.3: + resolution: {integrity: sha512-pPlHxhAegZP4QAaOYd51vRd6VXTGfF7VLKJwuwN0iEB1aIi3SnqXYuS/bH/6wWBOq+Ehdil49mHm1Nseon085w==} + engines: {'0': node} + + nwmatcher@1.4.4: + resolution: {integrity: sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==} + + nwsapi@2.2.23: + resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.defaults@1.1.0: + resolution: {integrity: sha512-c/K0mw/F11k4dEUBMW8naXUuBuhxRCfG7W+yFy8EcijU/rSmazOUd1XAEEe6bC0OuXY4HUKjTJv7xbxIMqdxrA==} + engines: {node: '>=0.10.0'} + + object.map@1.0.1: + resolution: {integrity: sha512-3+mAJu2PLfnSVGHwIWubpOFLscJANBKuB/6A4CxBstc4aqwQY0FWcsppuy4jU5GSB95yES5JHSI+33AWuS4k6w==} + engines: {node: '>=0.10.0'} + + object.pick@1.3.0: + resolution: {integrity: sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==} + engines: {node: '>=0.10.0'} + + obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + + omggif@1.0.10: + resolution: {integrity: sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==} + + on-finished@2.3.0: + resolution: {integrity: sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==} + engines: {node: '>= 0.8'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + on-headers@1.1.0: + resolution: {integrity: sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + open@10.2.0: + resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} + engines: {node: '>=18'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + opencollective-postinstall@2.0.3: + resolution: {integrity: sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==} + hasBin: true + + opener@1.5.2: + resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} + hasBin: true + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + + os-homedir@1.0.2: + resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} + engines: {node: '>=0.10.0'} + + os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + + osenv@0.1.5: + resolution: {integrity: sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==} + deprecated: This package is no longer supported. + + otpauth@9.3.6: + resolution: {integrity: sha512-eIcCvuEvcAAPHxUKC9Q4uCe0Fh/yRc5jv9z+f/kvyIF2LPrhgAOuLB7J9CssGYhND/BL8M9hlHBTFmffpoQlMQ==} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-retry@6.2.1: + resolution: {integrity: sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==} + engines: {node: '>=16.17'} + + pac-proxy-agent@7.2.0: + resolution: {integrity: sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==} + engines: {node: '>= 14'} + + pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + pad-stream@2.0.0: + resolution: {integrity: sha512-3QeQw19K48BQzUGZ9dEf/slX5Jbfy5ZeBTma2XICketO7kFNK7omF00riVcecOKN+DSiJZcK2em1eYKaVOeXKg==} + engines: {node: '>=4'} + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + + param-case@3.0.4: + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parent-module@2.0.0: + resolution: {integrity: sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg==} + engines: {node: '>=8'} + + parse-asn1@5.1.9: + resolution: {integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==} + engines: {node: '>= 0.10'} + + parse-bmfont-ascii@1.0.6: + resolution: {integrity: sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==} + + parse-bmfont-binary@1.0.6: + resolution: {integrity: sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==} + + parse-bmfont-xml@1.1.6: + resolution: {integrity: sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==} + + parse-filepath@1.0.2: + resolution: {integrity: sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==} + engines: {node: '>=0.8'} + + parse-imports@2.2.1: + resolution: {integrity: sha512-OL/zLggRp8mFhKL0rNORUTR4yBYujK/uU+xZL+/0Rgm2QE4nLO9v8PzEweSJEbMGKmDRjJE4R3IMJlL2di4JeQ==} + engines: {node: '>= 18'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse-passwd@1.0.0: + resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} + engines: {node: '>=0.10.0'} + + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-root-regex@0.1.2: + resolution: {integrity: sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==} + engines: {node: '>=0.10.0'} + + path-root@0.1.1: + resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==} + engines: {node: '>=0.10.0'} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-to-regexp@0.1.13: + resolution: {integrity: sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==} + + path@0.12.7: + resolution: {integrity: sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==} + + pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + + pbkdf2@3.1.5: + resolution: {integrity: sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==} + engines: {node: '>= 0.10'} + + peek-readable@4.1.0: + resolution: {integrity: sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==} + engines: {node: '>=8'} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + pgp-utils@0.0.35: + resolution: {integrity: sha512-gCT6EbSTgljgycVa5qGpfRITaLOLbIKsEVRTdsNRgmLMAJpuJNNdrTn/95r8IWo9rFLlccfmGMJXkG9nVDwmrA==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + piscina@4.9.2: + resolution: {integrity: sha512-Fq0FERJWFEUpB4eSY59wSNwXD4RYqR+nR/WiEVcZW8IWfVBxJJafcgTEZDQo8k3w0sUarJ8RyVbbUF4GQ2LGbQ==} + + pixelmatch@5.3.0: + resolution: {integrity: sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==} + hasBin: true + + pngjs@6.0.0: + resolution: {integrity: sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==} + engines: {node: '>=12.13.0'} + + pngjs@7.0.0: + resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} + engines: {node: '>=14.19.0'} + + popper.js@1.16.1: + resolution: {integrity: sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==} + deprecated: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1 + + portscanner@2.2.0: + resolution: {integrity: sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==} + engines: {node: '>=0.4', npm: '>=1.0.0'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss-css-variables@0.19.0: + resolution: {integrity: sha512-Hr0WEYKLK9VCrY15anHXOd4RCvJy/xRvCnWdplGBeLInwEj6Z14hgzTb2W/39dYTCnS8hnHUfU4/F1zxX0IZuQ==} + peerDependencies: + postcss: ^8.2.6 + + postcss-import@16.1.1: + resolution: {integrity: sha512-2xVS1NCZAfjtVdvXiyegxzJ447GyqCeEI5V7ApgQVOWnros1p5lGNovJNapwPpMombyFBfqDwt7AD3n2l0KOfQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-loader@8.2.1: + resolution: {integrity: sha512-k98jtRzthjj3f76MYTs9JTpRqV1RaaMhEU0Lpw9OTmQZQdppg4B30VZ74BojuBHt3F4KyubHJoXCMUeM8Bqeow==} + engines: {node: '>= 18.12.0'} + peerDependencies: + '@rspack/core': 0.x || ^1.0.0 || ^2.0.0-0 + postcss: ^7.0.0 || ^8.0.1 + webpack: ^5.0.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + postcss-modules-extract-imports@3.1.0: + resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-local-by-default@4.2.0: + resolution: {integrity: sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-scope@3.2.1: + resolution: {integrity: sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-values@4.0.0: + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-selector-parser@7.1.1: + resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.8: + resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + pretty-error@4.0.0: + resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + + progress@1.1.8: + resolution: {integrity: sha512-UdA8mJ4weIkUBO224tIarHzuHs4HuYiJvsuGT7j/SPQiUJVjYvNDBIPa0hAorduOfjGohB/qHWRa/lrrWX/mXw==} + engines: {node: '>=0.4.0'} + + prompt@1.3.0: + resolution: {integrity: sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==} + engines: {node: '>= 6.0.0'} + + protobufjs@7.5.4: + resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} + engines: {node: '>=12.0.0'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + proxy-agent@6.5.0: + resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} + engines: {node: '>= 14'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + proxy-from-env@2.1.0: + resolution: {integrity: sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==} + engines: {node: '>=10'} + + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + + public-encrypt@4.0.3: + resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} + + pump@2.0.1: + resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + + pumpify@1.5.1: + resolution: {integrity: sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==} + + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + + punycode@1.4.1: + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + purepack@1.0.6: + resolution: {integrity: sha512-L/e3qq/3m/TrYtINo2aBB98oz6w8VHGyFy+arSKwPMZDUNNw2OaQxYnZO6UIZZw2OnRl2qkxGmuSOEfsuHXJdA==} + engines: {node: '>=0.10.0'} + + qr-image@3.2.0: + resolution: {integrity: sha512-rXKDS5Sx3YipVsqmlMJsJsk6jXylEpiHRC2+nJy66fxA5ExYyGa4PqwteW69SaVmAb2OQ18HbYriT7cGQMbduw==} + + qs@6.14.2: + resolution: {integrity: sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==} + engines: {node: '>=0.6'} + + qs@6.15.0: + resolution: {integrity: sha512-mAZTtNCeetKMH+pSjrb76NAM8V9a05I9aBZOHztWy/UqcJdQYNsf59vrRKWnojAT9Y+GbIvoTBC++CPHqpDBhQ==} + engines: {node: '>=0.6'} + + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + randomfill@1.0.4: + resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@1.1.7: + resolution: {integrity: sha512-WmJJU2e9Y6M5UzTOkHaM7xJGAPQD8PNzx3bAd2+uhZAim6wDk6dAZxPVYLF67XhbR4hmKGh33Lpmh4XWrCH5Mg==} + engines: {node: '>= 0.8.0'} + deprecated: No longer maintained. Please upgrade to a stable version. + + raw-body@2.5.3: + resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} + engines: {node: '>= 0.8'} + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + read@1.0.7: + resolution: {integrity: sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==} + engines: {node: '>=0.8'} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readable-stream@4.7.0: + resolution: {integrity: sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + readable-web-to-node-stream@3.0.4: + resolution: {integrity: sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==} + engines: {node: '>=8'} + + readdir-glob@1.1.3: + resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + rechoir@0.7.1: + resolution: {integrity: sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==} + engines: {node: '>= 0.10'} + + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + + regenerate-unicode-properties@10.2.2: + resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==} + engines: {node: '>=4'} + + regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + + regenerator-runtime@0.11.1: + resolution: {integrity: sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==} + + regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + regexpu-core@6.4.0: + resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} + engines: {node: '>=4'} + + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.13.0: + resolution: {integrity: sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==} + hasBin: true + + relateurl@0.2.7: + resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} + engines: {node: '>= 0.10'} + + renderkid@3.0.0: + resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + + resolve-dir@1.0.1: + resolution: {integrity: sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + revalidator@0.1.8: + resolution: {integrity: sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==} + engines: {node: '>= 0.4.0'} + + rimraf@2.7.1: + resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rimraf@5.0.10: + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} + hasBin: true + + ripemd160@2.0.3: + resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} + engines: {node: '>= 0.8'} + + rison@0.1.1: + resolution: {integrity: sha512-8C+/PKKTaAYE2quDtOUwny/eQpNn9YGby7T80wntbVWSGvw0aUT9M0YgLdLkUgIQzQwaB1ZTr80rwLVKyohHig==} + + robust-predicates@3.0.3: + resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==} + + rrweb-cssom@0.7.1: + resolution: {integrity: sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==} + + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + + run-applescript@7.1.0: + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} + + rw@1.3.3: + resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-json-parse@1.0.1: + resolution: {integrity: sha512-o0JmTu17WGUaUOHa1l0FPGXKBfijbxK6qoHzlkihsDXxzBHvJcA7zgviKR92Xs841rX9pK16unfphLq0/KqX7A==} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sax@1.6.0: + resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} + engines: {node: '>=11.0.0'} + + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + + schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + + schema-utils@4.3.3: + resolution: {integrity: sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==} + engines: {node: '>= 10.13.0'} + + scryptsy@2.1.0: + resolution: {integrity: sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w==} + + select-hose@2.0.0: + resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} + + selenium-webdriver@4.27.0: + resolution: {integrity: sha512-LkTJrNz5socxpPnWPODQ2bQ65eYx9JK+DQMYNihpTjMCqHwgWGYQnQTCAAche2W3ZP87alA+1zYPvgS8tHNzMQ==} + engines: {node: '>= 14.21.0'} + + selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + + semver@7.7.4: + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.2: + resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} + engines: {node: '>= 0.8.0'} + + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + + serve-index@1.9.2: + resolution: {integrity: sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==} + engines: {node: '>= 0.8.0'} + + serve-static@1.16.3: + resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} + engines: {node: '>= 0.8.0'} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + sha.js@2.4.12: + resolution: {integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==} + engines: {node: '>= 0.10'} + hasBin: true + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shell-quote@1.8.3: + resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} + engines: {node: '>= 0.4'} + + shelljs@0.5.3: + resolution: {integrity: sha512-C2FisSSW8S6TIYHHiMHN0NqzdjWfTekdMpA2FJTbRWnQMLO1RRIXEB9eVZYOlofYmjZA7fY3ChoFu09MeI3wlQ==} + engines: {node: '>=0.8.0'} + hasBin: true + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-xml-to-json@1.2.4: + resolution: {integrity: sha512-3MY16e0ocMHL7N1ufpdObURGyX+lCo0T/A+y6VCwosLdH1HSda4QZl1Sdt/O+2qWp48WFi26XEp5rF0LoaL0Dg==} + engines: {node: '>=20.12.2'} + + sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + + sitemap@8.0.3: + resolution: {integrity: sha512-9Ew1tR2WYw8RGE2XLy7GjkusvYXy8Rg6y8TYuBuQMfIEdGcWoJpY2Wr5DzsEiL/TKCw56+YKTCCUHglorEYK+A==} + engines: {node: '>=14.0.0', npm: '>=6.0.0'} + hasBin: true + + slashes@3.0.12: + resolution: {integrity: sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==} + + smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + + snackbarjs@1.1.0: + resolution: {integrity: sha512-WIMYor1cy6Q2r1GdfvKG4F+Rg9VpQM5/DiemAQFMlVEpnPA7HSk7dBoYam195+y3rMfzhg87v7SW5J0QGoMj2g==} + + sockjs@0.3.24: + resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} + + socks-proxy-agent@8.0.5: + resolution: {integrity: sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==} + engines: {node: '>= 14'} + + socks@2.8.7: + resolution: {integrity: sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + + sortablejs@1.15.7: + resolution: {integrity: sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@4.0.0: + resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} + + spdx-license-ids@3.0.23: + resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} + + spdy-transport@3.0.0: + resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} + + spdy@4.0.2: + resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} + engines: {node: '>=6.0.0'} + + split.js@1.6.5: + resolution: {integrity: sha512-mPTnGCiS/RiuTNsVhCm9De9cCAUsrNFFviRbADdKiiV+Kk8HKp/0fWu7Kr8pi3/yBmsqLFHuXGT9UUZ+CNLwFw==} + + split2@2.2.0: + resolution: {integrity: sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + ssdeep.js@0.0.3: + resolution: {integrity: sha512-QXKADMuEsOmRYGlB9JvrulcF5NLAjAvYLg3qDHUrEEilUFLKoL4fUQDw1s7hF+mOL96jwcdyXpnmCqyNu7Wm3Q==} + + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + + stacktrace-parser@0.1.10: + resolution: {integrity: sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==} + engines: {node: '>=6'} + + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + stop-iteration-iterator@1.1.0: + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} + + stream-browserify@3.0.0: + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} + + stream-shift@1.0.3: + resolution: {integrity: sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==} + + string-template@0.2.1: + resolution: {integrity: sha512-Yptehjogou2xm4UJbxJ4CxgZx12HBfeystp0y3x7s4Dj32ltVVG1Gg8YhKjHZkHicuKpZX/ffilA8505VbUbpw==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string_decoder@0.10.31: + resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@3.0.1: + resolution: {integrity: sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==} + engines: {node: '>=0.10.0'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.2.0: + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} + + strip-comments@2.0.1: + resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==} + engines: {node: '>=10'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + strtok3@6.3.0: + resolution: {integrity: sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==} + engines: {node: '>=10'} + + style-mod@4.1.3: + resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==} + + supports-color@2.0.0: + resolution: {integrity: sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==} + engines: {node: '>=0.8.0'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + synckit@0.9.3: + resolution: {integrity: sha512-JJoOEKTfL1urb1mDoEblhD9NhEbWmq9jHEMEnxoC4ujUaZ4itA8vKgwkFAyNClgxplLi9tsUKX+EduK0p/l7sg==} + engines: {node: ^14.18.0 || >=16.0.0} + + tapable@2.3.2: + resolution: {integrity: sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==} + engines: {node: '>=6'} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + tcp-port-used@1.0.2: + resolution: {integrity: sha512-l7ar8lLUD3XS1V2lfoJlCBaeoaWo/2xfYt81hM7VlvR4RrMVFqfmzfhLVk40hAb368uitje5gPtBRL1m/DGvLA==} + + terser-webpack-plugin@5.4.0: + resolution: {integrity: sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + + terser@5.46.1: + resolution: {integrity: sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==} + engines: {node: '>=10'} + hasBin: true + + tesseract.js-core@5.1.1: + resolution: {integrity: sha512-KX3bYSU5iGcO1XJa+QGPbi+Zjo2qq6eBhNjSGR5E5q0JtzkoipJKOUQD7ph8kFyteCEfEQ0maWLu8MCXtvX5uQ==} + + tesseract.js@5.1.1: + resolution: {integrity: sha512-lzVl/Ar3P3zhpUT31NjqeCo1f+D5+YfpZ5J62eo2S14QNVOmHBTtbchHm/YAbOOOzCegFnKf4B3Qih9LuldcYQ==} + + thingies@2.6.0: + resolution: {integrity: sha512-rMHRjmlFLM1R96UYPvpmnc3LYtdFrT33JIB7L9hetGue1qAPfn1N2LJeEjxUSidu1Iku+haLZXDuEXUHNGO/lg==} + engines: {node: '>=10.18'} + peerDependencies: + tslib: ^2 + + through2@2.0.5: + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + + thunky@1.1.0: + resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + + tiny-lr@1.1.1: + resolution: {integrity: sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==} + + tinycolor2@1.6.0: + resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tmp@0.2.5: + resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==} + engines: {node: '>=14.14'} + + to-buffer@1.2.2: + resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} + engines: {node: '>= 0.4'} + + to-fast-properties@1.0.3: + resolution: {integrity: sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og==} + engines: {node: '>=0.10.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toastr@2.1.4: + resolution: {integrity: sha512-LIy77F5n+sz4tefMmFOntcJ6HL0Fv3k1TDnNmFZ0bU/GcvIIfy6eG2v7zQmMiYgaalAiUv75ttFrPn5s0gyqlA==} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + token-types@4.2.1: + resolution: {integrity: sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==} + engines: {node: '>=10'} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + + tree-dump@1.1.0: + resolution: {integrity: sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + triplesec@4.0.3: + resolution: {integrity: sha512-fug70e1nJoCMxsXQJlETisAALohm84vl++IiTTHEqM7Lgqwz62jrlwqOC/gJEAJjO/ByN127sEcioB56HW3wIw==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tweetnacl@0.13.3: + resolution: {integrity: sha512-iNWodk4oBsZ03Qfw/Yvv0KB90uYrJqvL4Je7Gy4C5t/GS3sCXPRmIT1lxmId4RzvUp0XG62bcxJ2CBu/3L5DSg==} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + + type-fest@0.7.1: + resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} + engines: {node: '>=8'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + ua-parser-js@1.0.41: + resolution: {integrity: sha512-LbBDqdIC5s8iROCUjMbW1f5dJQTEFB1+KO9ogbvlb3nm9n4YHa5p4KTvFPWvh2Hs8gZMBuiB1/8+pdfe/tDPug==} + hasBin: true + + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + + uglify-js@3.19.3: + resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} + engines: {node: '>=0.8.0'} + hasBin: true + + uint64be@1.0.1: + resolution: {integrity: sha512-w+VZSp8hSZ/xWZfZNMppWNF6iqY+dcMYtG5CpwRDgxi94HIE6ematSdkzHGzVC4SDEaTsG65zrajN+oKoWG6ew==} + + unc-path-regex@0.1.2: + resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} + engines: {node: '>=0.10.0'} + + underscore.string@3.3.6: + resolution: {integrity: sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==} + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + + unicode-match-property-value-ecmascript@2.2.1: + resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} + engines: {node: '>=4'} + + unicode-property-aliases-ecmascript@2.2.0: + resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} + engines: {node: '>=4'} + + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + + unorm@1.6.0: + resolution: {integrity: sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==} + engines: {node: '>= 0.4.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + + url@0.11.4: + resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} + engines: {node: '>= 0.4'} + + urlsafe-base64@1.0.0: + resolution: {integrity: sha512-RtuPeMy7c1UrHwproMZN9gN6kiZ0SvJwRaEzwZY0j9MypEkFqyBaKv176jvlPtg58Zh36bOkS0NFABXMHvvGCA==} + + utf8@3.0.0: + resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} + + utif2@4.1.0: + resolution: {integrity: sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util@0.10.4: + resolution: {integrity: sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==} + + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + + utila@0.4.0: + resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@13.0.0: + resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} + hasBin: true + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + v8flags@3.2.0: + resolution: {integrity: sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==} + engines: {node: '>= 0.10'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + vkbeautify@0.99.3: + resolution: {integrity: sha512-2ozZEFfmVvQcHWoHLNuiKlUfDKlhh4KGsy54U0UrlLMR1SO+XKAIDqBxtBwHgNrekurlJwE8A9K6L49T78ZQ9Q==} + + vscode-languageserver-textdocument@1.0.12: + resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} + + vscode-uri@3.1.0: + resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + + w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + + wasm-feature-detect@1.8.0: + resolution: {integrity: sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==} + + watchpack@2.5.1: + resolution: {integrity: sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==} + engines: {node: '>=10.13.0'} + + wbuf@1.7.3: + resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + webpack-bundle-analyzer@4.10.2: + resolution: {integrity: sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==} + engines: {node: '>= 10.13.0'} + hasBin: true + + webpack-dev-middleware@7.4.5: + resolution: {integrity: sha512-uxQ6YqGdE4hgDKNf7hUiPXOdtkXvBJXrfEGYSx7P7LC8hnUYGK70X6xQXUvXeNyBDDcsiQXpG2m3G9vxowaEuA==} + engines: {node: '>= 18.12.0'} + peerDependencies: + webpack: ^5.0.0 + peerDependenciesMeta: + webpack: + optional: true + + webpack-dev-server@5.0.4: + resolution: {integrity: sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==} + engines: {node: '>= 18.12.0'} + hasBin: true + peerDependencies: + webpack: ^5.0.0 + webpack-cli: '*' + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + + webpack-node-externals@3.0.0: + resolution: {integrity: sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==} + engines: {node: '>=6'} + + webpack-sources@3.3.4: + resolution: {integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==} + engines: {node: '>=10.13.0'} + + webpack@5.105.4: + resolution: {integrity: sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + + websocket-driver@0.7.4: + resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + engines: {node: '>=0.8.0'} + + websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} + + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.20: + resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} + engines: {node: '>= 0.4'} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + widest-line@3.1.0: + resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} + engines: {node: '>=8'} + + winston@2.4.7: + resolution: {integrity: sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==} + engines: {node: '>= 0.10.0'} + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + + worker-loader@3.0.8: + resolution: {integrity: sha512-XQyQkIFeRVC7f7uRhFdNMe/iJOdO6zxAaR3EWbDp45v3mDhrTi+++oswKNxShUNjPC/1xUp5DB29YKLhFo129g==} + engines: {node: '>= 10.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + + workerpool@6.5.1: + resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.20.0: + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + wsl-utils@0.1.0: + resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} + engines: {node: '>=18'} + + xdg-basedir@5.1.0: + resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==} + engines: {node: '>=12'} + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xml-parse-from-string@1.0.1: + resolution: {integrity: sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==} + + xml2js@0.5.0: + resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} + engines: {node: '>=4.0.0'} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + xpath@0.0.34: + resolution: {integrity: sha512-FxF6+rkr1rNSQrhUNYrAFJpRXNzlDoMxeXN5qI84939ylEv3qqPFKa85Oxr6tDaJKqwW6KKyo2v26TSv3k6LeA==} + engines: {node: '>=0.6.0'} + + xregexp@5.1.2: + resolution: {integrity: sha512-6hGgEMCGhqCTFEJbqmWrNIPqfpdirdGWkqshu7fFZddmTSfgv5Sn9D2SaKloR79s5VUiUlpwzg3CM3G6D3VIlw==} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yaml@2.8.3: + resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + engines: {node: '>= 14.6'} + hasBin: true + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-unparser@2.0.0: + resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} + engines: {node: '>=10'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zip-stream@4.1.1: + resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} + engines: {node: '>= 10'} + + zlibjs@0.3.1: + resolution: {integrity: sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==} + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + +snapshots: + + '@asamuzakjp/css-color@3.2.0': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 10.4.3 + + '@astronautlabs/amf@0.0.6(reflect-metadata@0.2.2)': + dependencies: + '@astronautlabs/bitstream': 4.2.2(reflect-metadata@0.2.2) + transitivePeerDependencies: + - reflect-metadata + + '@astronautlabs/bitstream@4.2.2(reflect-metadata@0.2.2)': + dependencies: + reflect-metadata: 0.2.2 + + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.0': {} + + '@babel/core@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.29.2 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3(supports-color@8.1.1) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@9.39.4(jiti@2.6.1))': + dependencies: + '@babel/core': 7.29.0 + '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 + eslint: 9.39.4(jiti@2.6.1) + eslint-visitor-keys: 2.1.0 + semver: 6.3.1 + + '@babel/generator@7.29.1': + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.29.0 + + '@babel/helper-compilation-targets@7.28.6': + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.29.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + regexpu-core: 6.4.0 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + debug: 4.4.3(supports-color@8.1.1) + lodash.debounce: 4.0.8 + resolve: 1.22.11 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.28.5': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.28.6': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.29.0 + + '@babel/helper-plugin-utils@7.28.6': {} + + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-wrap-function': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helper-wrap-function@7.28.6': + dependencies: + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.29.2': + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + + '@babel/parser@7.29.2': + dependencies: + '@babel/types': 7.29.0 + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + + '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-globals': 7.28.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/template': 7.28.6 + + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-runtime@7.29.0(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.29.0) + babel-plugin-polyfill-corejs3: 0.13.0(@babel/core@7.29.0) + babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.29.0) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/polyfill@7.12.1': + dependencies: + core-js: 2.6.12 + regenerator-runtime: 0.13.11 + + '@babel/preset-env@7.29.2(@babel/core@7.29.0)': + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0) + '@babel/plugin-syntax-import-assertions': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.29.0) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-dotall-regex': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-explicit-resource-management': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-exponentiation-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-json-strings': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-systemjs': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-regenerator': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-regexp-modifiers': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-property-regex': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-sets-regex': 7.28.6(@babel/core@7.29.0) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.0) + babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.29.0) + babel-plugin-polyfill-corejs3: 0.14.2(@babel/core@7.29.0) + babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.29.0) + core-js-compat: 3.49.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/types': 7.29.0 + esutils: 2.0.3 + + '@babel/runtime-corejs3@7.29.2': + dependencies: + core-js-pure: 3.49.0 + + '@babel/runtime@7.29.2': {} + + '@babel/template@7.28.6': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + + '@babel/traverse@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@bazel/runfiles@6.5.0': {} + + '@blu3r4y/lzma@2.3.3': {} + + '@codemirror/commands@6.10.3': + dependencies: + '@codemirror/language': 6.12.3 + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + '@lezer/common': 1.5.1 + + '@codemirror/language@6.12.3': + dependencies: + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + '@lezer/common': 1.5.1 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.8 + style-mod: 4.1.3 + + '@codemirror/search@6.6.0': + dependencies: + '@codemirror/state': 6.6.0 + '@codemirror/view': 6.40.0 + crelt: 1.0.6 + + '@codemirror/state@6.6.0': + dependencies: + '@marijn/find-cluster-break': 1.0.2 + + '@codemirror/view@6.40.0': + dependencies: + '@codemirror/state': 6.6.0 + crelt: 1.0.6 + style-mod: 4.1.3 + w3c-keyname: 2.2.8 + + '@colors/colors@1.5.0': {} + + '@cspell/cspell-bundled-dicts@8.19.4': + dependencies: + '@cspell/dict-ada': 4.1.1 + '@cspell/dict-al': 1.1.1 + '@cspell/dict-aws': 4.0.17 + '@cspell/dict-bash': 4.2.2 + '@cspell/dict-companies': 3.2.11 + '@cspell/dict-cpp': 6.0.15 + '@cspell/dict-cryptocurrencies': 5.0.5 + '@cspell/dict-csharp': 4.0.8 + '@cspell/dict-css': 4.1.1 + '@cspell/dict-dart': 2.3.2 + '@cspell/dict-data-science': 2.0.13 + '@cspell/dict-django': 4.1.6 + '@cspell/dict-docker': 1.1.17 + '@cspell/dict-dotnet': 5.0.13 + '@cspell/dict-elixir': 4.0.8 + '@cspell/dict-en-common-misspellings': 2.1.12 + '@cspell/dict-en-gb': 1.1.33 + '@cspell/dict-en_us': 4.4.33 + '@cspell/dict-filetypes': 3.0.18 + '@cspell/dict-flutter': 1.1.1 + '@cspell/dict-fonts': 4.0.6 + '@cspell/dict-fsharp': 1.1.1 + '@cspell/dict-fullstack': 3.2.9 + '@cspell/dict-gaming-terms': 1.1.2 + '@cspell/dict-git': 3.1.0 + '@cspell/dict-golang': 6.0.26 + '@cspell/dict-google': 1.0.9 + '@cspell/dict-haskell': 4.0.6 + '@cspell/dict-html': 4.0.15 + '@cspell/dict-html-symbol-entities': 4.0.5 + '@cspell/dict-java': 5.0.12 + '@cspell/dict-julia': 1.1.1 + '@cspell/dict-k8s': 1.0.12 + '@cspell/dict-kotlin': 1.1.1 + '@cspell/dict-latex': 4.0.4 + '@cspell/dict-lorem-ipsum': 4.0.5 + '@cspell/dict-lua': 4.0.8 + '@cspell/dict-makefile': 1.0.5 + '@cspell/dict-markdown': 2.0.16(@cspell/dict-css@4.1.1)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.15)(@cspell/dict-typescript@3.2.3) + '@cspell/dict-monkeyc': 1.0.12 + '@cspell/dict-node': 5.0.9 + '@cspell/dict-npm': 5.2.38 + '@cspell/dict-php': 4.1.1 + '@cspell/dict-powershell': 5.0.15 + '@cspell/dict-public-licenses': 2.0.16 + '@cspell/dict-python': 4.2.26 + '@cspell/dict-r': 2.1.1 + '@cspell/dict-ruby': 5.1.1 + '@cspell/dict-rust': 4.1.2 + '@cspell/dict-scala': 5.0.9 + '@cspell/dict-shell': 1.1.2 + '@cspell/dict-software-terms': 5.2.2 + '@cspell/dict-sql': 2.2.1 + '@cspell/dict-svelte': 1.0.7 + '@cspell/dict-swift': 2.0.6 + '@cspell/dict-terraform': 1.1.3 + '@cspell/dict-typescript': 3.2.3 + '@cspell/dict-vue': 3.0.5 + + '@cspell/cspell-json-reporter@8.19.4': + dependencies: + '@cspell/cspell-types': 8.19.4 + + '@cspell/cspell-pipe@8.19.4': {} + + '@cspell/cspell-resolver@8.19.4': + dependencies: + global-directory: 4.0.1 + + '@cspell/cspell-service-bus@8.19.4': {} + + '@cspell/cspell-types@8.19.4': {} + + '@cspell/dict-ada@4.1.1': {} + + '@cspell/dict-al@1.1.1': {} + + '@cspell/dict-aws@4.0.17': {} + + '@cspell/dict-bash@4.2.2': + dependencies: + '@cspell/dict-shell': 1.1.2 + + '@cspell/dict-companies@3.2.11': {} + + '@cspell/dict-cpp@6.0.15': {} + + '@cspell/dict-cryptocurrencies@5.0.5': {} + + '@cspell/dict-csharp@4.0.8': {} + + '@cspell/dict-css@4.1.1': {} + + '@cspell/dict-dart@2.3.2': {} + + '@cspell/dict-data-science@2.0.13': {} + + '@cspell/dict-django@4.1.6': {} + + '@cspell/dict-docker@1.1.17': {} + + '@cspell/dict-dotnet@5.0.13': {} + + '@cspell/dict-elixir@4.0.8': {} + + '@cspell/dict-en-common-misspellings@2.1.12': {} + + '@cspell/dict-en-gb@1.1.33': {} + + '@cspell/dict-en_us@4.4.33': {} + + '@cspell/dict-filetypes@3.0.18': {} + + '@cspell/dict-flutter@1.1.1': {} + + '@cspell/dict-fonts@4.0.6': {} + + '@cspell/dict-fsharp@1.1.1': {} + + '@cspell/dict-fullstack@3.2.9': {} + + '@cspell/dict-gaming-terms@1.1.2': {} + + '@cspell/dict-git@3.1.0': {} + + '@cspell/dict-golang@6.0.26': {} + + '@cspell/dict-google@1.0.9': {} + + '@cspell/dict-haskell@4.0.6': {} + + '@cspell/dict-html-symbol-entities@4.0.5': {} + + '@cspell/dict-html@4.0.15': {} + + '@cspell/dict-java@5.0.12': {} + + '@cspell/dict-julia@1.1.1': {} + + '@cspell/dict-k8s@1.0.12': {} + + '@cspell/dict-kotlin@1.1.1': {} + + '@cspell/dict-latex@4.0.4': {} + + '@cspell/dict-lorem-ipsum@4.0.5': {} + + '@cspell/dict-lua@4.0.8': {} + + '@cspell/dict-makefile@1.0.5': {} + + '@cspell/dict-markdown@2.0.16(@cspell/dict-css@4.1.1)(@cspell/dict-html-symbol-entities@4.0.5)(@cspell/dict-html@4.0.15)(@cspell/dict-typescript@3.2.3)': + dependencies: + '@cspell/dict-css': 4.1.1 + '@cspell/dict-html': 4.0.15 + '@cspell/dict-html-symbol-entities': 4.0.5 + '@cspell/dict-typescript': 3.2.3 + + '@cspell/dict-monkeyc@1.0.12': {} + + '@cspell/dict-node@5.0.9': {} + + '@cspell/dict-npm@5.2.38': {} + + '@cspell/dict-php@4.1.1': {} + + '@cspell/dict-powershell@5.0.15': {} + + '@cspell/dict-public-licenses@2.0.16': {} + + '@cspell/dict-python@4.2.26': + dependencies: + '@cspell/dict-data-science': 2.0.13 + + '@cspell/dict-r@2.1.1': {} + + '@cspell/dict-ruby@5.1.1': {} + + '@cspell/dict-rust@4.1.2': {} + + '@cspell/dict-scala@5.0.9': {} + + '@cspell/dict-shell@1.1.2': {} + + '@cspell/dict-software-terms@5.2.2': {} + + '@cspell/dict-sql@2.2.1': {} + + '@cspell/dict-svelte@1.0.7': {} + + '@cspell/dict-swift@2.0.6': {} + + '@cspell/dict-terraform@1.1.3': {} + + '@cspell/dict-typescript@3.2.3': {} + + '@cspell/dict-vue@3.0.5': {} + + '@cspell/dynamic-import@8.19.4': + dependencies: + '@cspell/url': 8.19.4 + import-meta-resolve: 4.2.0 + + '@cspell/filetypes@8.19.4': {} + + '@cspell/strong-weak-map@8.19.4': {} + + '@cspell/url@8.19.4': {} + + '@csstools/color-helpers@5.1.0': {} + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-tokenizer@3.0.4': {} + + '@discoveryjs/json-ext@0.5.7': {} + + '@es-joy/jsdoccomment@0.46.0': + dependencies: + comment-parser: 1.4.1 + esquery: 1.7.0 + jsdoc-type-pratt-parser: 4.0.0 + + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.4(jiti@2.6.1))': + dependencies: + eslint: 9.39.4(jiti@2.6.1) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.2': {} + + '@eslint/config-array@0.21.2': + dependencies: + '@eslint/object-schema': 2.1.7 + debug: 4.4.3(supports-color@8.1.1) + minimatch: 3.1.5 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.4.2': + dependencies: + '@eslint/core': 0.17.0 + + '@eslint/core@0.17.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.5': + dependencies: + ajv: 6.14.0 + debug: 4.4.3(supports-color@8.1.1) + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 3.1.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.39.4': {} + + '@eslint/object-schema@2.1.7': {} + + '@eslint/plugin-kit@0.4.1': + dependencies: + '@eslint/core': 0.17.0 + levn: 0.4.1 + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jimp/core@1.6.0': + dependencies: + '@jimp/file-ops': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + await-to-js: 3.0.0 + exif-parser: 0.1.12 + file-type: 16.5.4 + mime: 3.0.0 + + '@jimp/diff@1.6.0': + dependencies: + '@jimp/plugin-resize': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + pixelmatch: 5.3.0 + + '@jimp/file-ops@1.6.0': {} + + '@jimp/js-bmp@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + bmp-ts: 1.0.9 + + '@jimp/js-gif@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + gifwrap: 0.10.1 + omggif: 1.0.10 + + '@jimp/js-jpeg@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + jpeg-js: 0.4.4 + + '@jimp/js-png@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + pngjs: 7.0.0 + + '@jimp/js-tiff@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + utif2: 4.1.0 + + '@jimp/plugin-blit@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-blur@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/utils': 1.6.0 + + '@jimp/plugin-circle@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-color@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + tinycolor2: 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-contain@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/plugin-blit': 1.6.0 + '@jimp/plugin-resize': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-cover@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/plugin-crop': 1.6.0 + '@jimp/plugin-resize': 1.6.0 + '@jimp/types': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-crop@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-displace@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-dither@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + + '@jimp/plugin-fisheye@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-flip@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-hash@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/js-bmp': 1.6.0 + '@jimp/js-jpeg': 1.6.0 + '@jimp/js-png': 1.6.0 + '@jimp/js-tiff': 1.6.0 + '@jimp/plugin-color': 1.6.0 + '@jimp/plugin-resize': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + any-base: 1.1.0 + + '@jimp/plugin-mask@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-print@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/js-jpeg': 1.6.0 + '@jimp/js-png': 1.6.0 + '@jimp/plugin-blit': 1.6.0 + '@jimp/types': 1.6.0 + parse-bmfont-ascii: 1.0.6 + parse-bmfont-binary: 1.0.6 + parse-bmfont-xml: 1.1.6 + simple-xml-to-json: 1.2.4 + zod: 3.25.76 + + '@jimp/plugin-quantize@1.6.0': + dependencies: + image-q: 4.0.0 + zod: 3.25.76 + + '@jimp/plugin-resize@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/types': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-rotate@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/plugin-crop': 1.6.0 + '@jimp/plugin-resize': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/plugin-threshold@1.6.0': + dependencies: + '@jimp/core': 1.6.0 + '@jimp/plugin-color': 1.6.0 + '@jimp/plugin-hash': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + zod: 3.25.76 + + '@jimp/types@1.6.0': + dependencies: + zod: 3.25.76 + + '@jimp/utils@1.6.0': + dependencies: + '@jimp/types': 1.6.0 + tinycolor2: 1.6.0 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/source-map@0.3.11': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@jsep-plugin/assignment@1.3.0(jsep@1.4.0)': + dependencies: + jsep: 1.4.0 + + '@jsep-plugin/regex@1.0.4(jsep@1.4.0)': + dependencies: + jsep: 1.4.0 + + '@jsonjoy.com/base64@1.1.2(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/base64@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/buffers@1.2.1(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/buffers@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/codegen@1.0.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/codegen@17.67.0(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/fs-core@4.57.1(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-builtins': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.1(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-fsa@4.57.1(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-core': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.1(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-builtins@4.57.1(tslib@2.8.1)': + dependencies: + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-to-fsa@4.57.1(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-fsa': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.1(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node-utils@4.57.1(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-builtins': 4.57.1(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-node@4.57.1(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-core': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.57.1(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-print@4.57.1(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/fs-node-utils': 4.57.1(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/fs-snapshot@4.57.1(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/json-pack': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@1.21.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 1.1.2(tslib@2.8.1) + '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/json-pointer': 1.0.2(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 2.6.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pack@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/base64': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/json-pointer': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + hyperdyperid: 1.2.0 + thingies: 2.6.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pointer@1.0.2(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/json-pointer@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/util': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@1.9.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 1.2.1(tslib@2.8.1) + '@jsonjoy.com/codegen': 1.0.0(tslib@2.8.1) + tslib: 2.8.1 + + '@jsonjoy.com/util@17.67.0(tslib@2.8.1)': + dependencies: + '@jsonjoy.com/buffers': 17.67.0(tslib@2.8.1) + '@jsonjoy.com/codegen': 17.67.0(tslib@2.8.1) + tslib: 2.8.1 + + '@leichtgewicht/ip-codec@2.0.5': {} + + '@lezer/common@1.5.1': {} + + '@lezer/highlight@1.2.3': + dependencies: + '@lezer/common': 1.5.1 + + '@lezer/lr@1.4.8': + dependencies: + '@lezer/common': 1.5.1 + + '@marijn/find-cluster-break@1.0.2': {} + + '@napi-rs/nice-android-arm-eabi@1.1.1': + optional: true + + '@napi-rs/nice-android-arm64@1.1.1': + optional: true + + '@napi-rs/nice-darwin-arm64@1.1.1': + optional: true + + '@napi-rs/nice-darwin-x64@1.1.1': + optional: true + + '@napi-rs/nice-freebsd-x64@1.1.1': + optional: true + + '@napi-rs/nice-linux-arm-gnueabihf@1.1.1': + optional: true + + '@napi-rs/nice-linux-arm64-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-arm64-musl@1.1.1': + optional: true + + '@napi-rs/nice-linux-ppc64-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-riscv64-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-s390x-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-x64-gnu@1.1.1': + optional: true + + '@napi-rs/nice-linux-x64-musl@1.1.1': + optional: true + + '@napi-rs/nice-openharmony-arm64@1.1.1': + optional: true + + '@napi-rs/nice-win32-arm64-msvc@1.1.1': + optional: true + + '@napi-rs/nice-win32-ia32-msvc@1.1.1': + optional: true + + '@napi-rs/nice-win32-x64-msvc@1.1.1': + optional: true + + '@napi-rs/nice@1.1.1': + optionalDependencies: + '@napi-rs/nice-android-arm-eabi': 1.1.1 + '@napi-rs/nice-android-arm64': 1.1.1 + '@napi-rs/nice-darwin-arm64': 1.1.1 + '@napi-rs/nice-darwin-x64': 1.1.1 + '@napi-rs/nice-freebsd-x64': 1.1.1 + '@napi-rs/nice-linux-arm-gnueabihf': 1.1.1 + '@napi-rs/nice-linux-arm64-gnu': 1.1.1 + '@napi-rs/nice-linux-arm64-musl': 1.1.1 + '@napi-rs/nice-linux-ppc64-gnu': 1.1.1 + '@napi-rs/nice-linux-riscv64-gnu': 1.1.1 + '@napi-rs/nice-linux-s390x-gnu': 1.1.1 + '@napi-rs/nice-linux-x64-gnu': 1.1.1 + '@napi-rs/nice-linux-x64-musl': 1.1.1 + '@napi-rs/nice-openharmony-arm64': 1.1.1 + '@napi-rs/nice-win32-arm64-msvc': 1.1.1 + '@napi-rs/nice-win32-ia32-msvc': 1.1.1 + '@napi-rs/nice-win32-x64-msvc': 1.1.1 + optional: true + + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + dependencies: + eslint-scope: 5.1.1 + + '@nightwatch/chai@5.0.3': + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.2 + deep-eql: 4.0.1 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.0.8 + + '@nightwatch/html-reporter-template@0.3.0': {} + + '@nightwatch/nightwatch-inspector@1.0.1': + dependencies: + archiver: 5.3.2 + + '@noble/hashes@1.6.1': {} + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pkgr/core@0.1.2': {} + + '@polka/url@1.0.0-next.29': {} + + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + + '@testim/chrome-version@1.1.4': {} + + '@tokenizer/token@0.3.0': {} + + '@tootallnate/quickjs-emscripten@0.23.0': {} + + '@types/body-parser@1.19.6': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 25.5.0 + + '@types/bonjour@3.5.13': + dependencies: + '@types/node': 25.5.0 + + '@types/chai@4.3.20': {} + + '@types/connect-history-api-fallback@1.5.4': + dependencies: + '@types/express-serve-static-core': 5.1.1 + '@types/node': 25.5.0 + + '@types/connect@3.4.38': + dependencies: + '@types/node': 25.5.0 + + '@types/eslint-scope@3.7.7': + dependencies: + '@types/eslint': 9.6.1 + '@types/estree': 1.0.8 + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + + '@types/estree@1.0.8': {} + + '@types/express-serve-static-core@4.19.8': + dependencies: + '@types/node': 25.5.0 + '@types/qs': 6.15.0 + '@types/range-parser': 1.2.7 + '@types/send': 1.2.1 + + '@types/express-serve-static-core@5.1.1': + dependencies: + '@types/node': 25.5.0 + '@types/qs': 6.15.0 + '@types/range-parser': 1.2.7 + '@types/send': 1.2.1 + + '@types/express@4.17.25': + dependencies: + '@types/body-parser': 1.19.6 + '@types/express-serve-static-core': 4.19.8 + '@types/qs': 6.15.0 + '@types/serve-static': 1.15.10 + + '@types/html-minifier-terser@6.1.0': {} + + '@types/http-errors@2.0.5': {} + + '@types/http-proxy@1.17.17': + dependencies: + '@types/node': 25.5.0 + + '@types/json-schema@7.0.15': {} + + '@types/mime@1.3.5': {} + + '@types/node-forge@1.3.14': + dependencies: + '@types/node': 25.5.0 + + '@types/node@16.9.1': {} + + '@types/node@17.0.45': {} + + '@types/node@25.5.0': + dependencies: + undici-types: 7.18.2 + + '@types/qs@6.15.0': {} + + '@types/range-parser@1.2.7': {} + + '@types/retry@0.12.2': {} + + '@types/sax@1.2.7': + dependencies: + '@types/node': 17.0.45 + + '@types/selenium-webdriver@4.35.5': + dependencies: + '@types/node': 25.5.0 + '@types/ws': 8.18.1 + + '@types/send@0.17.6': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 25.5.0 + + '@types/send@1.2.1': + dependencies: + '@types/node': 25.5.0 + + '@types/serve-index@1.9.4': + dependencies: + '@types/express': 4.17.25 + + '@types/serve-static@1.15.10': + dependencies: + '@types/http-errors': 2.0.5 + '@types/node': 25.5.0 + '@types/send': 0.17.6 + + '@types/sockjs@0.3.36': + dependencies: + '@types/node': 25.5.0 + + '@types/trusted-types@2.0.7': + optional: true + + '@types/ws@8.18.1': + dependencies: + '@types/node': 25.5.0 + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 25.5.0 + optional: true + + '@wavesenterprise/crypto-gost-js@2.1.0-RC1': {} + + '@webassemblyjs/ast@1.14.1': + dependencies: + '@webassemblyjs/helper-numbers': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + + '@webassemblyjs/floating-point-hex-parser@1.13.2': {} + + '@webassemblyjs/helper-api-error@1.13.2': {} + + '@webassemblyjs/helper-buffer@1.14.1': {} + + '@webassemblyjs/helper-numbers@1.13.2': + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.13.2 + '@webassemblyjs/helper-api-error': 1.13.2 + '@xtuc/long': 4.2.2 + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} + + '@webassemblyjs/helper-wasm-section@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/wasm-gen': 1.14.1 + + '@webassemblyjs/ieee754@1.13.2': + dependencies: + '@xtuc/ieee754': 1.2.0 + + '@webassemblyjs/leb128@1.13.2': + dependencies: + '@xtuc/long': 4.2.2 + + '@webassemblyjs/utf8@1.13.2': {} + + '@webassemblyjs/wasm-edit@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/helper-wasm-section': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-opt': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + '@webassemblyjs/wast-printer': 1.14.1 + + '@webassemblyjs/wasm-gen@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wasm-opt@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + + '@webassemblyjs/wasm-parser@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-api-error': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wast-printer@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@xtuc/long': 4.2.2 + + '@xmldom/xmldom@0.8.11': {} + + '@xtuc/ieee754@1.2.0': {} + + '@xtuc/long@4.2.2': {} + + abbrev@1.1.1: {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-import-phases@1.0.4(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn-jsx@5.3.2(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn-walk@8.3.5: + dependencies: + acorn: 8.16.0 + + acorn@8.16.0: {} + + agent-base@7.1.4: {} + + ajv-formats@2.1.1(ajv@8.18.0): + optionalDependencies: + ajv: 8.18.0 + + ajv-keywords@3.5.2(ajv@6.14.0): + dependencies: + ajv: 6.14.0 + + ajv-keywords@5.1.0(ajv@8.18.0): + dependencies: + ajv: 8.18.0 + fast-deep-equal: 3.1.3 + + ajv@6.14.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.18.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-align@3.0.1: + dependencies: + string-width: 4.2.3 + + ansi-colors@4.1.3: {} + + ansi-html-community@0.0.8: {} + + ansi-regex@2.1.1: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@2.2.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.3: {} + + ansi-to-html@0.7.2: + dependencies: + entities: 2.2.0 + + any-base@1.1.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.2 + + archiver-utils@2.1.0: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 2.3.8 + + archiver-utils@3.0.4: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + archiver@5.3.2: + dependencies: + archiver-utils: 2.1.0 + async: 3.2.6 + buffer-crc32: 0.2.13 + readable-stream: 3.6.2 + readdir-glob: 1.1.3 + tar-stream: 2.2.0 + zip-stream: 4.1.1 + + are-docs-informative@0.0.2: {} + + arg@5.0.2: {} + + argon2-browser@1.18.0: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + aria-query@5.1.3: + dependencies: + deep-equal: 2.2.3 + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-each@1.0.1: {} + + array-flatten@1.1.1: {} + + array-slice@1.1.0: {} + + array-timsort@1.0.3: {} + + arrify@2.0.1: {} + + arrive@2.5.3: {} + + asn1.js@4.10.1: + dependencies: + bn.js: 4.12.3 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + assert@2.1.0: + dependencies: + call-bind: 1.0.8 + is-nan: 1.3.2 + object-is: 1.1.6 + object.assign: 4.1.7 + util: 0.12.5 + + assertion-error@1.1.0: {} + + ast-types@0.13.4: + dependencies: + tslib: 2.8.1 + + async@2.6.4: + dependencies: + lodash: 4.17.23 + + async@3.2.3: {} + + async@3.2.6: {} + + asynckit@0.4.0: {} + + autoprefixer@10.4.27(postcss@8.5.8): + dependencies: + browserslist: 4.28.1 + caniuse-lite: 1.0.30001781 + fraction.js: 5.3.4 + picocolors: 1.1.1 + postcss: 8.5.8 + postcss-value-parser: 4.2.0 + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + avsc@5.7.9: {} + + await-to-js@3.0.0: {} + + axe-core@4.11.1: {} + + axios@1.14.0: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.5 + proxy-from-env: 2.1.0 + transitivePeerDependencies: + - debug + + babel-code-frame@6.26.0: + dependencies: + chalk: 1.1.3 + esutils: 2.0.3 + js-tokens: 3.0.2 + + babel-loader@10.1.1(@babel/core@7.29.0)(webpack@5.105.4): + dependencies: + '@babel/core': 7.29.0 + find-up: 5.0.0 + optionalDependencies: + webpack: 5.105.4 + + babel-messages@6.23.0: + dependencies: + babel-runtime: 6.26.0 + + babel-plugin-dynamic-import-node@2.3.3: + dependencies: + object.assign: 4.1.7 + + babel-plugin-polyfill-corejs2@0.4.17(@babel/core@7.29.0): + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.0) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.13.0(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.0) + core-js-compat: 3.49.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.14.2(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.0) + core-js-compat: 3.49.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.8(@babel/core@7.29.0): + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-builtin-extend@1.1.2: + dependencies: + babel-runtime: 6.26.0 + babel-template: 6.26.0 + transitivePeerDependencies: + - supports-color + + babel-runtime@6.26.0: + dependencies: + core-js: 2.6.12 + regenerator-runtime: 0.11.1 + + babel-template@6.26.0: + dependencies: + babel-runtime: 6.26.0 + babel-traverse: 6.26.0 + babel-types: 6.26.0 + babylon: 6.18.0 + lodash: 4.17.23 + transitivePeerDependencies: + - supports-color + + babel-traverse@6.26.0: + dependencies: + babel-code-frame: 6.26.0 + babel-messages: 6.23.0 + babel-runtime: 6.26.0 + babel-types: 6.26.0 + babylon: 6.18.0 + debug: 2.6.9 + globals: 9.18.0 + invariant: 2.2.4 + lodash: 4.17.23 + transitivePeerDependencies: + - supports-color + + babel-types@6.26.0: + dependencies: + babel-runtime: 6.26.0 + esutils: 2.0.3 + lodash: 4.17.23 + to-fast-properties: 1.0.3 + + babylon@6.18.0: {} + + balanced-match@1.0.2: {} + + base64-js@1.5.1: {} + + base64-loader@1.0.0: {} + + baseline-browser-mapping@2.10.12: {} + + basic-auth@2.0.1: + dependencies: + safe-buffer: 5.1.2 + + basic-ftp@5.2.0: {} + + batch@0.6.1: {} + + bcryptjs@2.4.3: {} + + big.js@5.2.2: {} + + bignumber.js@9.3.1: {} + + binary-extensions@2.3.0: {} + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + blakejs@1.2.1: {} + + bmp-js@0.1.0: {} + + bmp-ts@1.0.9: {} + + bn.js@4.12.3: {} + + bn.js@5.2.3: {} + + bn@1.0.5: {} + + body-parser@1.20.4: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.14.2 + raw-body: 2.5.3 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + body@5.1.0: + dependencies: + continuable-cache: 0.3.1 + error: 7.2.1 + raw-body: 1.1.7 + safe-json-parse: 1.0.1 + + bonjour-service@1.3.0: + dependencies: + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + + boolbase@1.0.0: {} + + bootstrap-colorpicker@3.4.0: + dependencies: + bootstrap: 4.6.2(jquery@3.7.1)(popper.js@1.16.1) + jquery: 3.7.1 + popper.js: 1.16.1 + + bootstrap-material-design@4.1.3: {} + + bootstrap@4.6.2(jquery@3.7.1)(popper.js@1.16.1): + dependencies: + jquery: 3.7.1 + popper.js: 1.16.1 + + boxen@5.1.2: + dependencies: + ansi-align: 3.0.1 + camelcase: 6.3.0 + chalk: 4.1.2 + cli-boxes: 2.2.1 + string-width: 4.2.3 + type-fest: 0.20.2 + widest-line: 3.1.0 + wrap-ansi: 7.0.0 + + brace-expansion@1.1.13: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.3: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + brorand@1.1.0: {} + + browser-stdout@1.3.1: {} + + browserify-aes@1.2.0: + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.7 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + browserify-cipher@1.0.1: + dependencies: + browserify-aes: 1.2.0 + browserify-des: 1.0.2 + evp_bytestokey: 1.0.3 + + browserify-des@1.0.2: + dependencies: + cipher-base: 1.0.7 + des.js: 1.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + browserify-rsa@4.1.1: + dependencies: + bn.js: 5.2.3 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + browserify-sign@4.2.5: + dependencies: + bn.js: 5.2.3 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + create-hmac: 1.1.7 + elliptic: 6.6.1 + inherits: 2.0.4 + parse-asn1: 5.1.9 + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + + browserify-zlib@0.2.0: + dependencies: + pako: 1.0.11 + + browserslist@4.28.1: + dependencies: + baseline-browser-mapping: 2.10.12 + caniuse-lite: 1.0.30001781 + electron-to-chromium: 1.5.328 + node-releases: 2.0.36 + update-browserslist-db: 1.2.3(browserslist@4.28.1) + + bson@4.7.2: + dependencies: + buffer: 5.7.1 + + buffer-crc32@0.2.13: {} + + buffer-equal-constant-time@1.0.1: {} + + buffer-from@1.1.2: {} + + buffer-xor@1.0.3: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + + bytes@1.0.0: {} + + bytes@3.1.2: {} + + bzip-deflate@1.0.0: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + camel-case@4.1.2: + dependencies: + pascal-case: 3.1.2 + tslib: 2.8.1 + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001781: {} + + cbor@9.0.2: + dependencies: + nofilter: 3.1.0 + + chai-nightwatch@0.5.3: + dependencies: + assertion-error: 1.1.0 + + chalk-template@1.1.2: + dependencies: + chalk: 5.6.2 + + chalk@1.1.3: + dependencies: + ansi-styles: 2.2.1 + escape-string-regexp: 1.0.5 + has-ansi: 2.0.0 + strip-ansi: 3.0.1 + supports-color: 2.0.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.6.2: {} + + check-error@1.0.2: {} + + chi-squared@1.1.0: + dependencies: + gamma: 1.0.0 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chrome-trace-event@1.0.4: {} + + chromedriver@143.0.4: + dependencies: + '@testim/chrome-version': 1.1.4 + axios: 1.14.0 + compare-versions: 6.1.1 + extract-zip: 2.0.1 + proxy-agent: 6.5.0 + proxy-from-env: 1.1.0 + tcp-port-used: 1.0.2 + transitivePeerDependencies: + - debug + - supports-color + + ci-info@3.3.0: {} + + cipher-base@1.0.7: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + + clean-css@5.3.3: + dependencies: + source-map: 0.6.1 + + clear-module@4.1.2: + dependencies: + parent-module: 2.0.0 + resolve-from: 5.0.0 + + cli-boxes@2.2.1: {} + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-progress@3.12.0: + dependencies: + string-width: 4.2.3 + + cli-spinners@2.9.2: {} + + cli-table3@0.6.5: + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone@1.0.4: {} + + codepage@1.15.0: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + colorette@2.0.20: {} + + colors@1.0.3: {} + + colors@1.1.2: {} + + colors@1.4.0: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@13.1.0: {} + + commander@2.20.3: {} + + commander@7.2.0: {} + + commander@8.3.0: {} + + comment-json@4.6.2: + dependencies: + array-timsort: 1.0.3 + esprima: 4.0.1 + + comment-parser@1.4.1: {} + + compare-versions@6.1.1: {} + + compress-commons@4.1.2: + dependencies: + buffer-crc32: 0.2.13 + crc32-stream: 4.0.3 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + compressible@2.0.18: + dependencies: + mime-db: 1.54.0 + + compression-webpack-plugin@11.1.0(webpack@5.105.4): + dependencies: + schema-utils: 4.3.3 + serialize-javascript: 6.0.2 + webpack: 5.105.4 + + compression@1.8.1: + dependencies: + bytes: 3.1.2 + compressible: 2.0.18 + debug: 2.6.9 + negotiator: 0.6.4 + on-headers: 1.1.0 + safe-buffer: 5.2.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + concat-map@0.0.1: {} + + connect-history-api-fallback@2.0.0: {} + + connect-livereload@0.6.1: {} + + connect@3.7.0: + dependencies: + debug: 2.6.9 + finalhandler: 1.1.2 + parseurl: 1.3.3 + utils-merge: 1.0.1 + transitivePeerDependencies: + - supports-color + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + continuable-cache@0.3.1: {} + + convert-source-map@2.0.0: {} + + cookie-signature@1.0.7: {} + + cookie@0.7.2: {} + + copy-webpack-plugin@13.0.1(webpack@5.105.4): + dependencies: + glob-parent: 6.0.2 + normalize-path: 3.0.0 + schema-utils: 4.3.3 + serialize-javascript: 6.0.2 + tinyglobby: 0.2.15 + webpack: 5.105.4 + + core-js-compat@3.49.0: + dependencies: + browserslist: 4.28.1 + + core-js-pure@3.49.0: {} + + core-js@2.6.12: {} + + core-js@3.49.0: {} + + core-util-is@1.0.3: {} + + cosmiconfig@9.0.1: + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + parse-json: 5.2.0 + + crc-32@1.2.2: {} + + crc32-stream@4.0.3: + dependencies: + crc-32: 1.2.2 + readable-stream: 3.6.2 + + create-ecdh@4.0.4: + dependencies: + bn.js: 4.12.3 + elliptic: 6.6.1 + + create-hash@1.2.0: + dependencies: + cipher-base: 1.0.7 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.3 + sha.js: 2.4.12 + + create-hmac@1.1.7: + dependencies: + cipher-base: 1.0.7 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.3 + safe-buffer: 5.2.1 + sha.js: 2.4.12 + + crelt@1.0.6: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypto-api@0.8.5: {} + + crypto-browserify@3.12.1: + dependencies: + browserify-cipher: 1.0.1 + browserify-sign: 4.2.5 + create-ecdh: 4.0.4 + create-hash: 1.2.0 + create-hmac: 1.1.7 + diffie-hellman: 5.0.3 + hash-base: 3.0.5 + inherits: 2.0.4 + pbkdf2: 3.1.5 + public-encrypt: 4.0.3 + randombytes: 2.1.0 + randomfill: 1.0.4 + + crypto-js@4.2.0: {} + + cspell-config-lib@8.19.4: + dependencies: + '@cspell/cspell-types': 8.19.4 + comment-json: 4.6.2 + yaml: 2.8.3 + + cspell-dictionary@8.19.4: + dependencies: + '@cspell/cspell-pipe': 8.19.4 + '@cspell/cspell-types': 8.19.4 + cspell-trie-lib: 8.19.4 + fast-equals: 5.4.0 + + cspell-gitignore@8.19.4: + dependencies: + '@cspell/url': 8.19.4 + cspell-glob: 8.19.4 + cspell-io: 8.19.4 + + cspell-glob@8.19.4: + dependencies: + '@cspell/url': 8.19.4 + picomatch: 4.0.4 + + cspell-grammar@8.19.4: + dependencies: + '@cspell/cspell-pipe': 8.19.4 + '@cspell/cspell-types': 8.19.4 + + cspell-io@8.19.4: + dependencies: + '@cspell/cspell-service-bus': 8.19.4 + '@cspell/url': 8.19.4 + + cspell-lib@8.19.4: + dependencies: + '@cspell/cspell-bundled-dicts': 8.19.4 + '@cspell/cspell-pipe': 8.19.4 + '@cspell/cspell-resolver': 8.19.4 + '@cspell/cspell-types': 8.19.4 + '@cspell/dynamic-import': 8.19.4 + '@cspell/filetypes': 8.19.4 + '@cspell/strong-weak-map': 8.19.4 + '@cspell/url': 8.19.4 + clear-module: 4.1.2 + comment-json: 4.6.2 + cspell-config-lib: 8.19.4 + cspell-dictionary: 8.19.4 + cspell-glob: 8.19.4 + cspell-grammar: 8.19.4 + cspell-io: 8.19.4 + cspell-trie-lib: 8.19.4 + env-paths: 3.0.0 + fast-equals: 5.4.0 + gensequence: 7.0.0 + import-fresh: 3.3.1 + resolve-from: 5.0.0 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.1.0 + xdg-basedir: 5.1.0 + + cspell-trie-lib@8.19.4: + dependencies: + '@cspell/cspell-pipe': 8.19.4 + '@cspell/cspell-types': 8.19.4 + gensequence: 7.0.0 + + cspell@8.19.4: + dependencies: + '@cspell/cspell-json-reporter': 8.19.4 + '@cspell/cspell-pipe': 8.19.4 + '@cspell/cspell-types': 8.19.4 + '@cspell/dynamic-import': 8.19.4 + '@cspell/url': 8.19.4 + chalk: 5.6.2 + chalk-template: 1.1.2 + commander: 13.1.0 + cspell-dictionary: 8.19.4 + cspell-gitignore: 8.19.4 + cspell-glob: 8.19.4 + cspell-io: 8.19.4 + cspell-lib: 8.19.4 + fast-json-stable-stringify: 2.1.0 + file-entry-cache: 9.1.0 + semver: 7.7.4 + tinyglobby: 0.2.15 + + css-loader@7.1.4(webpack@5.105.4): + dependencies: + icss-utils: 5.1.0(postcss@8.5.8) + postcss: 8.5.8 + postcss-modules-extract-imports: 3.1.0(postcss@8.5.8) + postcss-modules-local-by-default: 4.2.0(postcss@8.5.8) + postcss-modules-scope: 3.2.1(postcss@8.5.8) + postcss-modules-values: 4.0.0(postcss@8.5.8) + postcss-value-parser: 4.2.0 + semver: 7.7.4 + optionalDependencies: + webpack: 5.105.4 + + css-select@4.3.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + + css-what@6.2.2: {} + + cssesc@3.0.0: {} + + cssstyle@4.6.0: + dependencies: + '@asamuzakjp/css-color': 3.2.0 + rrweb-cssom: 0.8.0 + + ctph.js@0.0.5: {} + + cycle@1.0.3: {} + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-axis@3.0.0: {} + + d3-brush@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3-chord@3.0.1: + dependencies: + d3-path: 3.1.0 + + d3-color@3.1.0: {} + + d3-contour@4.0.2: + dependencies: + d3-array: 3.2.4 + + d3-delaunay@6.0.4: + dependencies: + delaunator: 5.1.0 + + d3-dispatch@3.0.1: {} + + d3-drag@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-selection: 3.0.0 + + d3-dsv@3.0.1: + dependencies: + commander: 7.2.0 + iconv-lite: 0.6.3 + rw: 1.3.3 + + d3-ease@3.0.1: {} + + d3-fetch@3.0.1: + dependencies: + d3-dsv: 3.0.1 + + d3-force@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-quadtree: 3.0.1 + d3-timer: 3.0.1 + + d3-format@3.1.2: {} + + d3-geo@3.1.1: + dependencies: + d3-array: 3.2.4 + + d3-hexbin@0.2.2: {} + + d3-hierarchy@3.1.2: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-path@3.1.0: {} + + d3-polygon@3.0.1: {} + + d3-quadtree@3.0.1: {} + + d3-random@3.0.1: {} + + d3-scale-chromatic@3.1.0: + dependencies: + d3-color: 3.1.0 + d3-interpolate: 3.0.1 + + d3-scale@4.0.2: + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.2 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + + d3-selection@3.0.0: {} + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + + d3-time-format@4.1.0: + dependencies: + d3-time: 3.1.0 + + d3-time@3.1.0: + dependencies: + d3-array: 3.2.4 + + d3-timer@3.0.1: {} + + d3-transition@3.0.1(d3-selection@3.0.0): + dependencies: + d3-color: 3.1.0 + d3-dispatch: 3.0.1 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-timer: 3.0.1 + + d3-zoom@3.0.0: + dependencies: + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-interpolate: 3.0.1 + d3-selection: 3.0.0 + d3-transition: 3.0.1(d3-selection@3.0.0) + + d3@7.9.0: + dependencies: + d3-array: 3.2.4 + d3-axis: 3.0.0 + d3-brush: 3.0.0 + d3-chord: 3.0.1 + d3-color: 3.1.0 + d3-contour: 4.0.2 + d3-delaunay: 6.0.4 + d3-dispatch: 3.0.1 + d3-drag: 3.0.0 + d3-dsv: 3.0.1 + d3-ease: 3.0.1 + d3-fetch: 3.0.1 + d3-force: 3.0.0 + d3-format: 3.1.2 + d3-geo: 3.1.1 + d3-hierarchy: 3.1.2 + d3-interpolate: 3.0.1 + d3-path: 3.1.0 + d3-polygon: 3.0.1 + d3-quadtree: 3.0.1 + d3-random: 3.0.1 + d3-scale: 4.0.2 + d3-scale-chromatic: 3.1.0 + d3-selection: 3.0.0 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + d3-timer: 3.0.1 + d3-transition: 3.0.1(d3-selection@3.0.0) + d3-zoom: 3.0.0 + + data-uri-to-buffer@6.0.2: {} + + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + + dateformat@4.6.3: {} + + debounce@1.2.1: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.3.1: + dependencies: + ms: 2.1.2 + + debug@4.4.3(supports-color@8.1.1): + dependencies: + ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + + decamelize@4.0.0: {} + + decimal.js@10.6.0: {} + + deep-eql@4.0.1: + dependencies: + type-detect: 4.0.8 + + deep-equal@1.1.2: + dependencies: + is-arguments: 1.2.0 + is-date-object: 1.1.0 + is-regex: 1.2.1 + object-is: 1.1.6 + object-keys: 1.1.1 + regexp.prototype.flags: 1.5.4 + + deep-equal@2.2.3: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + es-get-iterator: 1.1.3 + get-intrinsic: 1.3.0 + is-arguments: 1.2.0 + is-array-buffer: 3.0.5 + is-date-object: 1.1.0 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + isarray: 2.0.5 + object-is: 1.1.6 + object-keys: 1.1.1 + object.assign: 4.1.7 + regexp.prototype.flags: 1.5.4 + side-channel: 1.1.0 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.20 + + deep-for-each@3.0.0: + dependencies: + lodash.isplainobject: 4.0.6 + + deep-is@0.1.4: {} + + default-browser-id@5.0.1: {} + + default-browser@5.5.0: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.1 + + default-gateway@6.0.3: + dependencies: + execa: 5.1.1 + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-lazy-prop@2.0.0: {} + + define-lazy-prop@3.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + + delaunator@5.1.0: + dependencies: + robust-predicates: 3.0.3 + + delayed-stream@1.0.0: {} + + depd@1.1.2: {} + + depd@2.0.0: {} + + des.js@1.1.0: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + destroy@1.2.0: {} + + detect-file@1.0.0: {} + + detect-node@2.1.0: {} + + devtools-protocol@0.0.1140464: {} + + didyoumean@1.2.2: {} + + diff@5.2.2: {} + + diffie-hellman@5.0.3: + dependencies: + bn.js: 4.12.3 + miller-rabin: 4.0.1 + randombytes: 2.1.0 + + dns-packet@5.6.1: + dependencies: + '@leichtgewicht/ip-codec': 2.0.5 + + dom-converter@0.2.0: + dependencies: + utila: 0.4.0 + + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + domelementtype@2.3.0: {} + + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 + + dompurify@3.3.3: + optionalDependencies: + '@types/trusted-types': 2.0.7 + + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + + dot-case@3.0.4: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + dotenv@16.3.1: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexer@0.1.2: {} + + duplexify@3.7.1: + dependencies: + end-of-stream: 1.4.5 + inherits: 2.0.4 + readable-stream: 2.3.8 + stream-shift: 1.0.3 + + eastasianwidth@0.2.0: {} + + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + ee-first@1.1.1: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.4 + + electron-to-chromium@1.5.328: {} + + elliptic@6.6.1: + dependencies: + bn.js: 4.12.3 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + emojis-list@3.0.0: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + enhanced-resolve@5.20.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.2 + + entities@2.2.0: {} + + entities@4.5.0: {} + + entities@6.0.1: {} + + env-paths@2.2.1: {} + + env-paths@3.0.0: {} + + envinfo@7.11.0: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + error@7.2.1: + dependencies: + string-template: 0.2.1 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-get-iterator@1.1.3: + dependencies: + call-bind: 1.0.8 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + is-arguments: 1.2.0 + is-map: 2.0.3 + is-set: 2.0.3 + is-string: 1.1.1 + isarray: 2.0.5 + stop-iteration-iterator: 1.1.0 + + es-module-lexer@1.7.0: {} + + es-module-lexer@2.0.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es6-object-assign@1.1.0: {} + + es6-polyfills@2.0.0: + dependencies: + es6-object-assign: 1.1.0 + es6-promise-polyfill: 1.2.0 + + es6-promise-polyfill@1.2.0: {} + + es6-promisify@7.0.0: {} + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + eslint-plugin-jsdoc@48.11.0(eslint@9.39.4(jiti@2.6.1)): + dependencies: + '@es-joy/jsdoccomment': 0.46.0 + are-docs-informative: 0.0.2 + comment-parser: 1.4.1 + debug: 4.4.3(supports-color@8.1.1) + escape-string-regexp: 4.0.0 + eslint: 9.39.4(jiti@2.6.1) + espree: 10.4.0 + esquery: 1.7.0 + parse-imports: 2.2.1 + semver: 7.7.4 + spdx-expression-parse: 4.0.0 + synckit: 0.9.3 + transitivePeerDependencies: + - supports-color + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@2.1.0: {} + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.39.4(jiti@2.6.1): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.4(jiti@2.6.1)) + '@eslint-community/regexpp': 4.12.2 + '@eslint/config-array': 0.21.2 + '@eslint/config-helpers': 0.4.2 + '@eslint/core': 0.17.0 + '@eslint/eslintrc': 3.3.5 + '@eslint/js': 9.39.4 + '@eslint/plugin-kit': 0.4.1 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + ajv: 6.14.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3(supports-color@8.1.1) + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.5 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.1 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + eslint-visitor-keys: 4.2.1 + + esprima@4.0.1: {} + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@4.3.0: {} + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + etag@1.8.1: {} + + event-target-shim@5.0.1: {} + + eventemitter2@0.4.14: {} + + eventemitter3@4.0.7: {} + + events@3.3.0: {} + + evp_bytestokey@1.0.3: + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + exif-parser@0.1.12: {} + + exit@0.1.2: {} + + expand-tilde@2.0.2: + dependencies: + homedir-polyfill: 1.0.3 + + express@4.22.1: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.4 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.2 + cookie-signature: 1.0.7 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.2 + fresh: 0.5.2 + http-errors: 2.0.1 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.13 + proxy-addr: 2.0.7 + qs: 6.14.2 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.2 + serve-static: 1.16.3 + setprototypeof: 1.2.0 + statuses: 2.0.2 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + extend@3.0.2: {} + + extract-zip@2.0.1: + dependencies: + debug: 4.4.3(supports-color@8.1.1) + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + + eyes@0.1.8: {} + + fast-deep-equal@3.1.3: {} + + fast-equals@5.4.0: {} + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-uri@3.1.0: {} + + faye-websocket@0.10.0: + dependencies: + websocket-driver: 0.7.4 + + faye-websocket@0.11.4: + dependencies: + websocket-driver: 0.7.4 + + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + fernet@0.3.3: + dependencies: + crypto-js: 4.2.0 + urlsafe-base64: 1.0.0 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + file-entry-cache@9.1.0: + dependencies: + flat-cache: 5.0.0 + + file-saver@2.0.5: {} + + file-sync-cmp@0.1.1: {} + + file-type@16.5.4: + dependencies: + readable-web-to-node-stream: 3.0.4 + strtok3: 6.3.0 + token-types: 4.2.1 + + filelist@1.0.6: + dependencies: + minimatch: 5.1.9 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.1.2: + dependencies: + debug: 2.6.9 + encodeurl: 1.0.2 + escape-html: 1.0.3 + on-finished: 2.3.0 + parseurl: 1.3.3 + statuses: 1.5.0 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + finalhandler@1.3.2: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.2 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + findup-sync@4.0.0: + dependencies: + detect-file: 1.0.0 + is-glob: 4.0.3 + micromatch: 4.0.8 + resolve-dir: 1.0.1 + + findup-sync@5.0.0: + dependencies: + detect-file: 1.0.0 + is-glob: 4.0.3 + micromatch: 4.0.8 + resolve-dir: 1.0.1 + + fined@1.2.0: + dependencies: + expand-tilde: 2.0.2 + is-plain-object: 2.0.4 + object.defaults: 1.1.0 + object.pick: 1.3.0 + parse-filepath: 1.0.2 + + flagged-respawn@1.0.1: {} + + flat-cache@4.0.1: + dependencies: + flatted: 3.4.2 + keyv: 4.5.4 + + flat-cache@5.0.0: + dependencies: + flatted: 3.4.2 + keyv: 4.5.4 + + flat@5.0.2: {} + + flat@6.0.1: {} + + flatted@3.4.2: {} + + follow-redirects@1.15.11: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + for-in@1.0.2: {} + + for-own@1.0.0: + dependencies: + for-in: 1.0.2 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + forwarded@0.2.0: {} + + fraction.js@5.3.4: {} + + fresh@0.5.2: {} + + fs-constants@1.0.0: {} + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + functions-have-names@1.2.3: {} + + gamma@1.0.0: {} + + gaze@1.1.3: + dependencies: + globule: 1.3.4 + + generator-function@2.0.1: {} + + gensequence@7.0.0: {} + + gensync@1.0.0-beta.2: {} + + geodesy@1.1.3: {} + + get-caller-file@2.0.5: {} + + get-func-name@2.0.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@5.2.0: + dependencies: + pump: 3.0.4 + + get-stream@6.0.1: {} + + get-uri@6.0.5: + dependencies: + basic-ftp: 5.2.0 + data-uri-to-buffer: 6.0.2 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + getobject@1.0.2: {} + + gifwrap@0.10.1: + dependencies: + image-q: 4.0.0 + omggif: 1.0.10 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob-to-regex.js@1.2.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + glob-to-regexp@0.4.1: {} + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@7.1.7: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.0.8 + once: 1.4.0 + path-is-absolute: 1.0.1 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.9 + once: 1.4.0 + + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + + global-modules@1.0.0: + dependencies: + global-prefix: 1.0.2 + is-windows: 1.0.2 + resolve-dir: 1.0.1 + + global-prefix@1.0.2: + dependencies: + expand-tilde: 2.0.2 + homedir-polyfill: 1.0.3 + ini: 1.3.8 + is-windows: 1.0.2 + which: 1.3.1 + + globals@14.0.0: {} + + globals@15.15.0: {} + + globals@9.18.0: {} + + globule@1.3.4: + dependencies: + glob: 7.1.7 + lodash: 4.17.23 + minimatch: 3.0.8 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + grunt-chmod@1.1.1: + dependencies: + shelljs: 0.5.3 + + grunt-cli@1.4.3: + dependencies: + grunt-known-options: 2.0.0 + interpret: 1.1.0 + liftup: 3.0.1 + nopt: 4.0.3 + v8flags: 3.2.0 + + grunt-concurrent@3.0.0(grunt@1.6.1): + dependencies: + arrify: 2.0.1 + async: 3.2.6 + grunt: 1.6.1 + indent-string: 4.0.0 + pad-stream: 2.0.0 + + grunt-contrib-clean@2.0.1(grunt@1.6.1): + dependencies: + async: 3.2.6 + grunt: 1.6.1 + rimraf: 2.7.1 + + grunt-contrib-connect@5.0.1: + dependencies: + async: 3.2.6 + connect: 3.7.0 + connect-livereload: 0.6.1 + http2-wrapper: 2.2.1 + morgan: 1.10.1 + open: 8.4.2 + portscanner: 2.2.0 + serve-index: 1.9.2 + serve-static: 1.16.3 + transitivePeerDependencies: + - supports-color + + grunt-contrib-copy@1.0.0: + dependencies: + chalk: 1.1.3 + file-sync-cmp: 0.1.1 + + grunt-contrib-watch@1.1.0: + dependencies: + async: 2.6.4 + gaze: 1.1.3 + lodash: 4.17.23 + tiny-lr: 1.1.1 + transitivePeerDependencies: + - supports-color + + grunt-eslint@25.0.0(grunt@1.6.1)(jiti@2.6.1): + dependencies: + chalk: 4.1.2 + eslint: 9.39.4(jiti@2.6.1) + grunt: 1.6.1 + transitivePeerDependencies: + - jiti + - supports-color + + grunt-exec@3.0.0(grunt@1.6.1): + dependencies: + grunt: 1.6.1 + + grunt-known-options@2.0.0: {} + + grunt-legacy-log-utils@2.1.0: + dependencies: + chalk: 4.1.2 + lodash: 4.17.23 + + grunt-legacy-log@3.0.0: + dependencies: + colors: 1.1.2 + grunt-legacy-log-utils: 2.1.0 + hooker: 0.2.3 + lodash: 4.17.23 + + grunt-legacy-util@2.0.1: + dependencies: + async: 3.2.6 + exit: 0.1.2 + getobject: 1.0.2 + hooker: 0.2.3 + lodash: 4.17.23 + underscore.string: 3.3.6 + which: 2.0.2 + + grunt-retro@0.6.4: {} + + grunt-webpack@6.0.0(webpack@5.105.4): + dependencies: + deep-for-each: 3.0.0 + lodash: 4.17.23 + webpack: 5.105.4 + + grunt-zip@1.0.0: + dependencies: + grunt-retro: 0.6.4 + jszip: 3.10.1 + + grunt@1.6.1: + dependencies: + dateformat: 4.6.3 + eventemitter2: 0.4.14 + exit: 0.1.2 + findup-sync: 5.0.0 + glob: 7.1.7 + grunt-cli: 1.4.3 + grunt-known-options: 2.0.0 + grunt-legacy-log: 3.0.0 + grunt-legacy-util: 2.0.1 + iconv-lite: 0.6.3 + js-yaml: 3.14.2 + minimatch: 3.0.8 + nopt: 3.0.6 + + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + + handle-thing@2.0.1: {} + + handlebars@4.7.9: + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.19.3 + + has-ansi@2.0.0: + dependencies: + ansi-regex: 2.1.1 + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hash-base@3.0.5: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + hash-base@3.1.2: + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + + hash-wasm@4.12.0: {} + + hash.js@1.1.7: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + highlight.js@11.11.1: {} + + hmac-drbg@1.0.1: + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + homedir-polyfill@1.0.3: + dependencies: + parse-passwd: 1.0.0 + + hooker@0.2.3: {} + + hpack.js@2.1.6: + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + + html-entities@2.6.0: {} + + html-escaper@2.0.2: {} + + html-minifier-terser@6.1.0: + dependencies: + camel-case: 4.1.2 + clean-css: 5.3.3 + commander: 8.3.0 + he: 1.2.0 + param-case: 3.0.4 + relateurl: 0.2.7 + terser: 5.46.1 + + html-webpack-plugin@5.6.6(webpack@5.105.4): + dependencies: + '@types/html-minifier-terser': 6.1.0 + html-minifier-terser: 6.1.0 + lodash: 4.17.23 + pretty-error: 4.0.0 + tapable: 2.3.2 + optionalDependencies: + webpack: 5.105.4 + + htmlparser2@6.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + domutils: 2.8.0 + entities: 2.2.0 + + http-deceiver@1.2.7: {} + + http-errors@1.8.1: + dependencies: + depd: 1.1.2 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 1.5.0 + toidentifier: 1.0.1 + + http-errors@2.0.1: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.2 + toidentifier: 1.0.1 + + http-parser-js@0.5.10: {} + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + http-proxy-middleware@2.0.9(@types/express@4.17.25): + dependencies: + '@types/http-proxy': 1.17.17 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.8 + optionalDependencies: + '@types/express': 4.17.25 + transitivePeerDependencies: + - debug + + http-proxy@1.18.1: + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.11 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + + http2-wrapper@2.2.1: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + + hyperdyperid@1.2.0: {} + + iced-error@0.0.13: {} + + iced-lock@1.1.0: + dependencies: + iced-runtime: 1.0.4 + + iced-runtime@1.0.4: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + icss-utils@5.1.0(postcss@8.5.8): + dependencies: + postcss: 8.5.8 + + idb-keyval@6.2.2: {} + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + image-q@4.0.0: + dependencies: + '@types/node': 16.9.1 + + immediate@3.0.6: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-meta-resolve@4.2.0: {} + + imports-loader@5.0.0(webpack@5.105.4): + dependencies: + source-map-js: 1.2.1 + strip-comments: 2.0.1 + webpack: 5.105.4 + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.3: {} + + inherits@2.0.4: {} + + ini@1.3.8: {} + + ini@4.1.1: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + internmap@2.0.3: {} + + interpret@1.1.0: {} + + invariant@2.2.4: + dependencies: + loose-envify: 1.4.0 + + ip-address@10.1.0: {} + + ip-regex@4.3.0: {} + + ipaddr.js@1.9.1: {} + + ipaddr.js@2.3.0: {} + + is-absolute@1.0.0: + dependencies: + is-relative: 1.0.0 + is-windows: 1.0.2 + + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-arrayish@0.2.1: {} + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-docker@2.2.1: {} + + is-docker@3.0.0: {} + + is-electron@2.2.2: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-interactive@1.0.0: {} + + is-map@2.0.3: {} + + is-nan@1.3.2: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + + is-network-error@1.3.1: {} + + is-number-like@1.0.8: + dependencies: + lodash.isfinite: 3.3.2 + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-plain-obj@2.1.0: {} + + is-plain-obj@3.0.0: {} + + is-plain-object@2.0.4: + dependencies: + isobject: 3.0.1 + + is-potential-custom-element-name@1.0.1: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-relative@1.0.0: + dependencies: + is-unc-path: 1.0.0 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-stream@2.0.1: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.20 + + is-unc-path@1.0.0: + dependencies: + unc-path-regex: 0.1.2 + + is-unicode-supported@0.1.0: {} + + is-url@1.2.4: {} + + is-weakmap@2.0.2: {} + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-windows@1.0.2: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + + is2@2.0.9: + dependencies: + deep-is: 0.1.4 + ip-regex: 4.3.0 + is-url: 1.2.4 + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isobject@3.0.1: {} + + isstream@0.1.2: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jake@10.9.4: + dependencies: + async: 3.2.6 + filelist: 1.0.6 + picocolors: 1.1.1 + + jest-worker@27.5.1: + dependencies: + '@types/node': 25.5.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jimp@1.6.0: + dependencies: + '@jimp/core': 1.6.0 + '@jimp/diff': 1.6.0 + '@jimp/js-bmp': 1.6.0 + '@jimp/js-gif': 1.6.0 + '@jimp/js-jpeg': 1.6.0 + '@jimp/js-png': 1.6.0 + '@jimp/js-tiff': 1.6.0 + '@jimp/plugin-blit': 1.6.0 + '@jimp/plugin-blur': 1.6.0 + '@jimp/plugin-circle': 1.6.0 + '@jimp/plugin-color': 1.6.0 + '@jimp/plugin-contain': 1.6.0 + '@jimp/plugin-cover': 1.6.0 + '@jimp/plugin-crop': 1.6.0 + '@jimp/plugin-displace': 1.6.0 + '@jimp/plugin-dither': 1.6.0 + '@jimp/plugin-fisheye': 1.6.0 + '@jimp/plugin-flip': 1.6.0 + '@jimp/plugin-hash': 1.6.0 + '@jimp/plugin-mask': 1.6.0 + '@jimp/plugin-print': 1.6.0 + '@jimp/plugin-quantize': 1.6.0 + '@jimp/plugin-resize': 1.6.0 + '@jimp/plugin-rotate': 1.6.0 + '@jimp/plugin-threshold': 1.6.0 + '@jimp/types': 1.6.0 + '@jimp/utils': 1.6.0 + + jiti@2.6.1: {} + + jpeg-js@0.4.4: {} + + jq-web@0.6.2: {} + + jquery@3.7.1: {} + + js-sha3@0.9.3: {} + + js-tokens@3.0.2: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.2: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsdoc-type-pratt-parser@4.0.0: {} + + jsdom@24.1.3: + dependencies: + cssstyle: 4.6.0 + data-urls: 5.0.0 + decimal.js: 10.6.0 + form-data: 4.0.5 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.23 + parse5: 7.3.0 + rrweb-cssom: 0.7.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.4 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.20.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsep@1.4.0: {} + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + jsonata@2.1.0: {} + + jsonpath-plus@10.4.0: + dependencies: + '@jsep-plugin/assignment': 1.3.0(jsep@1.4.0) + '@jsep-plugin/regex': 1.0.4(jsep@1.4.0) + jsep: 1.4.0 + + jsonwebtoken@8.5.1: + dependencies: + jws: 3.2.3 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 5.7.2 + + jsqr@1.4.0: {} + + jsrsasign@11.1.1: {} + + jszip@3.10.1: + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + + jwa@1.4.2: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@3.2.3: + dependencies: + jwa: 1.4.2 + safe-buffer: 5.2.1 + + kbpgp@2.1.17: + dependencies: + bn: 1.0.5 + bzip-deflate: 1.0.0 + deep-equal: 1.1.2 + iced-error: 0.0.13 + iced-lock: 1.1.0 + iced-runtime: 1.0.4 + keybase-ecurve: 1.0.1 + keybase-nacl: 1.1.4 + minimist: 1.2.8 + pgp-utils: 0.0.35 + purepack: 1.0.6 + triplesec: 4.0.3 + tweetnacl: 0.13.3 + + keybase-ecurve@1.0.1: + dependencies: + bn: 1.0.5 + + keybase-nacl@1.1.4: + dependencies: + iced-runtime: 1.0.4 + tweetnacl: 0.13.3 + uint64be: 1.0.1 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kind-of@6.0.3: {} + + launch-editor@2.13.2: + dependencies: + picocolors: 1.1.1 + shell-quote: 1.8.3 + + lazystream@1.0.1: + dependencies: + readable-stream: 2.3.8 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + libbzip2-wasm@0.0.4: {} + + libyara-wasm@1.2.1: {} + + lie@3.3.0: + dependencies: + immediate: 3.0.6 + + liftup@3.0.1: + dependencies: + extend: 3.0.2 + findup-sync: 4.0.0 + fined: 1.2.0 + flagged-respawn: 1.0.1 + is-plain-object: 2.0.4 + object.map: 1.0.1 + rechoir: 0.7.1 + resolve: 1.22.11 + + lines-and-columns@1.2.4: {} + + linkify-it@5.0.0: + dependencies: + uc.micro: 2.1.0 + + livereload-js@2.4.0: {} + + loader-runner@4.3.1: {} + + loader-utils@2.0.4: + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.3 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.debounce@4.0.8: {} + + lodash.defaults@4.2.0: {} + + lodash.difference@4.5.0: {} + + lodash.flatten@4.4.0: {} + + lodash.includes@4.3.0: {} + + lodash.isboolean@3.0.3: {} + + lodash.isfinite@3.3.2: {} + + lodash.isinteger@4.0.4: {} + + lodash.isnumber@3.0.3: {} + + lodash.isplainobject@4.0.6: {} + + lodash.isstring@4.0.1: {} + + lodash.merge@4.6.2: {} + + lodash.once@4.1.1: {} + + lodash.union@4.6.0: {} + + lodash@4.17.23: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + loglevel-message-prefix@3.0.0: + dependencies: + es6-polyfills: 2.0.0 + loglevel: 1.9.2 + + loglevel@1.9.2: {} + + long@5.3.2: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + loupe@2.3.7: + dependencies: + get-func-name: 2.0.2 + + lower-case@2.0.2: + dependencies: + tslib: 2.8.1 + + lru-cache@10.4.3: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + lru-cache@7.18.3: {} + + lz-string@1.5.0: {} + + lz4js@0.2.0: {} + + make-iterator@1.0.1: + dependencies: + kind-of: 6.0.3 + + map-cache@0.2.2: {} + + markdown-it@14.1.1: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + + math-intrinsics@1.1.0: {} + + md5.js@1.3.5: + dependencies: + hash-base: 3.0.5 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + mdurl@2.0.0: {} + + media-typer@0.3.0: {} + + memfs@4.57.1(tslib@2.8.1): + dependencies: + '@jsonjoy.com/fs-core': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-fsa': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-node': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-builtins': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-to-fsa': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-node-utils': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-print': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/fs-snapshot': 4.57.1(tslib@2.8.1) + '@jsonjoy.com/json-pack': 1.21.0(tslib@2.8.1) + '@jsonjoy.com/util': 1.9.0(tslib@2.8.1) + glob-to-regex.js: 1.2.0(tslib@2.8.1) + thingies: 2.6.0(tslib@2.8.1) + tree-dump: 1.1.0(tslib@2.8.1) + tslib: 2.8.1 + + merge-descriptors@1.0.3: {} + + merge-stream@2.0.0: {} + + methods@1.1.2: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + miller-rabin@4.0.1: + dependencies: + bn.js: 4.12.3 + brorand: 1.1.0 + + mime-db@1.52.0: {} + + mime-db@1.54.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime-types@3.0.2: + dependencies: + mime-db: 1.54.0 + + mime@1.6.0: {} + + mime@3.0.0: {} + + mimic-fn@2.1.0: {} + + mini-css-extract-plugin@2.10.0(webpack@5.105.4): + dependencies: + schema-utils: 4.3.3 + tapable: 2.3.2 + webpack: 5.105.4 + + minimalistic-assert@1.0.1: {} + + minimalistic-crypto-utils@1.0.1: {} + + minimatch@3.0.8: + dependencies: + brace-expansion: 1.1.13 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.13 + + minimatch@3.1.5: + dependencies: + brace-expansion: 1.1.13 + + minimatch@5.1.9: + dependencies: + brace-expansion: 2.0.3 + + minimatch@9.0.9: + dependencies: + brace-expansion: 2.0.3 + + minimist@1.2.6: {} + + minimist@1.2.8: {} + + minipass@7.1.3: {} + + mocha@10.8.2: + dependencies: + ansi-colors: 4.1.3 + browser-stdout: 1.3.1 + chokidar: 3.6.0 + debug: 4.4.3(supports-color@8.1.1) + diff: 5.2.2 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 8.1.0 + he: 1.2.0 + js-yaml: 4.1.1 + log-symbols: 4.1.0 + minimatch: 5.1.9 + ms: 2.1.3 + serialize-javascript: 6.0.2 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 6.5.1 + yargs: 16.2.0 + yargs-parser: 20.2.9 + yargs-unparser: 2.0.0 + + modify-source-webpack-plugin@4.1.0(webpack@5.105.4): + dependencies: + loader-utils-webpack-v4: loader-utils@2.0.4 + schema-utils: 4.3.3 + webpack: 5.105.4 + + moment-timezone@0.6.1: + dependencies: + moment: 2.30.1 + + moment@2.30.1: {} + + more-entropy@0.0.7: + dependencies: + iced-runtime: 1.0.4 + + morgan@1.10.1: + dependencies: + basic-auth: 2.0.1 + debug: 2.6.9 + depd: 2.0.0 + on-finished: 2.3.0 + on-headers: 1.1.0 + transitivePeerDependencies: + - supports-color + + mrmime@2.0.1: {} + + ms@2.0.0: {} + + ms@2.1.2: {} + + ms@2.1.3: {} + + multicast-dns@7.2.5: + dependencies: + dns-packet: 5.6.1 + thunky: 1.1.0 + + mute-stream@0.0.8: {} + + nanoid@3.3.11: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + negotiator@0.6.4: {} + + neo-async@2.6.2: {} + + netmask@2.0.2: {} + + ngeohash@0.6.3: {} + + nightwatch-axe-verbose@2.5.1: + dependencies: + axe-core: 4.11.1 + + nightwatch@3.15.0(chromedriver@143.0.4): + dependencies: + '@nightwatch/chai': 5.0.3 + '@nightwatch/html-reporter-template': 0.3.0 + '@nightwatch/nightwatch-inspector': 1.0.1 + '@types/chai': 4.3.20 + '@types/selenium-webdriver': 4.35.5 + ansi-to-html: 0.7.2 + aria-query: 5.1.3 + assertion-error: 1.1.0 + boxen: 5.1.2 + chai-nightwatch: 0.5.3 + chalk: 4.1.2 + ci-info: 3.3.0 + cli-table3: 0.6.5 + devtools-protocol: 0.0.1140464 + didyoumean: 1.2.2 + dotenv: 16.3.1 + ejs: 3.1.10 + envinfo: 7.11.0 + glob: 7.2.3 + jsdom: 24.1.3 + lodash: 4.17.23 + minimatch: 3.1.2 + minimist: 1.2.6 + mocha: 10.8.2 + nightwatch-axe-verbose: 2.5.1 + open: 8.4.2 + ora: 5.4.1 + piscina: 4.9.2 + selenium-webdriver: 4.27.0 + semver: 7.5.4 + stacktrace-parser: 0.1.10 + strip-ansi: 6.0.1 + untildify: 4.0.0 + uuid: 8.3.2 + optionalDependencies: + chromedriver: 143.0.4 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-forge@1.4.0: {} + + node-md6@0.1.0: {} + + node-releases@2.0.36: {} + + nodom@2.4.0: {} + + nofilter@3.1.0: {} + + nopt@3.0.6: + dependencies: + abbrev: 1.1.1 + + nopt@4.0.3: + dependencies: + abbrev: 1.1.1 + osenv: 0.1.5 + + normalize-path@3.0.0: {} + + notepack.io@3.0.1: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + ntlm@0.1.3: {} + + nwmatcher@1.4.4: {} + + nwsapi@2.2.23: {} + + object-assign@4.1.1: {} + + object-inspect@1.13.4: {} + + object-is@1.1.6: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.defaults@1.1.0: + dependencies: + array-each: 1.0.1 + array-slice: 1.1.0 + for-own: 1.0.0 + isobject: 3.0.1 + + object.map@1.0.1: + dependencies: + for-own: 1.0.0 + make-iterator: 1.0.1 + + object.pick@1.3.0: + dependencies: + isobject: 3.0.1 + + obuf@1.1.2: {} + + omggif@1.0.10: {} + + on-finished@2.3.0: + dependencies: + ee-first: 1.1.1 + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + on-headers@1.1.0: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + open@10.2.0: + dependencies: + default-browser: 5.5.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + wsl-utils: 0.1.0 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + opencollective-postinstall@2.0.3: {} + + opener@1.5.2: {} + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + + os-homedir@1.0.2: {} + + os-tmpdir@1.0.2: {} + + osenv@0.1.5: + dependencies: + os-homedir: 1.0.2 + os-tmpdir: 1.0.2 + + otpauth@9.3.6: + dependencies: + '@noble/hashes': 1.6.1 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-retry@6.2.1: + dependencies: + '@types/retry': 0.12.2 + is-network-error: 1.3.1 + retry: 0.13.1 + + pac-proxy-agent@7.2.0: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.4 + debug: 4.4.3(supports-color@8.1.1) + get-uri: 6.0.5 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.0.2 + + package-json-from-dist@1.0.1: {} + + pad-stream@2.0.0: + dependencies: + pumpify: 1.5.1 + split2: 2.2.0 + through2: 2.0.5 + + pako@1.0.11: {} + + param-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.8.1 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parent-module@2.0.0: + dependencies: + callsites: 3.1.0 + + parse-asn1@5.1.9: + dependencies: + asn1.js: 4.10.1 + browserify-aes: 1.2.0 + evp_bytestokey: 1.0.3 + pbkdf2: 3.1.5 + safe-buffer: 5.2.1 + + parse-bmfont-ascii@1.0.6: {} + + parse-bmfont-binary@1.0.6: {} + + parse-bmfont-xml@1.1.6: + dependencies: + xml-parse-from-string: 1.0.1 + xml2js: 0.5.0 + + parse-filepath@1.0.2: + dependencies: + is-absolute: 1.0.0 + map-cache: 0.2.2 + path-root: 0.1.1 + + parse-imports@2.2.1: + dependencies: + es-module-lexer: 1.7.0 + slashes: 3.0.12 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.29.0 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-passwd@1.0.0: {} + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + parseurl@1.3.3: {} + + pascal-case@3.1.2: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-root-regex@0.1.2: {} + + path-root@0.1.1: + dependencies: + path-root-regex: 0.1.2 + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + + path-to-regexp@0.1.13: {} + + path@0.12.7: + dependencies: + process: 0.11.10 + util: 0.10.4 + + pathval@1.1.1: {} + + pbkdf2@3.1.5: + dependencies: + create-hash: 1.2.0 + create-hmac: 1.1.7 + ripemd160: 2.0.3 + safe-buffer: 5.2.1 + sha.js: 2.4.12 + to-buffer: 1.2.2 + + peek-readable@4.1.0: {} + + pend@1.2.0: {} + + pgp-utils@0.0.35: + dependencies: + iced-error: 0.0.13 + iced-runtime: 1.0.4 + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.4: {} + + pify@2.3.0: {} + + piscina@4.9.2: + optionalDependencies: + '@napi-rs/nice': 1.1.1 + + pixelmatch@5.3.0: + dependencies: + pngjs: 6.0.0 + + pngjs@6.0.0: {} + + pngjs@7.0.0: {} + + popper.js@1.16.1: {} + + portscanner@2.2.0: + dependencies: + async: 2.6.4 + is-number-like: 1.0.8 + + possible-typed-array-names@1.1.0: {} + + postcss-css-variables@0.19.0(postcss@8.5.8): + dependencies: + balanced-match: 1.0.2 + escape-string-regexp: 1.0.5 + extend: 3.0.2 + postcss: 8.5.8 + + postcss-import@16.1.1(postcss@8.5.8): + dependencies: + postcss: 8.5.8 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.11 + + postcss-loader@8.2.1(postcss@8.5.8)(webpack@5.105.4): + dependencies: + cosmiconfig: 9.0.1 + jiti: 2.6.1 + postcss: 8.5.8 + semver: 7.7.4 + optionalDependencies: + webpack: 5.105.4 + transitivePeerDependencies: + - typescript + + postcss-modules-extract-imports@3.1.0(postcss@8.5.8): + dependencies: + postcss: 8.5.8 + + postcss-modules-local-by-default@4.2.0(postcss@8.5.8): + dependencies: + icss-utils: 5.1.0(postcss@8.5.8) + postcss: 8.5.8 + postcss-selector-parser: 7.1.1 + postcss-value-parser: 4.2.0 + + postcss-modules-scope@3.2.1(postcss@8.5.8): + dependencies: + postcss: 8.5.8 + postcss-selector-parser: 7.1.1 + + postcss-modules-values@4.0.0(postcss@8.5.8): + dependencies: + icss-utils: 5.1.0(postcss@8.5.8) + postcss: 8.5.8 + + postcss-selector-parser@7.1.1: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.5.8: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + pretty-error@4.0.0: + dependencies: + lodash: 4.17.23 + renderkid: 3.0.0 + + process-nextick-args@2.0.1: {} + + process@0.11.10: {} + + progress@1.1.8: {} + + prompt@1.3.0: + dependencies: + '@colors/colors': 1.5.0 + async: 3.2.3 + read: 1.0.7 + revalidator: 0.1.8 + winston: 2.4.7 + + protobufjs@7.5.4: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 25.5.0 + long: 5.3.2 + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + proxy-agent@6.5.0: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@8.1.1) + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + lru-cache: 7.18.3 + pac-proxy-agent: 7.2.0 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.5 + transitivePeerDependencies: + - supports-color + + proxy-from-env@1.1.0: {} + + proxy-from-env@2.1.0: {} + + psl@1.15.0: + dependencies: + punycode: 2.3.1 + + public-encrypt@4.0.3: + dependencies: + bn.js: 4.12.3 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + parse-asn1: 5.1.9 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + pump@2.0.1: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + pumpify@1.5.1: + dependencies: + duplexify: 3.7.1 + inherits: 2.0.4 + pump: 2.0.1 + + punycode.js@2.3.1: {} + + punycode@1.4.1: {} + + punycode@2.3.1: {} + + purepack@1.0.6: {} + + qr-image@3.2.0: {} + + qs@6.14.2: + dependencies: + side-channel: 1.1.0 + + qs@6.15.0: + dependencies: + side-channel: 1.1.0 + + querystringify@2.2.0: {} + + quick-lru@5.1.1: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + randomfill@1.0.4: + dependencies: + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + range-parser@1.2.1: {} + + raw-body@1.1.7: + dependencies: + bytes: 1.0.0 + string_decoder: 0.10.31 + + raw-body@2.5.3: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.1 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + read@1.0.7: + dependencies: + mute-stream: 0.0.8 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readable-stream@4.7.0: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + + readable-web-to-node-stream@3.0.4: + dependencies: + readable-stream: 4.7.0 + + readdir-glob@1.1.3: + dependencies: + minimatch: 5.1.9 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.2 + + rechoir@0.7.1: + dependencies: + resolve: 1.22.11 + + reflect-metadata@0.2.2: {} + + regenerate-unicode-properties@10.2.2: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + regenerator-runtime@0.11.1: {} + + regenerator-runtime@0.13.11: {} + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + regexpu-core@6.4.0: + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.2 + regjsgen: 0.8.0 + regjsparser: 0.13.0 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.1 + + regjsgen@0.8.0: {} + + regjsparser@0.13.0: + dependencies: + jsesc: 3.1.0 + + relateurl@0.2.7: {} + + renderkid@3.0.0: + dependencies: + css-select: 4.3.0 + dom-converter: 0.2.0 + htmlparser2: 6.1.0 + lodash: 4.17.23 + strip-ansi: 6.0.1 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + requires-port@1.0.0: {} + + resolve-alpn@1.2.1: {} + + resolve-dir@1.0.1: + dependencies: + expand-tilde: 2.0.2 + global-modules: 1.0.0 + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + retry@0.13.1: {} + + revalidator@0.1.8: {} + + rimraf@2.7.1: + dependencies: + glob: 7.2.3 + + rimraf@5.0.10: + dependencies: + glob: 10.5.0 + + ripemd160@2.0.3: + dependencies: + hash-base: 3.1.2 + inherits: 2.0.4 + + rison@0.1.1: {} + + robust-predicates@3.0.3: {} + + rrweb-cssom@0.7.1: {} + + rrweb-cssom@0.8.0: {} + + run-applescript@7.1.0: {} + + rw@1.3.3: {} + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-json-parse@1.0.1: {} + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safer-buffer@2.1.2: {} + + sax@1.6.0: {} + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + schema-utils@3.3.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.14.0 + ajv-keywords: 3.5.2(ajv@6.14.0) + + schema-utils@4.3.3: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.18.0 + ajv-formats: 2.1.1(ajv@8.18.0) + ajv-keywords: 5.1.0(ajv@8.18.0) + + scryptsy@2.1.0: {} + + select-hose@2.0.0: {} + + selenium-webdriver@4.27.0: + dependencies: + '@bazel/runfiles': 6.5.0 + jszip: 3.10.1 + tmp: 0.2.5 + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.14 + node-forge: 1.4.0 + + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.5.4: + dependencies: + lru-cache: 6.0.0 + + semver@7.7.4: {} + + send@0.19.2: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.1 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.2 + transitivePeerDependencies: + - supports-color + + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + serve-index@1.9.2: + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9 + escape-html: 1.0.3 + http-errors: 1.8.1 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.3: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.2 + transitivePeerDependencies: + - supports-color + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + setimmediate@1.0.5: {} + + setprototypeof@1.2.0: {} + + sha.js@2.4.12: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shell-quote@1.8.3: {} + + shelljs@0.5.3: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + simple-xml-to-json@1.2.4: {} + + sirv@2.0.4: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + + sitemap@8.0.3: + dependencies: + '@types/node': 17.0.45 + '@types/sax': 1.2.7 + arg: 5.0.2 + sax: 1.6.0 + + slashes@3.0.12: {} + + smart-buffer@4.2.0: {} + + snackbarjs@1.1.0: {} + + sockjs@0.3.24: + dependencies: + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.4 + + socks-proxy-agent@8.0.5: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3(supports-color@8.1.1) + socks: 2.8.7 + transitivePeerDependencies: + - supports-color + + socks@2.8.7: + dependencies: + ip-address: 10.1.0 + smart-buffer: 4.2.0 + + sortablejs@1.15.7: {} + + source-map-js@1.2.1: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@4.0.0: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.23 + + spdx-license-ids@3.0.23: {} + + spdy-transport@3.0.0: + dependencies: + debug: 4.4.3(supports-color@8.1.1) + detect-node: 2.1.0 + hpack.js: 2.1.6 + obuf: 1.1.2 + readable-stream: 3.6.2 + wbuf: 1.7.3 + transitivePeerDependencies: + - supports-color + + spdy@4.0.2: + dependencies: + debug: 4.4.3(supports-color@8.1.1) + handle-thing: 2.0.1 + http-deceiver: 1.2.7 + select-hose: 2.0.0 + spdy-transport: 3.0.0 + transitivePeerDependencies: + - supports-color + + split.js@1.6.5: {} + + split2@2.2.0: + dependencies: + through2: 2.0.5 + + sprintf-js@1.0.3: {} + + sprintf-js@1.1.3: {} + + ssdeep.js@0.0.3: {} + + stack-trace@0.0.10: {} + + stacktrace-parser@0.1.10: + dependencies: + type-fest: 0.7.1 + + statuses@1.5.0: {} + + statuses@2.0.2: {} + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + stream-browserify@3.0.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + + stream-shift@1.0.3: {} + + string-template@0.2.1: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + + string_decoder@0.10.31: {} + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@3.0.1: + dependencies: + ansi-regex: 2.1.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + strip-comments@2.0.1: {} + + strip-final-newline@2.0.0: {} + + strip-json-comments@3.1.1: {} + + strtok3@6.3.0: + dependencies: + '@tokenizer/token': 0.3.0 + peek-readable: 4.1.0 + + style-mod@4.1.3: {} + + supports-color@2.0.0: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + symbol-tree@3.2.4: {} + + synckit@0.9.3: + dependencies: + '@pkgr/core': 0.1.2 + tslib: 2.8.1 + + tapable@2.3.2: {} + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.5 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + tcp-port-used@1.0.2: + dependencies: + debug: 4.3.1 + is2: 2.0.9 + transitivePeerDependencies: + - supports-color + + terser-webpack-plugin@5.4.0(webpack@5.105.4): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + jest-worker: 27.5.1 + schema-utils: 4.3.3 + terser: 5.46.1 + webpack: 5.105.4 + + terser@5.46.1: + dependencies: + '@jridgewell/source-map': 0.3.11 + acorn: 8.16.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + tesseract.js-core@5.1.1: {} + + tesseract.js@5.1.1: + dependencies: + bmp-js: 0.1.0 + idb-keyval: 6.2.2 + is-electron: 2.2.2 + is-url: 1.2.4 + node-fetch: 2.7.0 + opencollective-postinstall: 2.0.3 + regenerator-runtime: 0.13.11 + tesseract.js-core: 5.1.1 + wasm-feature-detect: 1.8.0 + zlibjs: 0.3.1 + transitivePeerDependencies: + - encoding + + thingies@2.6.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + through2@2.0.5: + dependencies: + readable-stream: 2.3.8 + xtend: 4.0.2 + + thunky@1.1.0: {} + + tiny-lr@1.1.1: + dependencies: + body: 5.1.0 + debug: 3.2.7 + faye-websocket: 0.10.0 + livereload-js: 2.4.0 + object-assign: 4.1.1 + qs: 6.15.0 + transitivePeerDependencies: + - supports-color + + tinycolor2@1.6.0: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tmp@0.2.5: {} + + to-buffer@1.2.2: + dependencies: + isarray: 2.0.5 + safe-buffer: 5.2.1 + typed-array-buffer: 1.0.3 + + to-fast-properties@1.0.3: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toastr@2.1.4: + dependencies: + jquery: 3.7.1 + + toidentifier@1.0.1: {} + + token-types@4.2.1: + dependencies: + '@tokenizer/token': 0.3.0 + ieee754: 1.2.1 + + totalist@3.0.1: {} + + tough-cookie@4.1.4: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + tr46@0.0.3: {} + + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + + tree-dump@1.1.0(tslib@2.8.1): + dependencies: + tslib: 2.8.1 + + triplesec@4.0.3: + dependencies: + iced-error: 0.0.13 + iced-lock: 1.1.0 + iced-runtime: 1.0.4 + more-entropy: 0.0.7 + progress: 1.1.8 + uglify-js: 3.19.3 + + tslib@2.8.1: {} + + tweetnacl@0.13.3: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-detect@4.0.8: {} + + type-fest@0.20.2: {} + + type-fest@0.7.1: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + ua-parser-js@1.0.41: {} + + uc.micro@2.1.0: {} + + uglify-js@3.19.3: {} + + uint64be@1.0.1: {} + + unc-path-regex@0.1.2: {} + + underscore.string@3.3.6: + dependencies: + sprintf-js: 1.1.3 + util-deprecate: 1.0.2 + + undici-types@7.18.2: {} + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.2.0 + + unicode-match-property-value-ecmascript@2.2.1: {} + + unicode-property-aliases-ecmascript@2.2.0: {} + + universalify@0.2.0: {} + + unorm@1.6.0: {} + + unpipe@1.0.0: {} + + untildify@4.0.0: {} + + update-browserslist-db@1.2.3(browserslist@4.28.1): + dependencies: + browserslist: 4.28.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + + url@0.11.4: + dependencies: + punycode: 1.4.1 + qs: 6.15.0 + + urlsafe-base64@1.0.0: {} + + utf8@3.0.0: {} + + utif2@4.1.0: + dependencies: + pako: 1.0.11 + + util-deprecate@1.0.2: {} + + util@0.10.4: + dependencies: + inherits: 2.0.3 + + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.2.0 + is-generator-function: 1.1.2 + is-typed-array: 1.1.15 + which-typed-array: 1.1.20 + + utila@0.4.0: {} + + utils-merge@1.0.1: {} + + uuid@13.0.0: {} + + uuid@8.3.2: {} + + v8flags@3.2.0: + dependencies: + homedir-polyfill: 1.0.3 + + vary@1.1.2: {} + + vkbeautify@0.99.3: {} + + vscode-languageserver-textdocument@1.0.12: {} + + vscode-uri@3.1.0: {} + + w3c-keyname@2.2.8: {} + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + wasm-feature-detect@1.8.0: {} + + watchpack@2.5.1: + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + + wbuf@1.7.3: + dependencies: + minimalistic-assert: 1.0.1 + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + webidl-conversions@3.0.1: {} + + webidl-conversions@7.0.0: {} + + webpack-bundle-analyzer@4.10.2: + dependencies: + '@discoveryjs/json-ext': 0.5.7 + acorn: 8.16.0 + acorn-walk: 8.3.5 + commander: 7.2.0 + debounce: 1.2.1 + escape-string-regexp: 4.0.0 + gzip-size: 6.0.0 + html-escaper: 2.0.2 + opener: 1.5.2 + picocolors: 1.1.1 + sirv: 2.0.4 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + webpack-dev-middleware@7.4.5(tslib@2.8.1)(webpack@5.105.4): + dependencies: + colorette: 2.0.20 + memfs: 4.57.1(tslib@2.8.1) + mime-types: 3.0.2 + on-finished: 2.4.1 + range-parser: 1.2.1 + schema-utils: 4.3.3 + optionalDependencies: + webpack: 5.105.4 + transitivePeerDependencies: + - tslib + + webpack-dev-server@5.0.4(tslib@2.8.1)(webpack@5.105.4): + dependencies: + '@types/bonjour': 3.5.13 + '@types/connect-history-api-fallback': 1.5.4 + '@types/express': 4.17.25 + '@types/serve-index': 1.9.4 + '@types/serve-static': 1.15.10 + '@types/sockjs': 0.3.36 + '@types/ws': 8.18.1 + ansi-html-community: 0.0.8 + bonjour-service: 1.3.0 + chokidar: 3.6.0 + colorette: 2.0.20 + compression: 1.8.1 + connect-history-api-fallback: 2.0.0 + default-gateway: 6.0.3 + express: 4.22.1 + graceful-fs: 4.2.11 + html-entities: 2.6.0 + http-proxy-middleware: 2.0.9(@types/express@4.17.25) + ipaddr.js: 2.3.0 + launch-editor: 2.13.2 + open: 10.2.0 + p-retry: 6.2.1 + rimraf: 5.0.10 + schema-utils: 4.3.3 + selfsigned: 2.4.1 + serve-index: 1.9.2 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack-dev-middleware: 7.4.5(tslib@2.8.1)(webpack@5.105.4) + ws: 8.20.0 + optionalDependencies: + webpack: 5.105.4 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - tslib + - utf-8-validate + + webpack-node-externals@3.0.0: {} + + webpack-sources@3.3.4: {} + + webpack@5.105.4: + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.16.0 + acorn-import-phases: 1.0.4(acorn@8.16.0) + browserslist: 4.28.1 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.20.1 + es-module-lexer: 2.0.0 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.1 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 4.3.3 + tapable: 2.3.2 + terser-webpack-plugin: 5.4.0(webpack@5.105.4) + watchpack: 2.5.1 + webpack-sources: 3.3.4 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + + websocket-driver@0.7.4: + dependencies: + http-parser-js: 0.5.10 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + + websocket-extensions@0.1.4: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.20: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + widest-line@3.1.0: + dependencies: + string-width: 4.2.3 + + winston@2.4.7: + dependencies: + async: 2.6.4 + colors: 1.0.3 + cycle: 1.0.3 + eyes: 0.1.8 + isstream: 0.1.2 + stack-trace: 0.0.10 + + word-wrap@1.2.5: {} + + wordwrap@1.0.0: {} + + worker-loader@3.0.8(webpack@5.105.4): + dependencies: + loader-utils: 2.0.4 + schema-utils: 3.3.0 + webpack: 5.105.4 + + workerpool@6.5.1: {} + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + + wrappy@1.0.2: {} + + ws@7.5.10: {} + + ws@8.20.0: {} + + wsl-utils@0.1.0: + dependencies: + is-wsl: 3.1.1 + + xdg-basedir@5.1.0: {} + + xml-name-validator@5.0.0: {} + + xml-parse-from-string@1.0.1: {} + + xml2js@0.5.0: + dependencies: + sax: 1.6.0 + xmlbuilder: 11.0.1 + + xmlbuilder@11.0.1: {} + + xmlchars@2.2.0: {} + + xpath@0.0.34: {} + + xregexp@5.1.2: + dependencies: + '@babel/runtime-corejs3': 7.29.2 + + xtend@4.0.2: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yallist@4.0.0: {} + + yaml@2.8.3: {} + + yargs-parser@20.2.9: {} + + yargs-unparser@2.0.0: + dependencies: + camelcase: 6.3.0 + decamelize: 4.0.0 + flat: 5.0.2 + is-plain-obj: 2.1.0 + + yargs@16.2.0: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 + + yocto-queue@0.1.0: {} + + zip-stream@4.1.1: + dependencies: + archiver-utils: 3.0.4 + compress-commons: 4.1.2 + readable-stream: 3.6.2 + + zlibjs@0.3.1: {} + + zod@3.25.76: {} diff --git a/plugins/srktoolbox/postcss.config.js b/plugins/srktoolbox/postcss.config.js new file mode 100644 index 00000000..2d46543d --- /dev/null +++ b/plugins/srktoolbox/postcss.config.js @@ -0,0 +1,9 @@ +module.exports = { + plugins: [ + require("postcss-import"), + require("autoprefixer"), + require("postcss-css-variables")({ + preserve: true + }), + ] +}; diff --git a/plugins/srktoolbox/public/logo.png b/plugins/srktoolbox/public/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..55db1fc247bb994dee469d153e96288952ba08dd GIT binary patch literal 4272 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 B@A3cu literal 0 HcmV?d00001 diff --git a/plugins/srktoolbox/public/plugin.json b/plugins/srktoolbox/public/plugin.json new file mode 100644 index 00000000..3a9aeafa --- /dev/null +++ b/plugins/srktoolbox/public/plugin.json @@ -0,0 +1,81 @@ +{ +<<<<<<< HEAD + "name": "srktoolbox", + "title": "SRK Toolbox for Ztools", + "description": "基于 CyberChef 的中文安全工具箱,支持编码、加密、压缩和数据分析。", + "author": "Raka-loah&&LAOBILAXI233", + "version": "10.22.1", + "main": "index.html", + "logo": "logo.png", + "pluginSetting": { + "height": 900 + }, + "development": { + "main": "http://localhost:54333" + }, + "features": [ + { + "code": "srk-toolbox", + "explain": "打开 SRK Toolbox 工具箱", + "icon": "logo.png", + "cmds": [ + "SRK Toolbox", + "srk", + "toolbox", + "工具箱", + "密码工具", + "编码转换", + "CyberChef" +======= + "$schema": "node_modules/@ztools-center/ztools-api-types/resource/ztools.schema.json", + "name": "vanusee", + "title": "SRK Toolbox for ztools", + "description": "A ZTools plugin", + "author": "laobi", + "version": "1.0.0", + "main": "index.html", + "preload": "preload/services.js", + "logo": "logo.png", + "development": { + "main": "http://localhost:5173" + }, + "features": [ + { + "code": "hello", + "explain": "这是插件应用的第一个功能", + "icon": "logo.png", + "cmds": ["你好", "hello"] + }, + { + "code": "read", + "explain": "功能指令+匹配指令示例,使用 node.js 能力读文件", + "icon": "logo.png", + "cmds": [ + "读文件", + { + "type": "files", + "fileType": "file", + "maxLength": 1, + "label": "读文件" + } + ] + }, + { + "code": "write", + "explain": "匹配指令示例,使用 node.js 能力写文件", + "icon": "logo.png", + "mainHide": true, + "cmds": [ + { + "type": "over", + "label": "保存为文件" + }, + { + "type": "img", + "label": "保存为文件" + } +>>>>>>> 334f3fc (first commit) + ] + } + ] +} diff --git a/plugins/srktoolbox/public/preload/package.json b/plugins/srktoolbox/public/preload/package.json new file mode 100644 index 00000000..5bbefffb --- /dev/null +++ b/plugins/srktoolbox/public/preload/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/plugins/srktoolbox/public/preload/services.js b/plugins/srktoolbox/public/preload/services.js new file mode 100644 index 00000000..83c3ef1f --- /dev/null +++ b/plugins/srktoolbox/public/preload/services.js @@ -0,0 +1,27 @@ +const fs = require('node:fs') +const path = require('node:path') + +// 通过 window 对象向渲染进程注入 nodejs 能力 +window.services = { + // 读文件 + readFile(file) { + return fs.readFileSync(file, { encoding: 'utf-8' }) + }, + // 文本写入到下载目录 + writeTextFile(text) { + const filePath = path.join(window.ztools.getPath('downloads'), Date.now().toString() + '.txt') + fs.writeFileSync(filePath, text, { encoding: 'utf-8' }) + return filePath + }, + // 图片写入到下载目录 + writeImageFile(base64Url) { + const matchs = /^data:image\/([a-z]{1,20});base64,/i.exec(base64Url) + if (!matchs) return + const filePath = path.join( + window.ztools.getPath('downloads'), + Date.now().toString() + '.' + matchs[1] + ) + fs.writeFileSync(filePath, base64Url.substring(matchs[0].length), { encoding: 'base64' }) + return filePath + } +} diff --git a/plugins/srktoolbox/src/App.vue b/plugins/srktoolbox/src/App.vue new file mode 100644 index 00000000..d4fabacb --- /dev/null +++ b/plugins/srktoolbox/src/App.vue @@ -0,0 +1,25 @@ + + + diff --git a/plugins/srktoolbox/src/Hello/index.vue b/plugins/srktoolbox/src/Hello/index.vue new file mode 100644 index 00000000..8fc58146 --- /dev/null +++ b/plugins/srktoolbox/src/Hello/index.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/plugins/srktoolbox/src/Read/index.vue b/plugins/srktoolbox/src/Read/index.vue new file mode 100644 index 00000000..903fea36 --- /dev/null +++ b/plugins/srktoolbox/src/Read/index.vue @@ -0,0 +1,105 @@ + + + + + diff --git a/plugins/srktoolbox/src/Write/index.vue b/plugins/srktoolbox/src/Write/index.vue new file mode 100644 index 00000000..f8021de0 --- /dev/null +++ b/plugins/srktoolbox/src/Write/index.vue @@ -0,0 +1,40 @@ + + + diff --git a/plugins/srktoolbox/src/core/Chef.mjs b/plugins/srktoolbox/src/core/Chef.mjs new file mode 100644 index 00000000..ab8f83de --- /dev/null +++ b/plugins/srktoolbox/src/core/Chef.mjs @@ -0,0 +1,183 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Dish from "./Dish.mjs"; +import Recipe from "./Recipe.mjs"; +import log from "loglevel"; +import { isWorkerEnvironment } from "./Utils.mjs"; + +/** + * The main controller for CyberChef. + */ +class Chef { + + /** + * Chef constructor + */ + constructor() { + this.dish = new Dish(); + } + + + /** + * Runs the recipe over the input. + * + * @param {string|ArrayBuffer} input - The input data as a string or ArrayBuffer + * @param {Object[]} recipeConfig - The recipe configuration object + * @param {Object} [options={}] - The options object storing various user choices + * @param {string} [options.returnType] - What type to return the result as + * + * @returns {Object} response + * @returns {string} response.result - The output of the recipe + * @returns {string} response.type - The data type of the result + * @returns {number} response.progress - The position that we have got to in the recipe + * @returns {number} response.duration - The number of ms it took to execute the recipe + * @returns {number} response.error - The error object thrown by a failed operation (false if no error) + */ + async bake(input, recipeConfig, options={}) { + log.debug("Chef baking"); + const startTime = Date.now(), + recipe = new Recipe(recipeConfig), + containsFc = recipe.containsFlowControl(); + let error = false, + progress = 0; + + if (containsFc && isWorkerEnvironment()) self.setOption("attemptHighlight", false); + + // Load data + const type = input instanceof ArrayBuffer ? Dish.ARRAY_BUFFER : Dish.STRING; + this.dish.set(input, type); + + try { + progress = await recipe.execute(this.dish, progress); + } catch (err) { + log.error(err); + error = { + displayStr: err.displayStr, + }; + progress = err.progress; + } + + // Create a raw version of the dish, unpresented + const rawDish = this.dish.clone(); + + // Present the raw result + await recipe.present(this.dish); + + const returnType = + this.dish.type === Dish.HTML ? Dish.HTML : + options?.returnType ? options.returnType : Dish.ARRAY_BUFFER; + + return { + dish: rawDish, + result: await this.dish.get(returnType), + type: Dish.enumLookup(this.dish.type), + progress: progress, + duration: Date.now() - startTime, + error: error + }; + } + + + /** + * When a browser tab is unfocused and the browser has to run lots of dynamic content in other tabs, + * it swaps out the memory for that tab. If the CyberChef tab has been unfocused for more than a + * minute, we run a silent bake which will force the browser to load and cache all the relevant + * JavaScript code needed to do a real bake. + * + * This will stop baking taking a long time when the CyberChef browser tab has been unfocused for a + * long time and the browser has swapped out all its memory. + * + * The output will not be modified (hence "silent" bake). + * + * This will only actually execute the recipe if auto-bake is enabled, otherwise it will just load + * the recipe, ingredients and dish. + * + * @param {Object[]} recipeConfig - The recipe configuration object + * @returns {number} The time it took to run the silent bake in milliseconds. + */ + silentBake(recipeConfig) { + log.debug("Running silent bake"); + + const startTime = Date.now(), + recipe = new Recipe(recipeConfig), + dish = new Dish(); + + try { + recipe.execute(dish); + } catch (err) { + // Suppress all errors + } + return Date.now() - startTime; + } + + + /** + * Calculates highlight offsets if possible. + * + * @param {Object[]} recipeConfig + * @param {string} direction + * @param {Object} pos - The position object for the highlight. + * @param {number} pos.start - The start offset. + * @param {number} pos.end - The end offset. + * @returns {Object} + */ + async calculateHighlights(recipeConfig, direction, pos) { + const recipe = new Recipe(recipeConfig); + const highlights = await recipe.generateHighlightList(); + + if (!highlights) return false; + + for (let i = 0; i < highlights.length; i++) { + // Remove multiple highlights before processing again + pos = [pos[0]]; + + const func = direction === "forward" ? highlights[i].f : highlights[i].b; + + if (typeof func == "function") { + try { + pos = func(pos, highlights[i].args); + } catch (err) { + // Throw away highlighting errors + pos = []; + } + } + } + + return { + pos: pos, + direction: direction + }; + } + + + /** + * Translates the dish to a specified type and returns it. + * + * @param {Dish} dish + * @param {string} type + * @returns {Dish} + */ + async getDishAs(dish, type) { + const newDish = new Dish(dish); + return await newDish.get(type); + } + + /** + * Gets the title of a dish and returns it + * + * @param {Dish} dish + * @param {number} [maxLength=100] + * @returns {string} + */ + async getDishTitle(dish, maxLength=100) { + const newDish = new Dish(dish); + return await newDish.getTitle(maxLength); + } + +} + +export default Chef; diff --git a/plugins/srktoolbox/src/core/ChefWorker.js b/plugins/srktoolbox/src/core/ChefWorker.js new file mode 100644 index 00000000..db3d8815 --- /dev/null +++ b/plugins/srktoolbox/src/core/ChefWorker.js @@ -0,0 +1,294 @@ +/** + * Web Worker to handle communications between the front-end and the core. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + */ + +import Chef from "./Chef.mjs"; +<<<<<<< HEAD +import OperationConfig from "./config/OperationConfig.json" with {type: "json"}; +======= +import OperationConfig from "./config/OperationConfig.json" assert {type: "json"}; +>>>>>>> 334f3fc (first commit) +import OpModules from "./config/modules/OpModules.mjs"; +import loglevelMessagePrefix from "loglevel-message-prefix"; + + +// Set up Chef instance +self.chef = new Chef(); + +self.OpModules = OpModules; +self.OperationConfig = OperationConfig; +self.inputNum = -1; + + +// Tell the app that the worker has loaded and is ready to operate +self.postMessage({ + action: "workerLoaded", + data: {} +}); + +/** + * Respond to message from parent thread. + * + * inputNum is optional and only used for baking multiple inputs. + * Defaults to -1 when one isn't sent with the bake message. + * + * Messages should have the following format: + * { + * action: "bake" | "silentBake", + * data: { + * input: {string}, + * recipeConfig: {[Object]}, + * options: {Object}, + * progress: {number}, + * step: {boolean}, + * [inputNum=-1]: {number} + * } + * } + */ +self.addEventListener("message", function(e) { + // Handle message + const r = e.data; + log.debug(`Receiving command '${r.action}'`); + + switch (r.action) { + case "bake": + bake(r.data); + break; + case "silentBake": + silentBake(r.data); + break; + case "getDishAs": + getDishAs(r.data); + break; + case "getDishTitle": + getDishTitle(r.data); + break; + case "docURL": + // Used to set the URL of the current document so that scripts can be + // imported into an inline worker. + self.docURL = r.data; + break; + case "highlight": + calculateHighlights( + r.data.recipeConfig, + r.data.direction, + r.data.pos + ); + break; + case "setLogLevel": + log.setLevel(r.data, false); + break; + case "setLogPrefix": + loglevelMessagePrefix(log, { + prefixes: [], + staticPrefixes: [r.data] + }); + break; + default: + break; + } +}); + + +/** + * Baking handler + * + * @param {Object} data + */ +async function bake(data) { + // Ensure the relevant modules are loaded + self.loadRequiredModules(data.recipeConfig); + try { + self.inputNum = data.inputNum === undefined ? -1 : data.inputNum; + const response = await self.chef.bake( + data.input, // The user's input + data.recipeConfig, // The configuration of the recipe + data.options // Options set by the user + ); + + const transferable = (response.dish.value instanceof ArrayBuffer) ? + [response.dish.value] : + undefined; + + self.postMessage({ + action: "bakeComplete", + data: Object.assign(response, { + id: data.id, + inputNum: data.inputNum, + bakeId: data.bakeId + }) + }, transferable); + + } catch (err) { + self.postMessage({ + action: "bakeError", + data: { + error: err.message || err, + id: data.id, + inputNum: data.inputNum + } + }); + } + self.inputNum = -1; +} + + +/** + * Silent baking handler + */ +function silentBake(data) { + const duration = self.chef.silentBake(data.recipeConfig); + + self.postMessage({ + action: "silentBakeComplete", + data: duration + }); +} + + +/** + * Translates the dish to a given type. + */ +async function getDishAs(data) { + const value = await self.chef.getDishAs(data.dish, data.type); + const transferable = (data.type === "ArrayBuffer") ? [value] : undefined; + self.postMessage({ + action: "dishReturned", + data: { + value: value, + id: data.id + } + }, transferable); +} + + +/** + * Gets the dish title + * + * @param {object} data + * @param {Dish} data.dish + * @param {number} data.maxLength + * @param {number} data.id + */ +async function getDishTitle(data) { + const title = await self.chef.getDishTitle(data.dish, data.maxLength); + self.postMessage({ + action: "dishReturned", + data: { + value: title, + id: data.id + } + }); +} + + +/** + * Calculates highlight offsets if possible. + * + * @param {Object[]} recipeConfig + * @param {string} direction + * @param {Object[]} pos - The position object for the highlight. + * @param {number} pos.start - The start offset. + * @param {number} pos.end - The end offset. + */ +async function calculateHighlights(recipeConfig, direction, pos) { + pos = await self.chef.calculateHighlights(recipeConfig, direction, pos); + + self.postMessage({ + action: "highlightsCalculated", + data: pos + }); +} + + +/** + * Checks that all required modules are loaded and loads them if not. + * + * @param {Object} recipeConfig + */ +self.loadRequiredModules = function(recipeConfig) { + recipeConfig.forEach(op => { + const module = self.OperationConfig[op.op].module; + + if (!(module in OpModules)) { + log.info(`Loading ${module} module`); + self.sendStatusMessage(`Loading ${module} module`); + self.importScripts(`${self.docURL}/modules/${module}.js`); // lgtm [js/client-side-unvalidated-url-redirection] + self.sendStatusMessage(""); + } + }); +}; + + +/** + * Send status update to the app. + * + * @param {string} msg + */ +self.sendStatusMessage = function(msg) { + self.postMessage({ + action: "statusMessage", + data: { + message: msg, + inputNum: self.inputNum + } + }); +}; + + +/** + * Send progress update to the app. + * + * @param {number} progress + * @param {number} total + */ +self.sendProgressMessage = function(progress, total) { + self.postMessage({ + action: "progressMessage", + data: { + progress: progress, + total: total, + inputNum: self.inputNum + } + }); +}; + + +/** + * Send an option value update to the app. + * + * @param {string} option + * @param {*} value + */ +self.setOption = function(option, value) { + self.postMessage({ + action: "optionUpdate", + data: { + option: option, + value: value + } + }); +}; + + +/** + * Send register values back to the app. + * + * @param {number} opIndex + * @param {number} numPrevRegisters + * @param {string[]} registers + */ +self.setRegisters = function(opIndex, numPrevRegisters, registers) { + self.postMessage({ + action: "setRegisters", + data: { + opIndex: opIndex, + numPrevRegisters: numPrevRegisters, + registers: registers + } + }); +}; diff --git a/plugins/srktoolbox/src/core/Dish.mjs b/plugins/srktoolbox/src/core/Dish.mjs new file mode 100644 index 00000000..11b1ff9f --- /dev/null +++ b/plugins/srktoolbox/src/core/Dish.mjs @@ -0,0 +1,569 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @author Matt C [matt@artemisbot.uk] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Utils, { isNodeEnvironment } from "./Utils.mjs"; +import DishError from "./errors/DishError.mjs"; +import BigNumber from "bignumber.js"; +import { detectFileType } from "./lib/FileType.mjs"; +import log from "loglevel"; + +import DishByteArray from "./dishTypes/DishByteArray.mjs"; +import DishBigNumber from "./dishTypes/DishBigNumber.mjs"; +import DishFile from "./dishTypes/DishFile.mjs"; +import DishHTML from "./dishTypes/DishHTML.mjs"; +import DishJSON from "./dishTypes/DishJSON.mjs"; +import DishListFile from "./dishTypes/DishListFile.mjs"; +import DishNumber from "./dishTypes/DishNumber.mjs"; +import DishString from "./dishTypes/DishString.mjs"; + + +/** + * The data being operated on by each operation. + */ +class Dish { + + /** + * Dish constructor + * + * @param {Dish || *} [dishOrInput=null] - A dish to clone OR an object + * literal to make into a dish + * @param {Enum} [type=null] (optional) - A type to accompany object + * literal input + */ + constructor(dishOrInput=null, type = null) { + this.value = new ArrayBuffer(0); + this.type = Dish.ARRAY_BUFFER; + + // Case: dishOrInput is dish object + if (dishOrInput && + Object.prototype.hasOwnProperty.call(dishOrInput, "value") && + Object.prototype.hasOwnProperty.call(dishOrInput, "type")) { + this.set(dishOrInput.value, dishOrInput.type); + // input and type defined separately + } else if (dishOrInput && type !== null) { + this.set(dishOrInput, type); + // No type declared, so infer it. + } else if (dishOrInput) { + const inferredType = Dish.typeEnum(dishOrInput.constructor.name); + this.set(dishOrInput, inferredType); + } + } + + + /** + * Returns the data type enum for the given type string. + * + * @param {string} typeStr - The name of the data type. + * @returns {number} The data type enum value. + */ + static typeEnum(typeStr) { + switch (typeStr.toLowerCase()) { + case "bytearray": + case "byte array": + return Dish.BYTE_ARRAY; + case "string": + return Dish.STRING; + case "number": + return Dish.NUMBER; + case "html": + return Dish.HTML; + case "arraybuffer": + case "array buffer": + return Dish.ARRAY_BUFFER; + case "bignumber": + case "big number": + return Dish.BIG_NUMBER; + case "json": + case "object": // object constructor name. To allow JSON input in node. + return Dish.JSON; + case "file": + return Dish.FILE; + case "list": + return Dish.LIST_FILE; + default: + throw new DishError("Invalid data type string. No matching enum."); + } + } + + + /** + * Returns the data type string for the given type enum. + * + * @param {number} typeEnum - The enum value of the data type. + * @returns {string} The data type as a string. + */ + static enumLookup(typeEnum) { + switch (typeEnum) { + case Dish.BYTE_ARRAY: + return "byteArray"; + case Dish.STRING: + return "string"; + case Dish.NUMBER: + return "number"; + case Dish.HTML: + return "html"; + case Dish.ARRAY_BUFFER: + return "ArrayBuffer"; + case Dish.BIG_NUMBER: + return "BigNumber"; + case Dish.JSON: + return "JSON"; + case Dish.FILE: + return "File"; + case Dish.LIST_FILE: + return "List"; + default: + throw new DishError("Invalid data type enum. No matching type."); + } + } + + + /** + * Returns the value of the data in the type format specified. + * + * If running in a browser, get is asynchronous. + * + * @param {number} type - The data type of value, see Dish enums. + * @returns {* | Promise} - (Browser) A promise | (Node) value of dish in given type + */ + get(type) { + if (typeof type === "string") { + type = Dish.typeEnum(type); + } + + if (this.type !== type) { + + // Node environment => _translate is sync + if (isNodeEnvironment()) { + this._translate(type); + return this.value; + + // Browser environment => _translate is async + } else { + return new Promise((resolve, reject) => { + this._translate(type) + .then(() => { + resolve(this.value); + }) + .catch(reject); + }); + } + } + + return this.value; + } + + + /** + * Sets the data value and type and then validates them. + * + * @param {*} value + * - The value of the input data. + * @param {number} type + * - The data type of value, see Dish enums. + */ + set(value, type) { + if (typeof type === "string") { + type = Dish.typeEnum(type); + } + + log.debug("Dish type: " + Dish.enumLookup(type)); + this.value = value; + this.type = type; + + if (!this.valid()) { + const sample = Utils.truncate(JSON.stringify(this.value), 25); + throw new DishError(`Data is not a valid ${Dish.enumLookup(type)}: ${sample}`); + } + } + + /** + * Returns the Dish as the given type, without mutating the original dish. + * + * If running in a browser, get is asynchronous. + * + * @Node + * + * @param {number} type - The data type of value, see Dish enums. + * @returns {Dish | Promise} - (Browser) A promise | (Node) value of dish in given type + */ + presentAs(type) { + const clone = this.clone(); + return clone.get(type); + } + + + /** + * Detects the MIME type of the current dish + * @returns {string} + */ + detectDishType() { + const data = new Uint8Array(this.value.slice(0, 2048)), + types = detectFileType(data); + + if (!types.length || !types[0].mime || !(types[0].mime === "text/plain")) { + return null; + } else { + return types[0].mime; + } + } + + + /** + * Returns the title of the data up to the specified length + * + * @param {number} maxLength - The maximum title length + * @returns {string} + */ + async getTitle(maxLength) { + let title = ""; + let cloned; + + switch (this.type) { + case Dish.FILE: + title = this.value.name; + break; + case Dish.LIST_FILE: + title = `${this.value.length} file(s)`; + break; + case Dish.JSON: + title = "application/json"; + break; + case Dish.NUMBER: + case Dish.BIG_NUMBER: + title = this.value.toString(); + break; + case Dish.ARRAY_BUFFER: + case Dish.BYTE_ARRAY: + title = this.detectDishType(); + if (title !== null) break; + // fall through if no mime type was detected + default: + try { + cloned = this.clone(); + cloned.value = cloned.value.slice(0, 256); + title = await cloned.get(Dish.STRING); + } catch (err) { + log.error(`${Dish.enumLookup(this.type)} cannot be sliced. ${err}`); + } + } + + return title.slice(0, maxLength); + } + + /** + * Validates that the value is the type that has been specified. + * May have to disable parts of BYTE_ARRAY validation if it effects performance. + * + * @returns {boolean} Whether the data is valid or not. + */ + valid() { + switch (this.type) { + case Dish.BYTE_ARRAY: + if (!(this.value instanceof Uint8Array) && !(this.value instanceof Array)) { + return false; + } + + // Check that every value is a number between 0 - 255 + for (let i = 0; i < this.value.length; i++) { + if (typeof this.value[i] !== "number" || + this.value[i] < 0 || + this.value[i] > 255) { + return false; + } + } + return true; + case Dish.STRING: + case Dish.HTML: + return typeof this.value === "string"; + case Dish.NUMBER: + return typeof this.value === "number"; + case Dish.ARRAY_BUFFER: + return this.value instanceof ArrayBuffer; + case Dish.BIG_NUMBER: + if (BigNumber.isBigNumber(this.value)) return true; + /* + If a BigNumber is passed between WebWorkers it is serialised as a JSON + object with a coefficient (c), exponent (e) and sign (s). We detect this + and reinitialise it as a BigNumber object. + */ + if (Object.keys(this.value).sort().equals(["c", "e", "s"])) { + const temp = new BigNumber(); + temp.c = this.value.c; + temp.e = this.value.e; + temp.s = this.value.s; + this.value = temp; + return true; + } + return false; + case Dish.JSON: + // All values can be serialised in some manner, so we return true in all cases + return true; + case Dish.FILE: + return this.value instanceof File; + case Dish.LIST_FILE: + return this.value instanceof Array && + this.value.reduce((acc, curr) => acc && curr instanceof File, true); + default: + return false; + } + } + + + /** + * Determines how much space the Dish takes up. + * Numbers in JavaScript are 64-bit floating point, however for the purposes of the Dish, + * we measure how many bytes are taken up when the number is written as a string. + * + * @returns {number} + */ + get size() { + switch (this.type) { + case Dish.BYTE_ARRAY: + case Dish.STRING: + case Dish.HTML: + return this.value.length; + case Dish.NUMBER: + case Dish.BIG_NUMBER: + return this.value.toString().length; + case Dish.ARRAY_BUFFER: + return this.value.byteLength; + case Dish.JSON: + return JSON.stringify(this.value).length; + case Dish.FILE: + return this.value.size; + case Dish.LIST_FILE: + return this.value.reduce((acc, curr) => acc + curr.size, 0); + default: + return -1; + } + } + + + /** + * Returns a deep clone of the current Dish. + * + * @returns {Dish} + */ + clone() { + const newDish = new Dish(); + + switch (this.type) { + case Dish.STRING: + case Dish.HTML: + case Dish.NUMBER: + case Dish.BIG_NUMBER: + // These data types are immutable so it is acceptable to copy them by reference + newDish.set( + this.value, + this.type + ); + break; + case Dish.BYTE_ARRAY: + case Dish.JSON: + // These data types are mutable so they need to be copied by value + newDish.set( + JSON.parse(JSON.stringify(this.value)), + this.type + ); + break; + case Dish.ARRAY_BUFFER: + // Slicing an ArrayBuffer returns a new ArrayBuffer with a copy its contents + newDish.set( + this.value.slice(0), + this.type + ); + break; + case Dish.FILE: + // A new file can be created by copying over all the values from the original + newDish.set( + new File([this.value], this.value.name, { + "type": this.value.type, + "lastModified": this.value.lastModified + }), + this.type + ); + break; + case Dish.LIST_FILE: + newDish.set( + this.value.map(f => + new File([f], f.name, { + "type": f.type, + "lastModified": f.lastModified + }) + ), + this.type + ); + break; + default: + throw new DishError("Cannot clone Dish, unknown type"); + } + + return newDish; + } + + /** + * Translates the data to the given type format. + * + * If running in the browser, _translate is asynchronous. + * + * @param {number} toType - The data type of value, see Dish enums. + * @returns {Promise || undefined} + */ + _translate(toType) { + log.debug(`Translating Dish from ${Dish.enumLookup(this.type)} to ${Dish.enumLookup(toType)}`); + + // Node environment => translate is sync + if (isNodeEnvironment()) { + this._toArrayBuffer(); + this.type = Dish.ARRAY_BUFFER; + this._fromArrayBuffer(toType); + + // Browser environment => translate is async + } else { + return new Promise((resolve, reject) => { + this._toArrayBuffer() + .then(() => this.type = Dish.ARRAY_BUFFER) + .then(() => { + this._fromArrayBuffer(toType); + resolve(); + }) + .catch(reject); + }); + } + + } + + /** + * Convert this.value to an ArrayBuffer + * + * If running in a browser, _toByteArray is asynchronous. + * + * @returns {Promise || undefined} + */ + _toArrayBuffer() { + // Using 'bind' here to allow this.value to be mutated within translation functions + const toByteArrayFuncs = { + browser: { + [Dish.STRING]: () => Promise.resolve(DishString.toArrayBuffer.bind(this)()), + [Dish.NUMBER]: () => Promise.resolve(DishNumber.toArrayBuffer.bind(this)()), + [Dish.HTML]: () => Promise.resolve(DishHTML.toArrayBuffer.bind(this)()), + [Dish.ARRAY_BUFFER]: () => Promise.resolve(), + [Dish.BIG_NUMBER]: () => Promise.resolve(DishBigNumber.toArrayBuffer.bind(this)()), + [Dish.JSON]: () => Promise.resolve(DishJSON.toArrayBuffer.bind(this)()), + [Dish.FILE]: () => DishFile.toArrayBuffer.bind(this)(), + [Dish.LIST_FILE]: () => Promise.resolve(DishListFile.toArrayBuffer.bind(this)()), + [Dish.BYTE_ARRAY]: () => Promise.resolve(DishByteArray.toArrayBuffer.bind(this)()), + }, + node: { + [Dish.STRING]: () => DishString.toArrayBuffer.bind(this)(), + [Dish.NUMBER]: () => DishNumber.toArrayBuffer.bind(this)(), + [Dish.HTML]: () => DishHTML.toArrayBuffer.bind(this)(), + [Dish.ARRAY_BUFFER]: () => {}, + [Dish.BIG_NUMBER]: () => DishBigNumber.toArrayBuffer.bind(this)(), + [Dish.JSON]: () => DishJSON.toArrayBuffer.bind(this)(), + [Dish.FILE]: () => DishFile.toArrayBuffer.bind(this)(), + [Dish.LIST_FILE]: () => DishListFile.toArrayBuffer.bind(this)(), + [Dish.BYTE_ARRAY]: () => DishByteArray.toArrayBuffer.bind(this)(), + } + }; + + try { + return toByteArrayFuncs[isNodeEnvironment() && "node" || "browser"][this.type](); + } catch (err) { + throw new DishError(`Error translating from ${Dish.enumLookup(this.type)} to ArrayBuffer: ${err}`); + } + } + + /** + * Convert this.value to the given type from ArrayBuffer + * + * @param {number} toType - the Dish enum to convert to + */ + _fromArrayBuffer(toType) { + + // Using 'bind' here to allow this.value to be mutated within translation functions + const toTypeFunctions = { + [Dish.STRING]: () => DishString.fromArrayBuffer.bind(this)(), + [Dish.NUMBER]: () => DishNumber.fromArrayBuffer.bind(this)(), + [Dish.HTML]: () => DishHTML.fromArrayBuffer.bind(this)(), + [Dish.ARRAY_BUFFER]: () => {}, + [Dish.BIG_NUMBER]: () => DishBigNumber.fromArrayBuffer.bind(this)(), + [Dish.JSON]: () => DishJSON.fromArrayBuffer.bind(this)(), + [Dish.FILE]: () => DishFile.fromArrayBuffer.bind(this)(), + [Dish.LIST_FILE]: () => DishListFile.fromArrayBuffer.bind(this)(), + [Dish.BYTE_ARRAY]: () => DishByteArray.fromArrayBuffer.bind(this)(), + }; + + try { + toTypeFunctions[toType](); + this.type = toType; + } catch (err) { + throw new DishError(`Error translating from ArrayBuffer to ${Dish.enumLookup(toType)}: ${err}`); + } + } + +} + + +/** + * Dish data type enum for byte arrays. + * @readonly + * @enum + */ +Dish.BYTE_ARRAY = 0; +/** + * Dish data type enum for strings. + * @readonly + * @enum + */ +Dish.STRING = 1; +/** + * Dish data type enum for numbers. + * @readonly + * @enum + */ +Dish.NUMBER = 2; +/** + * Dish data type enum for HTML. + * @readonly + * @enum + */ +Dish.HTML = 3; +/** + * Dish data type enum for ArrayBuffers. + * @readonly + * @enum + */ +Dish.ARRAY_BUFFER = 4; +/** + * Dish data type enum for BigNumbers. + * @readonly + * @enum + */ +Dish.BIG_NUMBER = 5; +/** + * Dish data type enum for JSON. + * @readonly + * @enum + */ +Dish.JSON = 6; +/** + * Dish data type enum for lists of files. + * @readonly + * @enum + */ +Dish.FILE = 7; +/** +* Dish data type enum for lists of files. +* @readonly +* @enum +*/ +Dish.LIST_FILE = 8; + + +export default Dish; diff --git a/plugins/srktoolbox/src/core/Ingredient.mjs b/plugins/srktoolbox/src/core/Ingredient.mjs new file mode 100644 index 00000000..319dfb15 --- /dev/null +++ b/plugins/srktoolbox/src/core/Ingredient.mjs @@ -0,0 +1,132 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Utils from "./Utils.mjs"; +import {fromHex} from "./lib/Hex.mjs"; + +/** + * The arguments to operations. + */ +class Ingredient { + + /** + * Ingredient constructor + * + * @param {Object} ingredientConfig + */ + constructor(ingredientConfig) { + this.name = ""; + this.type = ""; + this._value = null; + this.disabled = false; + this.hint = ""; + this.rows = 0; + this.toggleValues = []; + this.target = null; + this.defaultIndex = 0; + this.maxLength = null; + this.min = null; + this.max = null; + this.step = 1; + + if (ingredientConfig) { + this._parseConfig(ingredientConfig); + } + } + + + /** + * Reads and parses the given config. + * + * @private + * @param {Object} ingredientConfig + */ + _parseConfig(ingredientConfig) { + this.name = ingredientConfig.name; + this.type = ingredientConfig.type; + this.defaultValue = ingredientConfig.value; + this.disabled = !!ingredientConfig.disabled; + this.hint = ingredientConfig.hint || false; + this.rows = ingredientConfig.rows || false; + this.toggleValues = ingredientConfig.toggleValues; + this.target = typeof ingredientConfig.target !== "undefined" ? ingredientConfig.target : null; + this.defaultIndex = typeof ingredientConfig.defaultIndex !== "undefined" ? ingredientConfig.defaultIndex : 0; + this.maxLength = ingredientConfig.maxLength || null; + this.min = ingredientConfig.min; + this.max = ingredientConfig.max; + this.step = ingredientConfig.step; + } + + + /** + * Returns the value of the Ingredient as it should be displayed in a recipe config. + * + * @returns {*} + */ + get config() { + return this._value; + } + + + /** + * Sets the value of the Ingredient. + * + * @param {*} value + */ + set value(value) { + this._value = Ingredient.prepare(value, this.type); + } + + + /** + * Gets the value of the Ingredient. + * + * @returns {*} + */ + get value() { + return this._value; + } + + + /** + * Most values will be strings when they are entered. This function converts them to the correct + * type. + * + * @param {*} data + * @param {string} type - The name of the data type. + */ + static prepare(data, type) { + let number; + + switch (type) { + case "binaryString": + case "binaryShortString": + case "editableOption": + case "editableOptionShort": + return Utils.parseEscapedChars(data); + case "byteArray": + if (typeof data == "string") { + data = data.replace(/\s+/g, ""); + return fromHex(data); + } else { + return data; + } + case "number": + if (data === null) return data; + number = parseFloat(data); + if (isNaN(number)) { + const sample = Utils.truncate(data.toString(), 10); + throw "Invalid ingredient value. Not a number: " + sample; + } + return number; + default: + return data; + } + } + +} + +export default Ingredient; diff --git a/plugins/srktoolbox/src/core/Operation.mjs b/plugins/srktoolbox/src/core/Operation.mjs new file mode 100644 index 00000000..24739d3f --- /dev/null +++ b/plugins/srktoolbox/src/core/Operation.mjs @@ -0,0 +1,322 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Dish from "./Dish.mjs"; +import Ingredient from "./Ingredient.mjs"; + +/** + * The Operation specified by the user to be run. + */ +class Operation { + + /** + * Operation constructor + */ + constructor() { + // Private fields + this._inputType = -1; + this._outputType = -1; + this._presentType = -1; + this._breakpoint = false; + this._disabled = false; + this._flowControl = false; + this._manualBake = false; + this._ingList = []; + + // Public fields + this.name = ""; + this.module = ""; + this.description = ""; + this.infoURL = null; + } + + + /** + * Interface for operation runner + * + * @param {*} input + * @param {Object[]} args + * @returns {*} + */ + run(input, args) { + return input; + } + + + /** + * Interface for forward highlighter + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return false; + } + + + /** + * Interface for reverse highlighter + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return false; + } + + + /** + * Method to be called when displaying the result of an operation in a human-readable + * format. This allows operations to return usable data from their run() method and + * only format them when this method is called. + * + * The default action is to return the data unchanged, but child classes can override + * this behaviour. + * + * @param {*} data - The result of the run() function + * @param {Object[]} args - The operation's arguments + * @returns {*} - A human-readable version of the data + */ + present(data, args) { + return data; + } + + + /** + * Sets the input type as a Dish enum. + * + * @param {string} typeStr + */ + set inputType(typeStr) { + this._inputType = Dish.typeEnum(typeStr); + } + + + /** + * Gets the input type as a readable string. + * + * @returns {string} + */ + get inputType() { + return Dish.enumLookup(this._inputType); + } + + + /** + * Sets the output type as a Dish enum. + * + * @param {string} typeStr + */ + set outputType(typeStr) { + this._outputType = Dish.typeEnum(typeStr); + if (this._presentType < 0) this._presentType = this._outputType; + } + + + /** + * Gets the output type as a readable string. + * + * @returns {string} + */ + get outputType() { + return Dish.enumLookup(this._outputType); + } + + + /** + * Sets the presentation type as a Dish enum. + * + * @param {string} typeStr + */ + set presentType(typeStr) { + this._presentType = Dish.typeEnum(typeStr); + } + + + /** + * Gets the presentation type as a readable string. + * + * @returns {string} + */ + get presentType() { + return Dish.enumLookup(this._presentType); + } + + + /** + * Sets the args for the current operation. + * + * @param {Object[]} conf + */ + set args(conf) { + conf.forEach(arg => { + const ingredient = new Ingredient(arg); + this.addIngredient(ingredient); + }); + } + + + /** + * Gets the args for the current operation. + * + * @param {Object[]} conf + */ + get args() { + return this._ingList.map(ing => { + const conf = { + name: ing.name, + type: ing.type, + value: ing.defaultValue + }; + + if (ing.toggleValues) conf.toggleValues = ing.toggleValues; + if (ing.hint) conf.hint = ing.hint; + if (ing.rows) conf.rows = ing.rows; + if (ing.disabled) conf.disabled = ing.disabled; + if (ing.target) conf.target = ing.target; + if (ing.defaultIndex) conf.defaultIndex = ing.defaultIndex; + if (ing.maxLength) conf.maxLength = ing.maxLength; + if (typeof ing.min === "number") conf.min = ing.min; + if (typeof ing.max === "number") conf.max = ing.max; + if (ing.step) conf.step = ing.step; + return conf; + }); + } + + + /** + * Returns the value of the Operation as it should be displayed in a recipe config. + * + * @returns {Object} + */ + get config() { + return { + "op": this.name, + "args": this._ingList.map(ing => ing.config) + }; + } + + + /** + * Adds a new Ingredient to this Operation. + * + * @param {Ingredient} ingredient + */ + addIngredient(ingredient) { + this._ingList.push(ingredient); + } + + + /** + * Set the Ingredient values for this Operation. + * + * @param {Object[]} ingValues + */ + set ingValues(ingValues) { + ingValues.forEach((val, i) => { + this._ingList[i].value = val; + }); + } + + + /** + * Get the Ingredient values for this Operation. + * + * @returns {Object[]} + */ + get ingValues() { + return this._ingList.map(ing => ing.value); + } + + + /** + * Set whether this Operation has a breakpoint. + * + * @param {boolean} value + */ + set breakpoint(value) { + this._breakpoint = !!value; + } + + + /** + * Returns true if this Operation has a breakpoint set. + * + * @returns {boolean} + */ + get breakpoint() { + return this._breakpoint; + } + + + /** + * Set whether this Operation is disabled. + * + * @param {boolean} value + */ + set disabled(value) { + this._disabled = !!value; + } + + + /** + * Returns true if this Operation is disabled. + * + * @returns {boolean} + */ + get disabled() { + return this._disabled; + } + + + /** + * Returns true if this Operation is a flow control. + * + * @returns {boolean} + */ + get flowControl() { + return this._flowControl; + } + + + /** + * Set whether this Operation is a flowcontrol op. + * + * @param {boolean} value + */ + set flowControl(value) { + this._flowControl = !!value; + } + + + /** + * Returns true if this Operation should not trigger AutoBake. + * + * @returns {boolean} + */ + get manualBake() { + return this._manualBake; + } + + + /** + * Set whether this Operation should trigger AutoBake. + * + * @param {boolean} value + */ + set manualBake(value) { + this._manualBake = !!value; + } + +} + +export default Operation; diff --git a/plugins/srktoolbox/src/core/Recipe.mjs b/plugins/srktoolbox/src/core/Recipe.mjs new file mode 100644 index 00000000..7b038069 --- /dev/null +++ b/plugins/srktoolbox/src/core/Recipe.mjs @@ -0,0 +1,358 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +<<<<<<< HEAD +import OperationConfig from "./config/OperationConfig.json" with {type: "json"}; +======= +import OperationConfig from "./config/OperationConfig.json" assert {type: "json"}; +>>>>>>> 334f3fc (first commit) +import OperationError from "./errors/OperationError.mjs"; +import Operation from "./Operation.mjs"; +import DishError from "./errors/DishError.mjs"; +import log from "loglevel"; +import { isWorkerEnvironment } from "./Utils.mjs"; + +// Cache container for modules +let modules = null; + +/** + * The Recipe controls a list of Operations and the Dish they operate on. + */ +class Recipe { + + /** + * Recipe constructor + * + * @param {Object} recipeConfig + */ + constructor(recipeConfig) { + this.opList = []; + + if (recipeConfig) { + this._parseConfig(recipeConfig); + } + } + + + /** + * Reads and parses the given config. + * + * @private + * @param {Object} recipeConfig + */ + _parseConfig(recipeConfig) { + recipeConfig.forEach(c => { + try { + this.opList.push({ + name: c.op, + module: OperationConfig[c.op].module, + ingValues: c.args, + breakpoint: c.breakpoint, + disabled: c.disabled || c.op === "Comment", + }); + } catch (error) { + log.warn(`[WARNING] ${c.op} Not found: ${error}`); + } + + }); + } + + + /** + * Populate elements of opList with operation instances. + * Dynamic import here removes top-level cyclic dependency issue. + * + * @private + */ + async _hydrateOpList() { + if (!modules) { + // Using Webpack Magic Comments to force the dynamic import to be included in the main chunk + // https://webpack.js.org/api/module-methods/ + modules = await import(/* webpackMode: "eager" */ "./config/modules/OpModules.mjs"); + modules = modules.default; + } + + this.opList = this.opList.map(o => { + if (o instanceof Operation) { + return o; + } else { + const op = new modules[o.module][o.name](); + op.ingValues = o.ingValues; + op.breakpoint = o.breakpoint; + op.disabled = o.disabled; + return op; + } + }); + } + + + /** + * Returns the value of the Recipe as it should be displayed in a recipe config. + * + * @returns {Object[]} + */ + get config() { + return this.opList.map(op => ({ + op: op.name, + args: op.ingValues, + })); + } + + + /** + * Adds a new Operation to this Recipe. + * + * @param {Operation} operation + */ + addOperation(operation) { + this.opList.push(operation); + } + + + /** + * Adds a list of Operations to this Recipe. + * + * @param {Operation[]} operations + */ + addOperations(operations) { + operations.forEach(o => { + if (o instanceof Operation) { + this.opList.push(o); + } else { + this.opList.push({ + name: o.name, + module: o.module, + ingValues: o.args, + breakpoint: o.breakpoint, + disabled: o.disabled, + }); + } + }); + } + + + /** + * Set a breakpoint on a specified Operation. + * + * @param {number} position - The index of the Operation + * @param {boolean} value + */ + setBreakpoint(position, value) { + try { + this.opList[position].breakpoint = value; + } catch (err) { + // Ignore index error + } + } + + + /** + * Remove breakpoints on all Operations in the Recipe up to the specified position. Used by Flow + * Control Fork operation. + * + * @param {number} pos + */ + removeBreaksUpTo(pos) { + for (let i = 0; i < pos; i++) { + this.opList[i].breakpoint = false; + } + } + + + /** + * Returns true if there is a Flow Control Operation in this Recipe. + * + * @returns {boolean} + */ + containsFlowControl() { + return this.opList.reduce((acc, curr) => { + return acc || curr.flowControl; + }, false); + } + + + /** + * Executes each operation in the recipe over the given Dish. + * + * @param {Dish} dish + * @param {number} [startFrom=0] + * - The index of the Operation to start executing from + * @param {number} [forkState={}] + * - If this is a forked recipe, the state of the recipe up to this point + * @returns {number} + * - The final progress through the recipe + */ + async execute(dish, startFrom=0, forkState={}) { + let op, input, output, + numJumps = 0, + numRegisters = forkState.numRegisters || 0; + + if (startFrom === 0) this.lastRunOp = null; + + await this._hydrateOpList(); + + log.debug(`[*] Executing recipe of ${this.opList.length} operations, starting at ${startFrom}`); + + for (let i = startFrom; i < this.opList.length; i++) { + op = this.opList[i]; + log.debug(`[${i}] ${op.name} ${JSON.stringify(op.ingValues)}`); + if (op.disabled) { + log.debug("Operation is disabled, skipping"); + continue; + } + if (op.breakpoint) { + log.debug("Pausing at breakpoint"); + return i; + } + + try { + input = await dish.get(op.inputType); + log.debug(`Executing operation '${op.name}'`); + + if (isWorkerEnvironment()) { + self.sendStatusMessage(`执行中... (${i+1}/${this.opList.length})`); + self.sendProgressMessage(i + 1, this.opList.length); + } + + if (op.flowControl) { + // Package up the current state + let state = { + "progress": i, + "dish": dish, + "opList": this.opList, + "numJumps": numJumps, + "numRegisters": numRegisters, + "forkOffset": forkState.forkOffset || 0 + }; + + state = await op.run(state); + i = state.progress; + numJumps = state.numJumps; + numRegisters = state.numRegisters; + } else { + output = await op.run(input, op.ingValues); + dish.set(output, op.outputType); + } + this.lastRunOp = op; + } catch (err) { + log.error(err); + // Return expected errors as output + if (err instanceof OperationError || err?.type === "OperationError") { + // Cannot rely on `err instanceof OperationError` here as extending + // native types is not fully supported yet. + dish.set(err.message, "string"); + return i; + } else if (err instanceof DishError || err?.type === "DishError") { + dish.set(err.message, "string"); + return i; + } else { + const e = typeof err == "string" ? { message: err } : err; + + e.progress = i; + if (e.fileName) { + e.displayStr = `${op.name} - ${e.name} in ${e.fileName} on line ` + + `${e.lineNumber}.

Message: ${e.displayStr || e.message}`; + } else { + e.displayStr = `${op.name} - ${e.displayStr || e.message}`; + } + + throw e; + } + } + } + + log.debug("Recipe complete"); + return this.opList.length; + } + + + /** + * Present the results of the final operation. + * + * @param {Dish} dish + */ + async present(dish) { + if (!this.lastRunOp) return; + + const output = await this.lastRunOp.present( + await dish.get(this.lastRunOp.outputType), + this.lastRunOp.ingValues + ); + dish.set(output, this.lastRunOp.presentType); + } + + + /** + * Returns the recipe configuration in string format. + * + * @returns {string} + */ + toString() { + return JSON.stringify(this.config); + } + + + /** + * Creates a Recipe from a given configuration string. + * + * @param {string} recipeStr + */ + fromString(recipeStr) { + const recipeConfig = JSON.parse(recipeStr); + this._parseConfig(recipeConfig); + } + + + /** + * Generates a list of all the highlight functions assigned to operations in the recipe, if the + * entire recipe supports highlighting. + * + * @returns {Object[]} highlights + * @returns {function} highlights[].f + * @returns {function} highlights[].b + * @returns {Object[]} highlights[].args + */ + async generateHighlightList() { + await this._hydrateOpList(); + const highlights = []; + + for (let i = 0; i < this.opList.length; i++) { + const op = this.opList[i]; + if (op.disabled) continue; + + // If any breakpoints are set, do not attempt to highlight + if (op.breakpoint) return false; + + // If any of the operations do not support highlighting, fail immediately. + if (op.highlight === false || op.highlight === undefined) return false; + + highlights.push({ + f: op.highlight, + b: op.highlightReverse, + args: op.ingValues + }); + } + + return highlights; + } + + + /** + * Determines whether the previous operation has a different presentation type to its normal output. + * + * @param {number} progress + * @returns {boolean} + */ + lastOpPresented(progress) { + if (progress < 1) return false; + return this.opList[progress-1].presentType !== this.opList[progress-1].outputType; + } + +} + +export default Recipe; diff --git a/plugins/srktoolbox/src/core/Utils.mjs b/plugins/srktoolbox/src/core/Utils.mjs new file mode 100644 index 00000000..9a265427 --- /dev/null +++ b/plugins/srktoolbox/src/core/Utils.mjs @@ -0,0 +1,1606 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +// loglevel import required for Node API +import log from "loglevel"; +import utf8 from "utf8"; +import {fromBase64, toBase64} from "./lib/Base64.mjs"; +import {fromHex} from "./lib/Hex.mjs"; +import {fromDecimal} from "./lib/Decimal.mjs"; +import {fromBinary} from "./lib/Binary.mjs"; + +/** + * Utility functions for use in operations, the core framework and the stage. + */ +class Utils { + + /** + * Translates an ordinal into a character. + * + * @param {number} o + * @returns {char} + * + * @example + * // returns 'a' + * Utils.chr(97); + */ + static chr(o) { + // Detect astral symbols + // Thanks to @mathiasbynens for this solution + // https://mathiasbynens.be/notes/javascript-unicode + if (o > 0xffff) { + o -= 0x10000; + const high = String.fromCharCode(o >>> 10 & 0x3ff | 0xd800); + o = 0xdc00 | o & 0x3ff; + return high + String.fromCharCode(o); + } + + return String.fromCharCode(o); + } + + + /** + * Translates a character into an ordinal. + * + * @param {char} c + * @returns {number} + * + * @example + * // returns 97 + * Utils.ord('a'); + */ + static ord(c) { + // Detect astral symbols + // Thanks to @mathiasbynens for this solution + // https://mathiasbynens.be/notes/javascript-unicode + if (c.length === 2) { + const high = c.charCodeAt(0); + const low = c.charCodeAt(1); + if (high >= 0xd800 && high < 0xdc00 && + low >= 0xdc00 && low < 0xe000) { + return (high - 0xd800) * 0x400 + low - 0xdc00 + 0x10000; + } + } + + return c.charCodeAt(0); + } + + + /** + * Adds trailing bytes to a byteArray. + * + * @author tlwr [toby@toby.codes] + * + * @param {byteArray} arr - byteArray to add trailing bytes to. + * @param {number} numBytes - Maximum width of the array. + * @param {Integer} [padByte=0] - The byte to pad with. + * @returns {byteArray} + * + * @example + * // returns ["a", 0, 0, 0] + * Utils.padBytesRight("a", 4); + * + * // returns ["a", 1, 1, 1] + * Utils.padBytesRight("a", 4, 1); + * + * // returns ["t", "e", "s", "t", 0, 0, 0, 0] + * Utils.padBytesRight("test", 8); + * + * // returns ["t", "e", "s", "t", 1, 1, 1, 1] + * Utils.padBytesRight("test", 8, 1); + */ + static padBytesRight(arr, numBytes, padByte=0) { + const paddedBytes = new Array(numBytes); + paddedBytes.fill(padByte); + + [...arr].forEach((b, i) => { + paddedBytes[i] = b; + }); + + return paddedBytes; + } + + + /** + * Truncates a long string to max length and adds suffix. + * + * @param {string} str - String to truncate + * @param {number} max - Maximum length of the final string + * @param {string} [suffix='...'] - The string to add to the end of the final string + * @returns {string} + * + * @example + * // returns "A long..." + * Utils.truncate("A long string", 9); + * + * // returns "A long s-" + * Utils.truncate("A long string", 9, "-"); + */ + static truncate(str, max, suffix="...") { + if (str.length > max) { + str = str.slice(0, max - suffix.length) + suffix; + } + return str; + } + + + /** + * Converts a character or number to its hex representation. + * + * @param {char|number} c + * @param {number} [length=2] - The width of the resulting hex number. + * @returns {string} + * + * @example + * // returns "6e" + * Utils.hex("n"); + * + * // returns "6e" + * Utils.hex(110); + */ + static hex(c, length=2) { + c = typeof c == "string" ? Utils.ord(c) : c; + return c.toString(16).padStart(length, "0"); + } + + + /** + * Converts a character or number to its binary representation. + * + * @param {char|number} c + * @param {number} [length=8] - The width of the resulting binary number. + * @returns {string} + * + * @example + * // returns "01101110" + * Utils.bin("n"); + * + * // returns "01101110" + * Utils.bin(110); + */ + static bin(c, length=8) { + c = typeof c == "string" ? Utils.ord(c) : c; + return c.toString(2).padStart(length, "0"); + } + + + /** + * Returns a string with all non-printable chars as dots, optionally preserving whitespace. + * + * @param {string} str - The input string to display. + * @param {boolean} [preserveWs=false] - Whether or not to print whitespace. + * @param {boolean} [onlyAscii=false] - Whether or not to replace non ASCII characters. + * @returns {string} + */ + static printable(str, preserveWs=false, onlyAscii=false) { + if (onlyAscii) { + return str.replace(/[^\x20-\x7e]/g, "."); + } + + // eslint-disable-next-line no-misleading-character-class + const re = /[\0-\x08\x0B-\x0C\x0E-\x1F\x7F-\x9F\xAD\u0378\u0379\u037F-\u0383\u038B\u038D\u03A2\u0528-\u0530\u0557\u0558\u0560\u0588\u058B-\u058E\u0590\u05C8-\u05CF\u05EB-\u05EF\u05F5-\u0605\u061C\u061D\u06DD\u070E\u070F\u074B\u074C\u07B2-\u07BF\u07FB-\u07FF\u082E\u082F\u083F\u085C\u085D\u085F-\u089F\u08A1\u08AD-\u08E3\u08FF\u0978\u0980\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09FC-\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF2-\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B55\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B78-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BFB-\u0C00\u0C04\u0C0D\u0C11\u0C29\u0C34\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5A-\u0C5F\u0C64\u0C65\u0C70-\u0C77\u0C80\u0C81\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0D01\u0D04\u0D0D\u0D11\u0D3B\u0D3C\u0D45\u0D49\u0D4F-\u0D56\u0D58-\u0D5F\u0D64\u0D65\u0D76-\u0D78\u0D80\u0D81\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DF1\u0DF5-\u0E00\u0E3B-\u0E3E\u0E5C-\u0E80\u0E83\u0E85\u0E86\u0E89\u0E8B\u0E8C\u0E8E-\u0E93\u0E98\u0EA0\u0EA4\u0EA6\u0EA8\u0EA9\u0EAC\u0EBA\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F48\u0F6D-\u0F70\u0F98\u0FBD\u0FCD\u0FDB-\u0FFF\u10C6\u10C8-\u10CC\u10CE\u10CF\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u137D-\u137F\u139A-\u139F\u13F5-\u13FF\u169D-\u169F\u16F1-\u16FF\u170D\u1715-\u171F\u1737-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17DE\u17DF\u17EA-\u17EF\u17FA-\u17FF\u180F\u181A-\u181F\u1878-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191D-\u191F\u192C-\u192F\u193C-\u193F\u1941-\u1943\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DB-\u19DD\u1A1C\u1A1D\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1A9F\u1AAE-\u1AFF\u1B4C-\u1B4F\u1B7D-\u1B7F\u1BF4-\u1BFB\u1C38-\u1C3A\u1C4A-\u1C4C\u1C80-\u1CBF\u1CC8-\u1CCF\u1CF7-\u1CFF\u1DE7-\u1DFB\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FC5\u1FD4\u1FD5\u1FDC\u1FF0\u1FF1\u1FF5\u1FFF\u200B-\u200F\u202A-\u202E\u2060-\u206F\u2072\u2073\u208F\u209D-\u209F\u20BB-\u20CF\u20F1-\u20FF\u218A-\u218F\u23F4-\u23FF\u2427-\u243F\u244B-\u245F\u2700\u2B4D-\u2B4F\u2B5A-\u2BFF\u2C2F\u2C5F\u2CF4-\u2CF8\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D71-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E3C-\u2E7F\u2E9A\u2EF4-\u2EFF\u2FD6-\u2FEF\u2FFC-\u2FFF\u3040\u3097\u3098\u3100-\u3104\u312E-\u3130\u318F\u31BB-\u31BF\u31E4-\u31EF\u321F\u32FF\u4DB6-\u4DBF\u9FCD-\u9FFF\uA48D-\uA48F\uA4C7-\uA4CF\uA62C-\uA63F\uA698-\uA69E\uA6F8-\uA6FF\uA78F\uA794-\uA79F\uA7AB-\uA7F7\uA82C-\uA82F\uA83A-\uA83F\uA878-\uA87F\uA8C5-\uA8CD\uA8DA-\uA8DF\uA8FC-\uA8FF\uA954-\uA95E\uA97D-\uA97F\uA9CE\uA9DA-\uA9DD\uA9E0-\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A\uAA5B\uAA7C-\uAA7F\uAAC3-\uAADA\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F-\uABBF\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBC2-\uFBD2\uFD40-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFE\uFDFF\uFE1A-\uFE1F\uFE27-\uFE2F\uFE53\uFE67\uFE6C-\uFE6F\uFE75\uFEFD-\uFF00\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFDF\uFFE7\uFFEF-\uFFFB\uFFFE\uFFFF]/g; + const wsRe = /[\x09-\x10\u2028\u2029]/g; + + str = str.replace(re, "."); + if (!preserveWs) str = str.replace(wsRe, "."); + return str; + } + + + /** + * Returns a string with whitespace represented as special characters from the + * Unicode Private Use Area, which CyberChef will display as control characters. + * Private Use Area characters are in the range U+E000..U+F8FF. + * https://en.wikipedia.org/wiki/Private_Use_Areas + * @param {string} str + * @returns {string} + */ + static escapeWhitespace(str) { + return str.replace(/[\x09-\x10]/g, function(c) { + return String.fromCharCode(0xe000 + c.charCodeAt(0)); + }); + } + + + /** + * Parse a string entered by a user and replace escaped chars with the bytes they represent. + * + * @param {string} str + * @returns {string} + * + * @example + * // returns "\x00" + * Utils.parseEscapedChars("\\x00"); + * + * // returns "\n" + * Utils.parseEscapedChars("\\n"); + */ + static parseEscapedChars(str) { + return str.replace(/\\([abfnrtv'"]|[0-3][0-7]{2}|[0-7]{1,2}|x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]{1,6}\}|\\)/g, function(m, a) { + switch (a[0]) { + case "\\": + return "\\"; + case "0": + case "1": + case "2": + case "3": + case "4": + case "5": + case "6": + case "7": + return String.fromCharCode(parseInt(a, 8)); + case "a": + return String.fromCharCode(7); + case "b": + return "\b"; + case "t": + return "\t"; + case "n": + return "\n"; + case "v": + return "\v"; + case "f": + return "\f"; + case "r": + return "\r"; + case '"': + return '"'; + case "'": + return "'"; + case "x": + return String.fromCharCode(parseInt(a.substr(1), 16)); + case "u": + if (a[1] === "{") + return String.fromCodePoint(parseInt(a.slice(2, -1), 16)); + else + return String.fromCharCode(parseInt(a.substr(1), 16)); + } + }); + } + + + /** + * Escape a string containing regex control characters so that it can be safely + * used in a regex without causing unintended behaviours. + * + * @param {string} str + * @returns {string} + * + * @example + * // returns "\[example\]" + * Utils.escapeRegex("[example]"); + */ + static escapeRegex(str) { + return str.replace(/([.*+?^=!:${}()|[\]/\\])/g, "\\$1"); + } + + + /** + * Expand an alphabet range string into a list of the characters in that range. + * + * @param {string} alphStr + * @returns {char[]} + * + * @example + * // returns ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] + * Utils.expandAlphRange("0-9"); + * + * // returns ["a", "b", "c", "d", "0", "1", "2", "3", "+", "/"] + * Utils.expandAlphRange("a-d0-3+/"); + * + * // returns ["a", "b", "c", "d", "0", "-", "3"] + * Utils.expandAlphRange("a-d0\\-3") + */ + static expandAlphRange(alphStr) { + const alphArr = []; + + for (let i = 0; i < alphStr.length; i++) { + if (i < alphStr.length - 2 && + alphStr[i+1] === "-" && + alphStr[i] !== "\\") { + const start = Utils.ord(alphStr[i]), + end = Utils.ord(alphStr[i+2]); + + for (let j = start; j <= end; j++) { + alphArr.push(Utils.chr(j)); + } + i += 2; + } else if (i < alphStr.length - 2 && + alphStr[i] === "\\" && + alphStr[i+1] === "-") { + alphArr.push("-"); + i++; + } else { + alphArr.push(alphStr[i]); + } + } + return alphArr; + } + + + /** + * Coverts data of varying types to a byteArray. + * Accepts hex, Base64, UTF8 and Latin1 strings. + * + * @param {string} str + * @param {string} type - One of "Binary", "Hex", "Decimal", "Base64", "UTF8" or "Latin1" + * @returns {byteArray} + * + * @example + * // returns [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130] + * Utils.convertToByteArray("Привет", "utf8"); + * + * // returns [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130] + * Utils.convertToByteArray("d097d0b4d180d0b0d0b2d181d182d0b2d183d0b9d182d0b5", "hex"); + * + * // returns [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130] + * Utils.convertToByteArray("0JfQtNGA0LDQstGB0YLQstGD0LnRgtC1", "base64"); + */ + static convertToByteArray(str, type) { + switch (type.toLowerCase()) { + case "binary": + return fromBinary(str); + case "hex": + return fromHex(str); + case "十六进制": + return fromHex(str); + case "decimal": + return fromDecimal(str); + case "十进制": + return fromDecimal(str); + case "base64": + return fromBase64(str, null, "byteArray"); + case "utf8": + return Utils.strToUtf8ByteArray(str); + case "latin1": + default: + return Utils.strToByteArray(str); + } + } + + + /** + * Coverts data of varying types to a byte string. + * Accepts hex, Base64, UTF8 and Latin1 strings. + * + * @param {string} str + * @param {string} type - One of "Binary", "Hex", "Decimal", "Base64", "UTF8" or "Latin1" + * @returns {string} + * + * @example + * // returns "Привет" + * Utils.convertToByteString("Привет", "utf8"); + * + * // returns "Здравствуйте" + * Utils.convertToByteString("d097d0b4d180d0b0d0b2d181d182d0b2d183d0b9d182d0b5", "hex"); + * + * // returns "Здравствуйте" + * Utils.convertToByteString("0JfQtNGA0LDQstGB0YLQstGD0LnRgtC1", "base64"); + */ + static convertToByteString(str, type) { + switch (type.toLowerCase()) { + case "binary": + return Utils.byteArrayToChars(fromBinary(str)); + case "二进制": + return Utils.byteArrayToChars(fromBinary(str)); + case "十六进制": + return Utils.byteArrayToChars(fromHex(str)); + case "hex": + return Utils.byteArrayToChars(fromHex(str)); + case "十进制": + return Utils.byteArrayToChars(fromDecimal(str)); + case "decimal": + return Utils.byteArrayToChars(fromDecimal(str)); + case "base64": + return Utils.byteArrayToChars(fromBase64(str, null, "byteArray")); + case "utf8": + return utf8.encode(str); + case "latin1": + default: + return str; + } + } + + + /** + * Converts a byte array to an integer. + * + * @param {byteArray} byteArray + * @param {string} byteorder - "little" or "big" + * @returns {integer} + * + * @example + * // returns 67305985 + * Utils.byteArrayToInt([1, 2, 3, 4], "little"); + * + * // returns 16909060 + * Utils.byteArrayToInt([1, 2, 3, 4], "big"); + */ + static byteArrayToInt(byteArray, byteorder) { + let value = 0; + if (byteorder === "big") { + for (let i = 0; i < byteArray.length; i++) { + value = (value * 256) + byteArray[i]; + } + } else { + for (let i = byteArray.length - 1; i >= 0; i--) { + value = (value * 256) + byteArray[i]; + } + } + return value; + } + + + /** + * Converts an integer to a byte array of {length} bytes. + * + * @param {integer} value + * @param {integer} length + * @param {string} byteorder - "little" or "big" + * @returns {byteArray} + * + * @example + * // returns [5, 255, 109, 1] + * Utils.intToByteArray(23985925, 4, "little"); + * + * // returns [1, 109, 255, 5] + * Utils.intToByteArray(23985925, 4, "big"); + * + * // returns [0, 0, 0, 0, 1, 109, 255, 5] + * Utils.intToByteArray(23985925, 8, "big"); + */ + static intToByteArray(value, length, byteorder) { + const arr = new Array(length); + if (byteorder === "little") { + for (let i = 0; i < length; i++) { + arr[i] = value & 0xFF; + value = value >>> 8; + } + } else { + for (let i = length - 1; i >= 0; i--) { + arr[i] = value & 0xFF; + value = value >>> 8; + } + } + return arr; + } + + + /** + * Converts a string to an ArrayBuffer. + * Treats the string as UTF-8 if any values are over 255. + * + * @param {string} str + * @returns {ArrayBuffer} + * + * @example + * // returns [72,101,108,108,111] + * Utils.strToArrayBuffer("Hello"); + * + * // returns [228,189,160,229,165,189] + * Utils.strToArrayBuffer("你好"); + */ + static strToArrayBuffer(str) { + log.debug(`Converting string[${str?.length}] to array buffer`); + if (!str) return new ArrayBuffer; + + const arr = new Uint8Array(str.length); + let i = str.length, b; + while (i--) { + b = str.charCodeAt(i); + arr[i] = b; + // If any of the bytes are over 255, read as UTF-8 + if (b > 255) return Utils.strToUtf8ArrayBuffer(str); + } + return arr.buffer; + } + + + /** + * Converts a string to a UTF-8 ArrayBuffer. + * + * @param {string} str + * @returns {ArrayBuffer} + * + * @example + * // returns [72,101,108,108,111] + * Utils.strToUtf8ArrayBuffer("Hello"); + * + * // returns [228,189,160,229,165,189] + * Utils.strToUtf8ArrayBuffer("你好"); + */ + static strToUtf8ArrayBuffer(str) { + log.debug(`Converting string[${str?.length}] to UTF8 array buffer`); + if (!str) return new ArrayBuffer; + + const buffer = new TextEncoder("utf-8").encode(str); + + if (str.length !== buffer.length) { + if (isWorkerEnvironment() && self && typeof self.setOption === "function") { + self.setOption("attemptHighlight", false); + } else if (isWebEnvironment()) { + window.app.options.attemptHighlight = false; + } + } + + return buffer.buffer; + } + + + /** + * Converts a string to a byte array. + * Treats the string as UTF-8 if any values are over 255. + * + * @param {string} str + * @returns {byteArray} + * + * @example + * // returns [72,101,108,108,111] + * Utils.strToByteArray("Hello"); + * + * // returns [228,189,160,229,165,189] + * Utils.strToByteArray("你好"); + */ + static strToByteArray(str) { + log.debug(`Converting string[${str?.length}] to byte array`); + if (!str) return []; + const byteArray = new Array(str.length); + let i = str.length, b; + while (i--) { + b = str.charCodeAt(i); + byteArray[i] = b; + // If any of the bytes are over 255, read as UTF-8 + if (b > 255) return Utils.strToUtf8ByteArray(str); + } + return byteArray; + } + + + /** + * Converts a string to a UTF-8 byte array. + * + * @param {string} str + * @returns {byteArray} + * + * @example + * // returns [72,101,108,108,111] + * Utils.strToUtf8ByteArray("Hello"); + * + * // returns [228,189,160,229,165,189] + * Utils.strToUtf8ByteArray("你好"); + */ + static strToUtf8ByteArray(str) { + log.debug(`Converting string[${str?.length}] to UTF8 byte array`); + if (!str) return []; + const utf8Str = utf8.encode(str); + + if (str.length !== utf8Str.length) { + if (isWorkerEnvironment()) { + self.setOption("attemptHighlight", false); + } else if (isWebEnvironment()) { + window.app.options.attemptHighlight = false; + } + } + + return Utils.strToByteArray(utf8Str); + } + + + /** + * Converts a string to a unicode charcode array + * + * @param {string} str + * @returns {byteArray} + * + * @example + * // returns [72,101,108,108,111] + * Utils.strToCharcode("Hello"); + * + * // returns [20320,22909] + * Utils.strToCharcode("你好"); + */ + static strToCharcode(str) { + log.debug(`Converting string[${str?.length}] to charcode`); + if (!str) return []; + const charcode = []; + + for (let i = 0; i < str.length; i++) { + let ord = str.charCodeAt(i); + + // Detect and merge astral symbols + if (i < str.length - 1 && ord >= 0xd800 && ord < 0xdc00) { + const low = str[i + 1].charCodeAt(0); + if (low >= 0xdc00 && low < 0xe000) { + ord = Utils.ord(str[i] + str[++i]); + } + } + + charcode.push(ord); + } + + return charcode; + } + + + /** + * Attempts to convert a byte array to a UTF-8 string. + * + * @param {byteArray|Uint8Array} byteArray + * @returns {string} + * + * @example + * // returns "Hello" + * Utils.byteArrayToUtf8([72,101,108,108,111]); + * + * // returns "你好" + * Utils.byteArrayToUtf8([228,189,160,229,165,189]); + */ + static byteArrayToUtf8(byteArray) { + log.debug(`Converting byte array[${byteArray?.length}] to UTF8`); + if (!byteArray || !byteArray.length) return ""; + if (!(byteArray instanceof Uint8Array)) + byteArray = new Uint8Array(byteArray); + + try { + const str = new TextDecoder("utf-8", {fatal: true}).decode(byteArray); + + if (str.length !== byteArray.length) { + if (isWorkerEnvironment()) { + self.setOption("attemptHighlight", false); + } else if (isWebEnvironment()) { + window.app.options.attemptHighlight = false; + } + } + + return str; + } catch (err) { + // If it fails, treat it as ANSI + return Utils.byteArrayToChars(byteArray); + } + } + + + /** + * Converts a charcode array to a string. + * + * @param {byteArray|Uint8Array} byteArray + * @returns {string} + * + * @example + * // returns "Hello" + * Utils.byteArrayToChars([72,101,108,108,111]); + * + * // returns "你好" + * Utils.byteArrayToChars([20320,22909]); + */ + static byteArrayToChars(byteArray) { + log.debug(`Converting byte array[${byteArray?.length}] to chars`); + if (!byteArray || !byteArray.length) return ""; + let str = ""; + // Maxiumum arg length for fromCharCode is 65535, but the stack may already be fairly deep, + // so don't get too near it. + for (let i = 0; i < byteArray.length; i += 20000) { + str += String.fromCharCode(...(byteArray.slice(i, i+20000))); + } + return str; + } + + + /** + * Converts an ArrayBuffer to a string. + * + * @param {ArrayBuffer} arrayBuffer + * @param {boolean} [utf8=true] - Whether to attempt to decode the buffer as UTF-8 + * @returns {string} + * + * @example + * // returns "hello" + * Utils.arrayBufferToStr(Uint8Array.from([104,101,108,108,111]).buffer); + */ + static arrayBufferToStr(arrayBuffer, utf8=true) { + log.debug(`Converting array buffer[${arrayBuffer?.byteLength}] to str`); + if (!arrayBuffer || !arrayBuffer.byteLength) return ""; + const arr = new Uint8Array(arrayBuffer); + return utf8 ? Utils.byteArrayToUtf8(arr) : Utils.byteArrayToChars(arr); + } + + /** + * Calculates the Shannon entropy for a given set of data. + * + * @param {Uint8Array|ArrayBuffer} input + * @returns {number} + */ + static calculateShannonEntropy(data) { + if (data instanceof ArrayBuffer) { + data = new Uint8Array(data); + } + const prob = [], + occurrences = new Array(256).fill(0); + + // Count occurrences of each byte in the input + let i; + for (i = 0; i < data.length; i++) { + occurrences[data[i]]++; + } + + // Store probability list + for (i = 0; i < occurrences.length; i++) { + if (occurrences[i] > 0) { + prob.push(occurrences[i] / data.length); + } + } + + // Calculate Shannon entropy + let entropy = 0, + p; + + for (i = 0; i < prob.length; i++) { + p = prob[i]; + entropy += p * Math.log(p) / Math.log(2); + } + + return -entropy; + } + + + /** + * Parses CSV data and returns it as a two dimensional array or strings. + * + * @param {string} data + * @param {string[]} [cellDelims=[","]] + * @param {string[]} [lineDelims=["\n", "\r"]] + * @returns {string[][]} + * + * @example + * // returns [["head1", "head2"], ["data1", "data2"]] + * Utils.parseCSV("head1,head2\ndata1,data2"); + */ + static parseCSV(data, cellDelims=[","], lineDelims=["\n", "\r"]) { + let b, + next, + renderNext = false, + inString = false, + cell = "", + line = []; + const lines = []; + + // Remove BOM, often present in Excel CSV files + if (data.length && data[0] === "\uFEFF") data = data.substr(1); + + for (let i = 0; i < data.length; i++) { + b = data[i]; + next = data[i+1] || ""; + if (renderNext) { + cell += b; + renderNext = false; + } else if (b === "\"" && !inString) { + inString = true; + } else if (b === "\"" && inString) { + if (next === "\"") renderNext = true; + else inString = false; + } else if (!inString && cellDelims.indexOf(b) >= 0) { + line.push(cell); + cell = ""; + } else if (!inString && lineDelims.indexOf(b) >= 0) { + line.push(cell); + cell = ""; + lines.push(line); + line = []; + // Skip next byte if it is also a line delim (e.g. \r\n) + if (lineDelims.indexOf(next) >= 0 && next !== b) { + i++; + } + } else { + cell += b; + } + } + + if (line.length) { + line.push(cell); + lines.push(line); + } + + return lines; + } + + + /** + * Removes all HTML (or XML) tags from the input string. + * + * @param {string} htmlStr + * @param {boolean} [removeScriptAndStyle=false] + * - Flag to specify whether to remove entire script or style blocks + * @returns {string} + * + * @example + * // returns "Test" + * Utils.stripHtmlTags("
Test
"); + */ + static stripHtmlTags(htmlStr, removeScriptAndStyle=false) { + /** + * Recursively remove a pattern from a string until there are no more matches. + * Avoids incomplete sanitization e.g. "aabcbc".replace(/abc/g, "") === "abc" + * + * @param {RegExp} pattern + * @param {string} str + * @returns {string} + */ + function recursiveRemove(pattern, str) { + const newStr = str.replace(pattern, ""); + return newStr.length === str.length ? newStr : recursiveRemove(pattern, newStr); + } + + if (removeScriptAndStyle) { + htmlStr = recursiveRemove(/]*>(\s|\S)*?<\/script[^>]*>/gi, htmlStr); + htmlStr = recursiveRemove(/]*>(\s|\S)*?<\/style[^>]*>/gi, htmlStr); + } + return recursiveRemove(/<[^>]+>/g, htmlStr); + } + + + /** + * Escapes HTML tags in a string to stop them being rendered. + * https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet + * + * Null bytes are a special case and are converted to a character from the Unicode + * Private Use Area, which CyberChef will display as a control character picture. + * This is done due to null bytes not being rendered or stored correctly in HTML + * DOM building. + * + * @param {string} str + * @returns string + * + * @example + * // return "A <script> tag" + * Utils.escapeHtml("A `; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {json} + */ + run(input, args) { + const visualizationType = args[0]; + input = new Uint8Array(input); + + switch (visualizationType) { + case "图表 (柱状图)": + case "图表 (折线图)": + return this.calculateByteFrequency(input); + case "曲线图": + case "图像": + return this.calculateScanningEntropy(input).entropyData; + case "香农量表": + default: + return this.calculateShannonEntropy(input); + } + } + + /** + * Displays the entropy in a visualisation for web apps. + * + * @param {json} entropyData + * @param {Object[]} args + * @returns {html} + */ + present(entropyData, args) { + const visualizationType = args[0]; + + switch (visualizationType) { + case "图表 (柱状图)": + return this.createByteFrequencyBarHistogram(entropyData); + case "图表 (折线图)": + return this.createByteFrequencyLineHistogram(entropyData); + case "曲线图": + return this.createEntropyCurve(entropyData); + case "图像": + return this.createEntropyImage(entropyData); + case "香农量表": + default: + return this.createShannonEntropyVisualization(entropyData); + } + } +} + +export default Entropy; diff --git a/plugins/srktoolbox/src/core/operations/EscapeString.mjs b/plugins/srktoolbox/src/core/operations/EscapeString.mjs new file mode 100644 index 00000000..40b039c1 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/EscapeString.mjs @@ -0,0 +1,96 @@ +/** + * @author Vel0x [dalemy@microsoft.com] + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import jsesc from "jsesc"; + +/** + * Escape string operation + */ +class EscapeString extends Operation { + + /** + * EscapeString constructor + */ + constructor() { + super(); + + this.name = "转义字符串"; + this.module = "Default"; + this.description = "将字符串中的特殊字符转义,防止和代码发生冲突。例如,Don't stop me now 转义成 Don\\'t stop me now

支持以下的字符转义:
  • \\n (换行,LF)
  • \\r (回车,CR)
  • \\t (制表符)
  • \\b (退格)
  • \\f (换页,FF)
  • \\xnn (十六进制,n是0到f)
  • \\\\ (反斜杠)
  • \\' (单引号)
  • \\" (双引号)
  • \\unnnn (Unicode字符)
  • \\u{nnnnnn} (Unicode码点)
"; + this.infoURL = "https://wikipedia.org/wiki/Escape_sequence"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "转义等级", + "type": "option", + "value": ["特殊字符", "所有", "最少"] + }, + { + "name": "转义引号", + "type": "option", + "value": ["单引号", "双引号", "反勾号"] + }, + { + "name": "JSON兼容", + "type": "boolean", + "value": false + }, + { + "name": "ES6兼容", + "type": "boolean", + "value": true + }, + { + "name": "十六进制大写", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + * + * @example + * EscapeString.run("Don't do that", []) + * > "Don\'t do that" + * EscapeString.run(`Hello + * World`, []) + * > "Hello\nWorld" + */ + run(input, args) { + const level = args[0], + quotes = args[1], + jsonCompat = args[2], + es6Compat = args[3], + lowercaseHex = !args[4]; + + const quotesDict = { + "单引号": "single", + "双引号": "double", + "反勾号": "backtick" + }; + + return jsesc(input, { + quotes: quotesDict[quotes], + es6: es6Compat, + escapeEverything: level === "所有", + minimal: level === "最少", + json: jsonCompat, + lowercaseHex: lowercaseHex, + }); + } + +} + +export default EscapeString; diff --git a/plugins/srktoolbox/src/core/operations/EscapeUnicodeCharacters.mjs b/plugins/srktoolbox/src/core/operations/EscapeUnicodeCharacters.mjs new file mode 100644 index 00000000..b4722621 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/EscapeUnicodeCharacters.mjs @@ -0,0 +1,81 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Escape Unicode Characters operation + */ +class EscapeUnicodeCharacters extends Operation { + + /** + * EscapeUnicodeCharacters constructor + */ + constructor() { + super(); + + this.name = "Unicode字符转义"; + this.module = "Default"; + this.description = "把Unicode字符根据选定的前缀格式进行转义。

支持以下前缀:
  • \\u
  • %u
  • U+
例: σου 编码为 \\u03C3\\u03BF\\u03C5"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "前缀", + "type": "option", + "value": ["\\u", "%u", "U+"] + }, + { + "name": "转义所有字符", + "type": "boolean", + "value": false + }, + { + "name": "填充位数", + "type": "number", + "value": 4 + }, + { + "name": "十六进制大写", + "type": "boolean", + "value": true + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const regexWhitelist = /[ -~]/i, + [prefix, encodeAll, padding, uppercaseHex] = args; + + let output = "", + character = ""; + + for (let i = 0; i < input.length; i++) { + character = input[i]; + if (!encodeAll && regexWhitelist.test(character)) { + // It’s a printable ASCII character so don’t escape it. + output += character; + continue; + } + + let cp = character.codePointAt(0).toString(16); + if (uppercaseHex) cp = cp.toUpperCase(); + output += prefix + cp.padStart(padding, "0"); + } + + return output; + } + +} + +export default EscapeUnicodeCharacters; diff --git a/plugins/srktoolbox/src/core/operations/ExpandAlphabetRange.mjs b/plugins/srktoolbox/src/core/operations/ExpandAlphabetRange.mjs new file mode 100644 index 00000000..c426bf7a --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExpandAlphabetRange.mjs @@ -0,0 +1,48 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Expand alphabet range operation + */ +class ExpandAlphabetRange extends Operation { + + /** + * ExpandAlphabetRange constructor + */ + constructor() { + super(); + + this.name = "扩写字母范围"; + this.module = "Default"; + this.description = "把字母范围扩写成在此范围内的所有字母。

例如:a-z 扩写成 abcdefghijklmnopqrstuvwxyz。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "分隔符", + "type": "binaryString", + "value": "" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return Utils.expandAlphRange(input).join(args[0]); + } + +} + +export default ExpandAlphabetRange; diff --git a/plugins/srktoolbox/src/core/operations/ExtractDates.mjs b/plugins/srktoolbox/src/core/operations/ExtractDates.mjs new file mode 100644 index 00000000..1234dece --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExtractDates.mjs @@ -0,0 +1,60 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { search } from "../lib/Extract.mjs"; + +/** + * Extract dates operation + */ +class ExtractDates extends Operation { + + /** + * ExtractDates constructor + */ + constructor() { + super(); + + this.name = "提取日期"; + this.module = "Regex"; + this.description = "提取以下格式的日期:
  • yyyy-mm-dd
  • dd/mm/yyyy
  • mm/dd/yyyy
分隔符可以为/、-、.或空格。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "显示总数", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const displayTotal = args[0], + date1 = "(?:19|20)\\d\\d[- /.](?:0[1-9]|1[012])[- /.](?:0[1-9]|[12][0-9]|3[01])", // yyyy-mm-dd + date2 = "(?:0[1-9]|[12][0-9]|3[01])[- /.](?:0[1-9]|1[012])[- /.](?:19|20)\\d\\d", // dd/mm/yyyy + date3 = "(?:0[1-9]|1[012])[- /.](?:0[1-9]|[12][0-9]|3[01])[- /.](?:19|20)\\d\\d", // mm/dd/yyyy + regex = new RegExp(date1 + "|" + date2 + "|" + date3, "ig"); + + const results = search(input, regex); + + if (displayTotal) { + return `共计: ${results.length}\n\n${results.join("\n")}`; + } else { + return results.join("\n"); + } + } + +} + +export default ExtractDates; diff --git a/plugins/srktoolbox/src/core/operations/ExtractDomains.mjs b/plugins/srktoolbox/src/core/operations/ExtractDomains.mjs new file mode 100644 index 00000000..1a332717 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExtractDomains.mjs @@ -0,0 +1,78 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { search, DOMAIN_REGEX, DMARC_DOMAIN_REGEX } from "../lib/Extract.mjs"; +import { caseInsensitiveSort } from "../lib/Sort.mjs"; + +/** + * Extract domains operation + */ +class ExtractDomains extends Operation { + + /** + * ExtractDomains constructor + */ + constructor() { + super(); + + this.name = "提取域名"; + this.module = "Regex"; + this.description = "提取完整域名。
注意不包括域名路径。用提取URL操作提取完整URL。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "显示总数", + type: "boolean", + value: false + }, + { + name: "排序", + type: "boolean", + value: false + }, + { + name: "去重", + type: "boolean", + value: false + }, + { + name: "Underscore (DMARC, DKIM, etc)", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [displayTotal, sort, unique, dmarc] = args; + + const results = search( + input, + dmarc ? DMARC_DOMAIN_REGEX : DOMAIN_REGEX, + null, + sort ? caseInsensitiveSort : null, + unique + ); + + if (displayTotal) { + return `总计: ${results.length}\n\n${results.join("\n")}`; + } else { + return results.join("\n"); + } + } + +} + +export default ExtractDomains; diff --git a/plugins/srktoolbox/src/core/operations/ExtractEXIF.mjs b/plugins/srktoolbox/src/core/operations/ExtractEXIF.mjs new file mode 100644 index 00000000..bc2e680a --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExtractEXIF.mjs @@ -0,0 +1,65 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import ExifParser from "exif-parser"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Extract EXIF operation + */ +class ExtractEXIF extends Operation { + + /** + * ExtractEXIF constructor + */ + constructor() { + super(); + + this.name = "提取EXIF"; + this.module = "Image"; + this.description = [ + "从图像中提取EXIF数据。", + "

", + "EXIF数据是嵌入在图片(JPEG, JPG, TIFF)和音频文件中的元数据。", + "

", + "照片的EXIF数据通常包括图像本身以及拍摄设备的信息。", + ].join("\n"); + this.infoURL = "https://wikipedia.org/wiki/Exif"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + try { + const parser = ExifParser.create(input); + const result = parser.parse(); + + const lines = []; + for (const tagName in result.tags) { + const value = result.tags[tagName]; + lines.push(`${tagName}: ${value}`); + } + + const numTags = lines.length; + lines.unshift(`找到 ${numTags} 个标签。\n`); + return lines.join("\n"); + } catch (err) { + throw new OperationError(`无法从图片中提取EXIF数据: ${err}`); + } + } + +} + +export default ExtractEXIF; diff --git a/plugins/srktoolbox/src/core/operations/ExtractEmailAddresses.mjs b/plugins/srktoolbox/src/core/operations/ExtractEmailAddresses.mjs new file mode 100644 index 00000000..cd5743b8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExtractEmailAddresses.mjs @@ -0,0 +1,75 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { search } from "../lib/Extract.mjs"; +import { caseInsensitiveSort } from "../lib/Sort.mjs"; + +/** + * Extract email addresses operation + */ +class ExtractEmailAddresses extends Operation { + + /** + * ExtractEmailAddresses constructor + */ + constructor() { + super(); + + this.name = "提取Email地址"; + this.module = "Regex"; + this.description = "从输入中提取所有的Email地址。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "显示总数", + type: "boolean", + value: false + }, + { + name: "排序", + type: "boolean", + value: false + }, + { + name: "去重", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [displayTotal, sort, unique] = args, + // email regex from: https://www.regextester.com/98066 + regex = /(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?\.)+[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9](?:[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9-]*[\u00A0-\uD7FF\uE000-\uFFFFa-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\])/ig; + + const results = search( + input, + regex, + null, + sort ? caseInsensitiveSort : null, + unique + ); + + if (displayTotal) { + return `总计: ${results.length}\n\n${results.join("\n")}`; + } else { + return results.join("\n"); + } + } + +} + +export default ExtractEmailAddresses; diff --git a/plugins/srktoolbox/src/core/operations/ExtractFilePaths.mjs b/plugins/srktoolbox/src/core/operations/ExtractFilePaths.mjs new file mode 100644 index 00000000..e68396f2 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExtractFilePaths.mjs @@ -0,0 +1,104 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { search } from "../lib/Extract.mjs"; +import { caseInsensitiveSort } from "../lib/Sort.mjs"; + +/** + * Extract file paths operation + */ +class ExtractFilePaths extends Operation { + + /** + * ExtractFilePaths constructor + */ + constructor() { + super(); + + this.name = "提取文件路径"; + this.module = "Regex"; + this.description = "从输入中提取任何长得像Windows或UNIX文件路径的字符串。

注意UNIX模式可能会产生很多误判。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Windows", + type: "boolean", + value: true + }, + { + name: "UNIX", + type: "boolean", + value: true + }, + { + name: "显示总数", + type: "boolean", + value: false + }, + { + name: "排序", + type: "boolean", + value: false + }, + { + name: "去重", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [includeWinPath, includeUnixPath, displayTotal, sort, unique] = args, + winDrive = "[A-Z]:\\\\", + winName = "[A-Z\\d][A-Z\\d\\- '_\\(\\)~]{0,61}", + winExt = "[A-Z\\d]{1,6}", + winPath = winDrive + "(?:" + winName + "\\\\?)*" + winName + + "(?:\\." + winExt + ")?", + unixPath = "(?:/[A-Z\\d.][A-Z\\d\\-.]{0,61})+"; + let filePaths = ""; + + if (includeWinPath && includeUnixPath) { + filePaths = winPath + "|" + unixPath; + } else if (includeWinPath) { + filePaths = winPath; + } else if (includeUnixPath) { + filePaths = unixPath; + } + + if (!filePaths) { + return ""; + } + + const regex = new RegExp(filePaths, "ig"); + const results = search( + input, + regex, + null, + sort ? caseInsensitiveSort : null, + unique + ); + + if (displayTotal) { + return `总计: ${results.length}\n\n${results.join("\n")}`; + } else { + return results.join("\n"); + } + + } + +} + +export default ExtractFilePaths; diff --git a/plugins/srktoolbox/src/core/operations/ExtractFiles.mjs b/plugins/srktoolbox/src/core/operations/ExtractFiles.mjs new file mode 100644 index 00000000..22ab4c5f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExtractFiles.mjs @@ -0,0 +1,125 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import {scanForFileTypes, extractFile} from "../lib/FileType.mjs"; +import {FILE_SIGNATURES} from "../lib/FileSignatures.mjs"; + +/** + * Extract Files operation + */ +class ExtractFiles extends Operation { + + /** + * ExtractFiles constructor + */ + constructor() { + super(); + + // Get the first extension for each signature that can be extracted + let supportedExts = Object.keys(FILE_SIGNATURES).map(cat => { + return FILE_SIGNATURES[cat] + .filter(sig => sig.extractor) + .map(sig => sig.extension.toUpperCase()); + }); + + // Flatten categories and remove duplicates + supportedExts = [].concat(...supportedExts).unique(); + + this.name = "提取文件"; + this.module = "Default"; + this.description = `从输入内容中进行文件雕复来尝试提取文件。

此操作目前可提取以下格式: +
    +
  • + ${supportedExts.join("
  • ")} +
  • +
可以指定最小文件尺寸来防止误判。`; + this.infoURL = "https://forensics.wiki/file_carving"; + this.inputType = "ArrayBuffer"; + this.outputType = "List"; + this.presentType = "html"; + this.args = Object.keys(FILE_SIGNATURES).map(cat => { + return { + name: cat, + type: "boolean", + value: cat === "其它" ? false : true + }; + }).concat([ + { + name: "忽略失败提取", + type: "boolean", + value: true + }, + { + name: "最小文件尺寸", + type: "number", + value: 100 + } + ]); + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {List} + */ + run(input, args) { + const bytes = new Uint8Array(input), + categories = [], + minSize = args.pop(1), + ignoreFailedExtractions = args.pop(1); + + args.forEach((cat, i) => { + if (cat) categories.push(Object.keys(FILE_SIGNATURES)[i]); + }); + + // Scan for embedded files + const detectedFiles = scanForFileTypes(bytes, categories); + + // Extract each file that we support + const files = []; + const errors = []; + detectedFiles.forEach(detectedFile => { + try { + const file = extractFile(bytes, detectedFile.fileDetails, detectedFile.offset); + if (file.size >= minSize) + files.push(file); + } catch (err) { + if (!ignoreFailedExtractions && err.message.indexOf("No extraction algorithm available") < 0) { + errors.push( + `Error while attempting to extract ${detectedFile.fileDetails.name} ` + + `at offset ${detectedFile.offset}:\n` + + `${err.message}` + ); + } + } + }); + + if (errors.length) { + throw new OperationError(errors.join("\n\n")); + } + + return files; + } + + + /** + * Displays the files in HTML for web apps. + * + * @param {File[]} files + * @returns {html} + */ + async present(files) { + return await Utils.displayFilesAsHTML(files); + } + +} + +export default ExtractFiles; diff --git a/plugins/srktoolbox/src/core/operations/ExtractHashes.mjs b/plugins/srktoolbox/src/core/operations/ExtractHashes.mjs new file mode 100644 index 00000000..300d2843 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExtractHashes.mjs @@ -0,0 +1,86 @@ +/** + * @author mshwed [m@ttshwed.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { search } from "../lib/Extract.mjs"; + +/** + * Extract Hash Values operation + */ +class ExtractHashes extends Operation { + + /** + * ExtractHashValues constructor + */ + constructor() { + super(); + + this.name = "提取哈希"; + this.module = "Regex"; + this.description = "根据哈希值长度提取哈希值。"; + this.infoURL = "https://wikipedia.org/wiki/Comparison_of_cryptographic_hash_functions"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "哈希值长度", + type: "number", + value: 40 + }, + { + name: "搜索所有种类哈希值", + type: "boolean", + value: false + }, + { + name: "显示总数", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const results = []; + let hashCount = 0; + + const [hashLength, searchAllHashes, showDisplayTotal] = args; + + // Convert character length to bit length + let hashBitLengths = [(hashLength / 2) * 8]; + + if (searchAllHashes) hashBitLengths = [4, 8, 16, 32, 64, 128, 160, 192, 224, 256, 320, 384, 512, 1024]; + + for (const hashBitLength of hashBitLengths) { + // Convert bit length to character length + const hashCharacterLength = (hashBitLength / 8) * 2; + + const regex = new RegExp(`(\\b|^)[a-f0-9]{${hashCharacterLength}}(\\b|$)`, "g"); + const searchResults = search(input, regex, null, false); + + hashCount += searchResults.length; + results.push(...searchResults); + } + + let output = ""; + if (showDisplayTotal) { + output = `结果总数:${hashCount}\n\n`; + } + + output = output + results.join("\n"); + return output; + } + +} + +export default ExtractHashes; diff --git a/plugins/srktoolbox/src/core/operations/ExtractID3.mjs b/plugins/srktoolbox/src/core/operations/ExtractID3.mjs new file mode 100644 index 00000000..f614729f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExtractID3.mjs @@ -0,0 +1,326 @@ +/** + * @author n1073645 [n1073645@gmail.com] + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Extract ID3 operation + */ +class ExtractID3 extends Operation { + + /** + * ExtractID3 constructor + */ + constructor() { + super(); + + this.name = "提取ID3"; + this.module = "Default"; + this.description = "此操作从MP3文件中提取ID3元数据。

ID3是一种元数据容器,多应用于MP3格式的音频文件中。它可以将相关的曲名、演唱者、专辑、音轨数等信息存储在MP3文件中,又称作“ID3Tags”。"; + this.infoURL = "https://wikipedia.org/wiki/ID3"; + this.inputType = "ArrayBuffer"; + this.outputType = "JSON"; + this.presentType = "html"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {JSON} + */ + run(input, args) { + input = new Uint8Array(input); + + /** + * Extracts the ID3 header fields. + */ + function extractHeader() { + if (!Array.from(input.slice(0, 3)).equals([0x49, 0x44, 0x33])) + throw new OperationError("未找到有效的ID3标头。"); + + const header = { + "Type": "ID3", + // Tag version + "Version": input[3].toString() + "." + input[4].toString(), + // Header version + "Flags": input[5].toString() + }; + + input = input.slice(6); + return header; + } + + /** + * Converts the size fields to a single integer. + * + * @param {number} num + * @returns {string} + */ + function readSize(num) { + let result = 0; + + // The sizes are 7 bit numbers stored in 8 bit locations + for (let i = (num) * 7; i; i -= 7) { + result = (result << i) | input[0]; + input = input.slice(1); + } + return result; + } + + /** + * Reads frame header based on ID. + * + * @param {string} id + * @returns {number} + */ + function readFrame(id) { + const frame = {}; + + // Size of frame + const size = readSize(4); + frame.Size = size.toString(); + frame.Description = FRAME_DESCRIPTIONS[id]; + input = input.slice(2); + + // Read data from frame + let data = ""; + for (let i = 1; i < size; i++) + data += String.fromCharCode(input[i]); + frame.Data = data; + + // Move to next Frame + input = input.slice(size); + + return [frame, size]; + } + + const result = extractHeader(); + + const headerTagSize = readSize(4); + result.Size = headerTagSize.toString(); + + const tags = {}; + let pos = 10; + + // While the current element is in the header + while (pos < headerTagSize) { + + // Frame Identifier of frame + let id = String.fromCharCode(input[0]) + String.fromCharCode(input[1]) + String.fromCharCode(input[2]); + input = input.slice(3); + + // If the next character is non-zero it is an identifier + if (input[0] !== 0) { + id += String.fromCharCode(input[0]); + } + input = input.slice(1); + + if (id in FRAME_DESCRIPTIONS) { + const [frame, size] = readFrame(id); + tags[id] = frame; + pos += 10 + size; + } else if (id === "\x00\x00\x00") { // end of header + break; + } else { + throw new OperationError("未知的Frame Identifier: " + id); + } + } + + result.Tags = tags; + + return result; + } + + /** + * Displays the extracted data in a more accessible format for web apps. + * @param {JSON} data + * @returns {html} + */ + present(data) { + if (!data || !Object.prototype.hasOwnProperty.call(data, "Tags")) + return JSON.stringify(data, null, 4); + + let output = ` + `; + + for (const tagID in data.Tags) { + const description = data.Tags[tagID].Description, + contents = data.Tags[tagID].Data; + output += ``; + } + output += "
标签描述Data
${tagID}${Utils.escapeHtml(description)}${Utils.escapeHtml(contents)}
"; + return output; + } + +} + +// Borrowed from https://github.com/aadsm/jsmediatags +const FRAME_DESCRIPTIONS = { + // v2.2 + "BUF": "Recommended buffer size", + "CNT": "Play counter", + "COM": "Comments", + "CRA": "Audio encryption", + "CRM": "Encrypted meta frame", + "ETC": "Event timing codes", + "EQU": "Equalization", + "GEO": "General encapsulated object", + "IPL": "Involved people list", + "LNK": "Linked information", + "MCI": "Music CD Identifier", + "MLL": "MPEG location lookup table", + "PIC": "Attached picture", + "POP": "Popularimeter", + "REV": "Reverb", + "RVA": "Relative volume adjustment", + "SLT": "Synchronized lyric/text", + "STC": "Synced tempo codes", + "TAL": "Album/Movie/Show title", + "TBP": "BPM (Beats Per Minute)", + "TCM": "Composer", + "TCO": "Content type", + "TCR": "Copyright message", + "TDA": "Date", + "TDY": "Playlist delay", + "TEN": "Encoded by", + "TFT": "File type", + "TIM": "Time", + "TKE": "Initial key", + "TLA": "Language(s)", + "TLE": "Length", + "TMT": "Media type", + "TOA": "Original artist(s)/performer(s)", + "TOF": "Original filename", + "TOL": "Original Lyricist(s)/text writer(s)", + "TOR": "Original release year", + "TOT": "Original album/Movie/Show title", + "TP1": "Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group", + "TP2": "Band/Orchestra/Accompaniment", + "TP3": "Conductor/Performer refinement", + "TP4": "Interpreted, remixed, or otherwise modified by", + "TPA": "Part of a set", + "TPB": "Publisher", + "TRC": "ISRC (International Standard Recording Code)", + "TRD": "Recording dates", + "TRK": "Track number/Position in set", + "TSI": "Size", + "TSS": "Software/hardware and settings used for encoding", + "TT1": "Content group description", + "TT2": "Title/Songname/Content description", + "TT3": "Subtitle/Description refinement", + "TXT": "Lyricist/text writer", + "TXX": "User defined text information frame", + "TYE": "Year", + "UFI": "Unique file identifier", + "ULT": "Unsychronized lyric/text transcription", + "WAF": "Official audio file webpage", + "WAR": "Official artist/performer webpage", + "WAS": "Official audio source webpage", + "WCM": "Commercial information", + "WCP": "Copyright/Legal information", + "WPB": "Publishers official webpage", + "WXX": "User defined URL link frame", + // v2.3 + "AENC": "Audio encryption", + "APIC": "Attached picture", + "ASPI": "Audio seek point index", + "CHAP": "Chapter", + "CTOC": "Table of contents", + "COMM": "Comments", + "COMR": "Commercial frame", + "ENCR": "Encryption method registration", + "EQU2": "Equalisation (2)", + "EQUA": "Equalization", + "ETCO": "Event timing codes", + "GEOB": "General encapsulated object", + "GRID": "Group identification registration", + "IPLS": "Involved people list", + "LINK": "Linked information", + "MCDI": "Music CD identifier", + "MLLT": "MPEG location lookup table", + "OWNE": "Ownership frame", + "PRIV": "Private frame", + "PCNT": "Play counter", + "POPM": "Popularimeter", + "POSS": "Position synchronisation frame", + "RBUF": "Recommended buffer size", + "RVA2": "Relative volume adjustment (2)", + "RVAD": "Relative volume adjustment", + "RVRB": "Reverb", + "SEEK": "Seek frame", + "SYLT": "Synchronized lyric/text", + "SYTC": "Synchronized tempo codes", + "TALB": "Album/Movie/Show title", + "TBPM": "BPM (beats per minute)", + "TCOM": "Composer", + "TCON": "Content type", + "TCOP": "Copyright message", + "TDAT": "Date", + "TDLY": "Playlist delay", + "TDRC": "Recording time", + "TDRL": "Release time", + "TDTG": "Tagging time", + "TENC": "Encoded by", + "TEXT": "Lyricist/Text writer", + "TFLT": "File type", + "TIME": "Time", + "TIPL": "Involved people list", + "TIT1": "Content group description", + "TIT2": "Title/songname/content description", + "TIT3": "Subtitle/Description refinement", + "TKEY": "Initial key", + "TLAN": "Language(s)", + "TLEN": "Length", + "TMCL": "Musician credits list", + "TMED": "Media type", + "TMOO": "Mood", + "TOAL": "Original album/movie/show title", + "TOFN": "Original filename", + "TOLY": "Original lyricist(s)/text writer(s)", + "TOPE": "Original artist(s)/performer(s)", + "TORY": "Original release year", + "TOWN": "File owner/licensee", + "TPE1": "Lead performer(s)/Soloist(s)", + "TPE2": "Band/orchestra/accompaniment", + "TPE3": "Conductor/performer refinement", + "TPE4": "Interpreted, remixed, or otherwise modified by", + "TPOS": "Part of a set", + "TPRO": "Produced notice", + "TPUB": "Publisher", + "TRCK": "Track number/Position in set", + "TRDA": "Recording dates", + "TRSN": "Internet radio station name", + "TRSO": "Internet radio station owner", + "TSOA": "Album sort order", + "TSOP": "Performer sort order", + "TSOT": "Title sort order", + "TSIZ": "Size", + "TSRC": "ISRC (international standard recording code)", + "TSSE": "Software/Hardware and settings used for encoding", + "TSST": "Set subtitle", + "TYER": "Year", + "TXXX": "User defined text information frame", + "UFID": "Unique file identifier", + "USER": "Terms of use", + "USLT": "Unsychronized lyric/text transcription", + "WCOM": "Commercial information", + "WCOP": "Copyright/Legal information", + "WOAF": "Official audio file webpage", + "WOAR": "Official artist/performer webpage", + "WOAS": "Official audio source webpage", + "WORS": "Official internet radio station homepage", + "WPAY": "Payment", + "WPUB": "Publishers official webpage", + "WXXX": "User defined URL link frame" +}; + +export default ExtractID3; diff --git a/plugins/srktoolbox/src/core/operations/ExtractIPAddresses.mjs b/plugins/srktoolbox/src/core/operations/ExtractIPAddresses.mjs new file mode 100644 index 00000000..0b9f5d18 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExtractIPAddresses.mjs @@ -0,0 +1,124 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { search } from "../lib/Extract.mjs"; +import { ipSort } from "../lib/Sort.mjs"; + +/** + * Extract IP addresses operation + */ +class ExtractIPAddresses extends Operation { + + /** + * ExtractIPAddresses constructor + */ + constructor() { + super(); + + this.name = "提取IP地址"; + this.module = "Regex"; + this.description = "提取所有的IPv4和IPv6地址。

警告:类似 1.2.3.4.5.6.7.8 这样的非有效IP地址输入也会匹配出 1.2.3.4 and 5.6.7.8,务必确认输入文本正确!"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "IPv4", + type: "boolean", + value: true + }, + { + name: "IPv6", + type: "boolean", + value: false + }, + { + name: "移除内网IPv4地址", + type: "boolean", + value: false + }, + { + name: "显示总数", + type: "boolean", + value: false + }, + { + name: "排序", + type: "boolean", + value: false + }, + { + name: "去重", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [includeIpv4, includeIpv6, removeLocal, displayTotal, sort, unique] = args, + + // IPv4 decimal groups can have values 0 to 255. To construct a regex the following sub-regex is reused: + ipv4DecimalByte = "(?:25[0-5]|2[0-4]\\d|1?[0-9]\\d|\\d)", + ipv4OctalByte = "(?:0[1-3]?[0-7]{1,2})", + + // Look behind and ahead will be used to exclude matches with additional decimal digits left and right of IP address + lookBehind = "(? option !== "") + .map((option) => COLOUR_OPTIONS.indexOf(option)), + parsedImage = await Jimp.read(input), + width = parsedImage.bitmap.width, + height = parsedImage.bitmap.height, + rgba = parsedImage.bitmap.data; + + if (bit < 0 || bit > 7) { + throw new OperationError( + "错误:位参数只能是 0 到 7", + ); + } + + let i, + combinedBinary = ""; + + if (pixelOrder === "按行") { + for (i = 0; i < rgba.length; i += 4) { + for (const colour of colours) { + combinedBinary += Utils.bin(rgba[i + colour])[bit]; + } + } + } else { + let rowWidth; + const pixelWidth = width * 4; + for (let col = 0; col < width; col++) { + for (let row = 0; row < height; row++) { + rowWidth = row * pixelWidth; + for (const colour of colours) { + i = rowWidth + (col + colour * 4); + combinedBinary += Utils.bin(rgba[i])[bit]; + } + } + } + } + + return fromBinary(combinedBinary); + } +} + +const COLOUR_OPTIONS = ["R", "G", "B", "A"]; + +export default ExtractLSB; diff --git a/plugins/srktoolbox/src/core/operations/ExtractMACAddresses.mjs b/plugins/srktoolbox/src/core/operations/ExtractMACAddresses.mjs new file mode 100644 index 00000000..cb3551d0 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExtractMACAddresses.mjs @@ -0,0 +1,73 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { search } from "../lib/Extract.mjs"; +import { hexadecimalSort } from "../lib/Sort.mjs"; + +/** + * Extract MAC addresses operation + */ +class ExtractMACAddresses extends Operation { + + /** + * ExtractMACAddresses constructor + */ + constructor() { + super(); + + this.name = "提取MAC地址"; + this.module = "Regex"; + this.description = "从输入中提取Media Access Control (MAC)地址。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "显示总数", + type: "boolean", + value: false + }, + { + name: "排序", + type: "boolean", + value: false + }, + { + name: "去重", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [displayTotal, sort, unique] = args, + regex = /[A-F\d]{2}(?:[:-][A-F\d]{2}){5}/ig, + results = search( + input, + regex, + null, + sort ? hexadecimalSort : null, + unique + ); + + if (displayTotal) { + return `总计: ${results.length}\n\n${results.join("\n")}`; + } else { + return results.join("\n"); + } + } + +} + +export default ExtractMACAddresses; diff --git a/plugins/srktoolbox/src/core/operations/ExtractRGBA.mjs b/plugins/srktoolbox/src/core/operations/ExtractRGBA.mjs new file mode 100644 index 00000000..282a0be7 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExtractRGBA.mjs @@ -0,0 +1,69 @@ +/** + * @author Ge0rg3 [georgeomnet+cyberchef@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { Jimp } from "jimp"; + +import { RGBA_DELIM_OPTIONS } from "../lib/Delim.mjs"; + +/** + * Extract RGBA operation + */ +class ExtractRGBA extends Operation { + /** + * ExtractRGBA constructor + */ + constructor() { + super(); + + this.name = "提取RGBA"; + this.module = "Image"; + this.description = + "提取图像中每个像素的RGBA值。此数据有时用于隐写术,可隐藏文字和数据。"; + this.infoURL = "https://wikipedia.org/wiki/RGBA_color_space"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "分隔符", + type: "editableOption", + value: RGBA_DELIM_OPTIONS, + }, + { + name: "包括Alpha", + type: "boolean", + value: true, + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + if (!isImage(input)) + throw new OperationError("请输入合法的图像文件。"); + + const delimiter = args[0], + includeAlpha = args[1], + parsedImage = await Jimp.read(input); + + let bitmap = parsedImage.bitmap.data; + bitmap = includeAlpha ? + bitmap : + bitmap.filter((val, idx) => idx % 4 !== 3); + + return bitmap.join(delimiter); + } +} + +export default ExtractRGBA; diff --git a/plugins/srktoolbox/src/core/operations/ExtractURLs.mjs b/plugins/srktoolbox/src/core/operations/ExtractURLs.mjs new file mode 100644 index 00000000..b0e1f54d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ExtractURLs.mjs @@ -0,0 +1,72 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { search, URL_REGEX } from "../lib/Extract.mjs"; +import { caseInsensitiveSort } from "../lib/Sort.mjs"; + +/** + * Extract URLs operation + */ +class ExtractURLs extends Operation { + + /** + * ExtractURLs constructor + */ + constructor() { + super(); + + this.name = "提取URL"; + this.module = "Regex"; + this.description = "从输入中提取Uniform Resource Locator (URL)。必须要带协议名称 (如http, ftp 等),否则会有过多误判。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "显示总数", + type: "boolean", + value: false + }, + { + name: "排序", + type: "boolean", + value: false + }, + { + name: "去重", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [displayTotal, sort, unique] = args; + const results = search( + input, + URL_REGEX, + null, + sort ? caseInsensitiveSort : null, + unique + ); + + if (displayTotal) { + return `总计: ${results.length}\n\n${results.join("\n")}`; + } else { + return results.join("\n"); + } + } + +} + +export default ExtractURLs; diff --git a/plugins/srktoolbox/src/core/operations/FangURL.mjs b/plugins/srktoolbox/src/core/operations/FangURL.mjs new file mode 100644 index 00000000..2f00063e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FangURL.mjs @@ -0,0 +1,80 @@ +/** + * @author arnydo [github@arnydo.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * FangURL operation + */ +class FangURL extends Operation { + + /** + * FangURL constructor + */ + constructor() { + super(); + + this.name = "URL无效化恢复"; + this.module = "Default"; + this.description = "将已经“无效化(Defanged)”的URL恢复成有效状态。"; + this.infoURL = "https://isc.sans.edu/forums/diary/Defang+all+the+things/22744/"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "恢复[.]", + type: "boolean", + value: true + }, + { + name: "恢复hxxp", + type: "boolean", + value: true + }, + { + name: "恢复://", + type: "boolean", + value: true + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [dots, http, slashes] = args; + + input = fangURL(input, dots, http, slashes); + + return input; + } + +} + + +/** + * Defangs a given URL + * + * @param {string} url + * @param {boolean} dots + * @param {boolean} http + * @param {boolean} slashes + * @returns {string} + */ +function fangURL(url, dots, http, slashes) { + if (dots) url = url.replace(/\[\.\]/g, "."); + if (http) url = url.replace(/hxxp/g, "http"); + if (slashes) url = url.replace(/\[:\/\/\]/g, "://"); + + return url; +} + +export default FangURL; diff --git a/plugins/srktoolbox/src/core/operations/FernetDecrypt.mjs b/plugins/srktoolbox/src/core/operations/FernetDecrypt.mjs new file mode 100644 index 00000000..8a74a125 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FernetDecrypt.mjs @@ -0,0 +1,65 @@ +/** + * @author Karsten Silkenbäumer [github.com/kassi] + * @copyright Karsten Silkenbäumer 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import fernet from "fernet"; + +/** + * FernetDecrypt operation + */ +class FernetDecrypt extends Operation { + /** + * FernetDecrypt constructor + */ + constructor() { + super(); + + this.name = "Fernet解密"; + this.module = "Default"; + this.description = "Fernet是一种对称加密算法,设计目的是确保加密过的信息在没有密钥的情况下无法被解密和修改。密钥使用URL安全编码。Fernet使用128位AES算法(CBC模式,PKCS7填充)和使用SHA256算法的HMAC进行校验。IV使用os.random()生成。

密钥:密钥长度必须为32字节(256位),使用Base64编码。"; + this.infoURL = "https://asecuritysite.com/encryption/fer"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "密钥", + "type": "string", + "value": "" + }, + ]; + this.patterns = [ + { + match: "^[A-Z\\d\\-_=]{20,}$", + flags: "i", + args: [] + }, + ]; + } + /** + * @param {String} input + * @param {Object[]} args + * @returns {String} + */ + run(input, args) { + const [secretInput] = args; + try { + const secret = new fernet.Secret(secretInput); + const token = new fernet.Token({ + secret: secret, + token: input, + ttl: 0 + }); + return token.decode(); + } catch (err) { + throw new OperationError(err); + } + } +} + +export default FernetDecrypt; diff --git a/plugins/srktoolbox/src/core/operations/FernetEncrypt.mjs b/plugins/srktoolbox/src/core/operations/FernetEncrypt.mjs new file mode 100644 index 00000000..67c12231 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FernetEncrypt.mjs @@ -0,0 +1,56 @@ +/** + * @author Karsten Silkenbäumer [github.com/kassi] + * @copyright Karsten Silkenbäumer 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import fernet from "fernet"; + +/** + * FernetEncrypt operation + */ +class FernetEncrypt extends Operation { + /** + * FernetEncrypt constructor + */ + constructor() { + super(); + + this.name = "Fernet加密"; + this.module = "Default"; + this.description = "Fernet是一种对称加密算法,设计目的是确保加密过的信息在没有密钥的情况下无法被解密和修改。密钥使用URL安全编码。Fernet使用128位AES算法(CBC模式,PKCS7填充)和使用SHA256算法的HMAC进行校验。IV使用os.random()生成。

密钥:密钥长度必须为32字节(256位),使用Base64编码。"; + this.infoURL = "https://asecuritysite.com/encryption/fer"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "密钥", + "type": "string", + "value": "" + }, + ]; + } + /** + * @param {String} input + * @param {Object[]} args + * @returns {String} + */ + run(input, args) { + const [secretInput] = args; + try { + const secret = new fernet.Secret(secretInput); + const token = new fernet.Token({ + secret: secret, + }); + return token.encode(input); + } catch (err) { + throw new OperationError(err); + } + } +} + +export default FernetEncrypt; diff --git a/plugins/srktoolbox/src/core/operations/FileTree.mjs b/plugins/srktoolbox/src/core/operations/FileTree.mjs new file mode 100644 index 00000000..b74baf07 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FileTree.mjs @@ -0,0 +1,96 @@ +/** + * @author sw5678 + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs"; + +/** + * Unique operation + */ +class FileTree extends Operation { + + /** + * Unique constructor + */ + constructor() { + super(); + + this.name = "文件树"; + this.module = "Default"; + this.description = "从给定的文件路径列表生成文件树(和Linux的tree命令类似)。"; + this.infoURL = "https://wikipedia.org/wiki/Tree_(command)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "文件路径分隔符", + type: "binaryString", + value: "/" + }, + { + name: "列表分隔符", + type: "option", + value: INPUT_DELIM_OPTIONS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + + // Set up arrow and pipe for nice output display + const ARROW = "|---"; + const PIPE = "| "; + + // Get args from input + const fileDelim = args[0]; + const entryDelim = Utils.charRep(args[1]); + + // Store path to print + const completedList = []; + const printList = []; + + // Loop through all entries + const filePaths = input.split(entryDelim).unique().sort(); + for (let i = 0; i < filePaths.length; i++) { + // Split by file delimiter + let path = filePaths[i].split(fileDelim); + + if (path[0] === "") { + path = path.slice(1, path.length); + } + + for (let j = 0; j < path.length; j++) { + let printLine; + let key; + if (j === 0) { + printLine = path[j]; + key = path[j]; + } else { + printLine = PIPE.repeat(j-1) + ARROW + path[j]; + key = path.slice(0, j+1).join("/"); + } + + // Check to see we have already added that path + if (!completedList.includes(key)) { + completedList.push(key); + printList.push(printLine); + } + } + } + return printList.join("\n"); + } + +} + +export default FileTree; diff --git a/plugins/srktoolbox/src/core/operations/Filter.mjs b/plugins/srktoolbox/src/core/operations/Filter.mjs new file mode 100644 index 00000000..7b9cbd0b --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Filter.mjs @@ -0,0 +1,75 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import XRegExp from "xregexp"; + +/** + * Filter operation + */ +class Filter extends Operation { + + /** + * Filter constructor + */ + constructor() { + super(); + + this.name = "过滤"; + this.module = "Regex"; + this.description = "将输入字符串使用给定的分隔符拆分,之后使用给定的正则表达式过滤。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": INPUT_DELIM_OPTIONS + }, + { + "name": "正则表达式", + "type": "string", + "value": "" + }, + { + "name": "反向过滤", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0]), + reverse = args[2]; + let regex; + + try { + regex = new XRegExp(args[1]); + } catch (err) { + throw new OperationError(`无效的正则表达式: ${err.message}`); + } + + const regexFilter = function(value) { + return reverse ^ regex.test(value); + }; + + return input.split(delim).filter(regexFilter).join(delim); + } + +} + +export default Filter; diff --git a/plugins/srktoolbox/src/core/operations/FindReplace.mjs b/plugins/srktoolbox/src/core/operations/FindReplace.mjs new file mode 100644 index 00000000..3ab79874 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FindReplace.mjs @@ -0,0 +1,96 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import XRegExp from "xregexp"; + +/** + * Find / Replace operation + */ +class FindReplace extends Operation { + + /** + * FindReplace constructor + */ + constructor() { + super(); + + this.name = "查找/替换"; + this.module = "Regex"; + this.description = "把第一个字符串用第二个字符串替换。

支持正则表达式(regex)、简单字符串和扩展字符串(即使用转义字符\\n, \\r, \\t, \\b, \\f和用\\x表示的十六进制字节,例如 \\x00 代表空字节)。"; + this.infoURL = "https://wikipedia.org/wiki/Regular_expression"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "查找内容", + "type": "toggleString", + "value": "", + "toggleValues": ["正则表达式", "扩展 (\\n, \\t, \\x...)", "简单字符串"] + }, + { + "name": "替换", + "type": "binaryString", + "value": "" + }, + { + "name": "全局匹配(g)", + "type": "boolean", + "value": true + }, + { + "name": "不区分大小写(i)", + "type": "boolean", + "value": false + }, + { + "name": "匹配多行(m)", + "type": "boolean", + "value": true + }, + { + "name": "点(.)匹配所有字符(s)", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [{option: type}, replace, g, i, m, s] = args; + let find = args[0].string, + modifiers = ""; + + if (g) modifiers += "g"; + if (i) modifiers += "i"; + if (m) modifiers += "m"; + if (s) modifiers += "s"; + + if (type === "正则表达式") { + find = new XRegExp(find, modifiers); + return input.replace(find, replace); + } + + if (type.indexOf("扩展") === 0) { + find = Utils.parseEscapedChars(find); + } + + find = new XRegExp(Utils.escapeRegex(find), modifiers); + + return input.replace(find, replace); + } + +} + +export default FindReplace; diff --git a/plugins/srktoolbox/src/core/operations/Fletcher16Checksum.mjs b/plugins/srktoolbox/src/core/operations/Fletcher16Checksum.mjs new file mode 100644 index 00000000..495c6293 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Fletcher16Checksum.mjs @@ -0,0 +1,52 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Fletcher-16 Checksum operation + */ +class Fletcher16Checksum extends Operation { + + /** + * Fletcher16Checksum constructor + */ + constructor() { + super(); + + this.name = "Fletcher-16校验和"; + this.module = "Crypto"; + this.description = "Fletcher校验和是用于计算位置相关校验和的算法,由Lawrence Livermore Labs的John Gould Fletcher在20世纪70年代末期设计。

Fletcher校验和可以提供接近循环冗余校验(Cyclic redundancy check, CRC)的错误检测功能,但所需的计算更少。"; + this.infoURL = "https://wikipedia.org/wiki/Fletcher%27s_checksum#Fletcher-16"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let a = 0, + b = 0; + input = new Uint8Array(input); + + for (let i = 0; i < input.length; i++) { + a = (a + input[i]) % 0xff; + b = (b + a) % 0xff; + } + + return Utils.hex(((b << 8) | a) >>> 0, 4); + } + +} + +export default Fletcher16Checksum; diff --git a/plugins/srktoolbox/src/core/operations/Fletcher32Checksum.mjs b/plugins/srktoolbox/src/core/operations/Fletcher32Checksum.mjs new file mode 100644 index 00000000..eba0ae6d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Fletcher32Checksum.mjs @@ -0,0 +1,60 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Fletcher-32 Checksum operation + */ +class Fletcher32Checksum extends Operation { + + /** + * Fletcher32Checksum constructor + */ + constructor() { + super(); + + this.name = "Fletcher-32校验和"; + this.module = "Crypto"; + this.description = "Fletcher校验和是用于计算位置相关校验和的算法,由Lawrence Livermore Labs的John Gould Fletcher在20世纪70年代末期设计。

Fletcher校验和可以提供接近循环冗余校验(Cyclic redundancy check, CRC)的错误检测功能,但所需的计算更少。"; + this.infoURL = "https://wikipedia.org/wiki/Fletcher%27s_checksum#Fletcher-32"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let a = 0, + b = 0; + if (ArrayBuffer.isView(input)) { + input = new DataView(input.buffer, input.byteOffset, input.byteLength); + } else { + input = new DataView(input); + } + + for (let i = 0; i < input.byteLength - 1; i += 2) { + a = (a + input.getUint16(i, true)) % 0xffff; + b = (b + a) % 0xffff; + } + if (input.byteLength % 2 !== 0) { + a = (a + input.getUint8(input.byteLength - 1)) % 0xffff; + b = (b + a) % 0xffff; + } + + return Utils.hex(((b << 16) | a) >>> 0, 8); + } + +} + +export default Fletcher32Checksum; diff --git a/plugins/srktoolbox/src/core/operations/Fletcher64Checksum.mjs b/plugins/srktoolbox/src/core/operations/Fletcher64Checksum.mjs new file mode 100644 index 00000000..c2b6f77f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Fletcher64Checksum.mjs @@ -0,0 +1,64 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Fletcher-64 Checksum operation + */ +class Fletcher64Checksum extends Operation { + + /** + * Fletcher64Checksum constructor + */ + constructor() { + super(); + + this.name = "Fletcher-64校验和"; + this.module = "Crypto"; + this.description = "Fletcher校验和是用于计算位置相关校验和的算法,由Lawrence Livermore Labs的John Gould Fletcher在20世纪70年代末期设计。

Fletcher校验和可以提供接近循环冗余校验(Cyclic redundancy check, CRC)的错误检测功能,但所需的计算更少。"; + this.infoURL = "https://wikipedia.org/wiki/Fletcher%27s_checksum#Fletcher-64"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let a = 0, + b = 0; + if (ArrayBuffer.isView(input)) { + input = new DataView(input.buffer, input.byteOffset, input.byteLength); + } else { + input = new DataView(input); + } + + for (let i = 0; i < input.byteLength - 3; i += 4) { + a = (a + input.getUint32(i, true)) % 0xffffffff; + b = (b + a) % 0xffffffff; + } + if (input.byteLength % 4 !== 0) { + let lastValue = 0; + for (let i = 0; i < input.byteLength % 4; i++) { + lastValue = (lastValue << 8) | input.getUint8(input.byteLength - 1 - i); + } + a = (a + lastValue) % 0xffffffff; + b = (b + a) % 0xffffffff; + } + + return Utils.hex(b >>> 0, 8) + Utils.hex(a >>> 0, 8); + } + +} + +export default Fletcher64Checksum; diff --git a/plugins/srktoolbox/src/core/operations/Fletcher8Checksum.mjs b/plugins/srktoolbox/src/core/operations/Fletcher8Checksum.mjs new file mode 100644 index 00000000..6efcf577 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Fletcher8Checksum.mjs @@ -0,0 +1,52 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Fletcher-8 Checksum operation + */ +class Fletcher8Checksum extends Operation { + + /** + * Fletcher8Checksum constructor + */ + constructor() { + super(); + + this.name = "Fletcher-8校验和"; + this.module = "Crypto"; + this.description = "Fletcher校验和是用于计算位置相关校验和的算法,由Lawrence Livermore Labs的John Gould Fletcher在20世纪70年代末期设计。

Fletcher校验和可以提供接近循环冗余校验(Cyclic redundancy check, CRC)的错误检测功能,但所需的计算更少。"; + this.infoURL = "https://wikipedia.org/wiki/Fletcher%27s_checksum"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let a = 0, + b = 0; + input = new Uint8Array(input); + + for (let i = 0; i < input.length; i++) { + a = (a + input[i]) % 0xf; + b = (b + a) % 0xf; + } + + return Utils.hex(((b << 4) | a) >>> 0, 2); + } + +} + +export default Fletcher8Checksum; diff --git a/plugins/srktoolbox/src/core/operations/FlipImage.mjs b/plugins/srktoolbox/src/core/operations/FlipImage.mjs new file mode 100644 index 00000000..2cbfce91 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FlipImage.mjs @@ -0,0 +1,107 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; +import { Jimp, JimpMime } from "jimp"; + +/** + * Flip Image operation + */ +class FlipImage extends Operation { + /** + * FlipImage constructor + */ + constructor() { + super(); + + this.name = "图像翻转"; + this.module = "Image"; + this.description = "将图像按X轴或Y轴翻转。"; + this.infoURL = ""; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = [ + { + name: "翻转轴", + type: "option", + value: ["水平", "垂直"], + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + async run(input, args) { + const [flipAxis] = args; + if (!isImage(input)) { + throw new OperationError("无效的文件类型。"); + } + + let image; + try { + image = await Jimp.read(input); + } catch (err) { + throw new OperationError(`载入图像出错:(${err})`); + } + try { + if (isWorkerEnvironment()) + self.sendStatusMessage("翻转图像……"); + switch (flipAxis) { + case "水平": + image.flip({ + horizontal: true, + vertical: false, + }); + break; + case "垂直": + image.flip({ + horizontal: false, + vertical: true, + }); + break; + } + + let imageBuffer; + if (image.mime === "image/gif") { + imageBuffer = await image.getBuffer(JimpMime.png); + } else { + imageBuffer = await image.getBuffer(image.mime); + } + return imageBuffer.buffer; + } catch (err) { + throw new OperationError(`翻转图像错误:(${err})`); + } + } + + /** + * Displays the flipped image using HTML for web apps + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const dataArray = new Uint8Array(data); + + const type = isImage(dataArray); + if (!type) { + throw new OperationError("无效的文件类型。"); + } + + return ``; + } +} + +export default FlipImage; diff --git a/plugins/srktoolbox/src/core/operations/Fork.mjs b/plugins/srktoolbox/src/core/operations/Fork.mjs new file mode 100644 index 00000000..0ed48742 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Fork.mjs @@ -0,0 +1,128 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Recipe from "../Recipe.mjs"; +import Dish from "../Dish.mjs"; + +/** + * Fork operation + */ +class Fork extends Operation { + + /** + * Fork constructor + */ + constructor() { + super(); + + this.name = "Fork"; + this.flowControl = true; + this.module = "Default"; + this.description = "将输入数据按照给定的分隔符分割,并对分割后的每条数据单独执行下面的所有操作。

例如:解码多个Base64字符串,将所有的字符串每行一个放置在输入框,然后使用“Fork”和“Base64解码”操作。每个字符串都会被单独解码。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "分割分隔符", + "type": "binaryShortString", + "value": "\\n" + }, + { + "name": "合并分隔符", + "type": "binaryShortString", + "value": "\\n" + }, + { + "name": "忽略报错", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on. + * @param {Operation[]} state.opList - The list of operations in the recipe. + * @returns {Object} The updated state of the recipe. + */ + async run(state) { + const opList = state.opList, + inputType = opList[state.progress].inputType, + outputType = opList[state.progress].outputType, + input = await state.dish.get(inputType), + ings = opList[state.progress].ingValues, + [splitDelim, mergeDelim, ignoreErrors] = ings, + subOpList = []; + let inputs = [], + i; + + if (input) + inputs = input.split(splitDelim); + + // Set to 1 as if we are here, then there is one, the current one. + let numOp = 1; + // Create subOpList for each tranche to operate on + // all remaining operations unless we encounter a Merge + for (i = state.progress + 1; i < opList.length; i++) { + if (opList[i].name === "Merge" && !opList[i].disabled) { + numOp--; + if (numOp === 0 || opList[i].ingValues[0]) + break; + else + // Not this Fork's Merge. + subOpList.push(opList[i]); + } else { + if (opList[i].name === "Fork" || opList[i].name === "Subsection") + numOp++; + subOpList.push(opList[i]); + } + } + + const recipe = new Recipe(); + const outputs = []; + let progress = 0; + + state.forkOffset += state.progress + 1; + + recipe.addOperations(subOpList); + + // Take a deep(ish) copy of the ingredient values + const ingValues = subOpList.map(op => JSON.parse(JSON.stringify(op.ingValues))); + + // Run recipe over each tranche + for (i = 0; i < inputs.length; i++) { + // Baseline ing values for each tranche so that registers are reset + recipe.opList.forEach((op, i) => { + op.ingValues = JSON.parse(JSON.stringify(ingValues[i])); + }); + + const dish = new Dish(); + dish.set(inputs[i], inputType); + + try { + progress = await recipe.execute(dish, 0, state); + } catch (err) { + if (!ignoreErrors) { + throw err; + } + progress = err.progress + 1; + } + outputs.push(await dish.get(outputType)); + } + + state.dish.set(outputs.join(mergeDelim), outputType); + state.progress += progress; + return state; + } + +} + +export default Fork; diff --git a/plugins/srktoolbox/src/core/operations/FormatMACAddresses.mjs b/plugins/srktoolbox/src/core/operations/FormatMACAddresses.mjs new file mode 100644 index 00000000..919ede80 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FormatMACAddresses.mjs @@ -0,0 +1,124 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Format MAC addresses operation + */ +class FormatMACAddresses extends Operation { + + /** + * FormatMACAddresses constructor + */ + constructor() { + super(); + + this.name = "MAC地址格式化"; + this.module = "Default"; + this.description = "将给定的MAC地址用多种不同格式显示。

列表需要用回车、空格或逗号分隔。

警告:无法验证MAC地址的有效性。"; + this.infoURL = "https://wikipedia.org/wiki/MAC_address#Notational_conventions"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "输出大小写", + "type": "option", + "value": ["大小写", "仅大写", "仅小写"] + }, + { + "name": "无分隔", + "type": "boolean", + "value": true + }, + { + "name": "横杠分隔", + "type": "boolean", + "value": true + }, + { + "name": "冒号分隔", + "type": "boolean", + "value": true + }, + { + "name": "思科Style", + "type": "boolean", + "value": false + }, + { + "name": "IPv6接口ID", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (!input) return ""; + + const [ + outputCase, + noDelim, + dashDelim, + colonDelim, + ciscoStyle, + ipv6IntID + ] = args, + outputList = [], + macs = input.toLowerCase().split(/[,\s\r\n]+/); + + macs.forEach(function(mac) { + const cleanMac = mac.replace(/[:.-]+/g, ""), + macHyphen = cleanMac.replace(/(.{2}(?=.))/g, "$1-"), + macColon = cleanMac.replace(/(.{2}(?=.))/g, "$1:"), + macCisco = cleanMac.replace(/(.{4}(?=.))/g, "$1."); + let macIPv6 = cleanMac.slice(0, 6) + "fffe" + cleanMac.slice(6); + + macIPv6 = macIPv6.replace(/(.{4}(?=.))/g, "$1:"); + let bite = parseInt(macIPv6.slice(0, 2), 16) ^ 2; + bite = bite.toString(16).padStart(2, "0"); + macIPv6 = bite + macIPv6.slice(2); + + if (outputCase === "仅小写") { + if (noDelim) outputList.push(cleanMac); + if (dashDelim) outputList.push(macHyphen); + if (colonDelim) outputList.push(macColon); + if (ciscoStyle) outputList.push(macCisco); + if (ipv6IntID) outputList.push(macIPv6); + } else if (outputCase === "仅大写") { + if (noDelim) outputList.push(cleanMac.toUpperCase()); + if (dashDelim) outputList.push(macHyphen.toUpperCase()); + if (colonDelim) outputList.push(macColon.toUpperCase()); + if (ciscoStyle) outputList.push(macCisco.toUpperCase()); + if (ipv6IntID) outputList.push(macIPv6.toUpperCase()); + } else { + if (noDelim) outputList.push(cleanMac, cleanMac.toUpperCase()); + if (dashDelim) outputList.push(macHyphen, macHyphen.toUpperCase()); + if (colonDelim) outputList.push(macColon, macColon.toUpperCase()); + if (ciscoStyle) outputList.push(macCisco, macCisco.toUpperCase()); + if (ipv6IntID) outputList.push(macIPv6, macIPv6.toUpperCase()); + } + + outputList.push( + "" // Empty line to delimit groups + ); + }); + + // Return the data as a string + return outputList.join("\n"); + } + +} + +export default FormatMACAddresses; diff --git a/plugins/srktoolbox/src/core/operations/FrequencyDistribution.mjs b/plugins/srktoolbox/src/core/operations/FrequencyDistribution.mjs new file mode 100644 index 00000000..db2b25f1 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FrequencyDistribution.mjs @@ -0,0 +1,134 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Frequency distribution operation + */ +class FrequencyDistribution extends Operation { + + /** + * FrequencyDistribution constructor + */ + constructor() { + super(); + + this.name = "频率分布"; + this.module = "Default"; + this.description = "将数据中字节的分布绘制成图表。"; + this.infoURL = "https://wikipedia.org/wiki/Frequency_distribution"; + this.inputType = "ArrayBuffer"; + this.outputType = "json"; + this.presentType = "html"; + this.args = [ + { + "name": "显示 0%", + "type": "boolean", + "value": true + }, + { + "name": "显示 ASCII", + "type": "boolean", + "value": true + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {json} + */ + run(input, args) { + const data = new Uint8Array(input); + if (!data.length) throw new OperationError("无数据"); + + const distrib = new Array(256).fill(0), + percentages = new Array(256), + len = data.length; + let i; + + // Count bytes + for (i = 0; i < len; i++) { + distrib[data[i]]++; + } + + // Calculate percentages + let repr = 0; + for (i = 0; i < 256; i++) { + if (distrib[i] > 0) repr++; + percentages[i] = distrib[i] / len * 100; + } + + return { + "dataLength": len, + "percentages": percentages, + "distribution": distrib, + "bytesRepresented": repr + }; + } + + /** + * Displays the frequency distribution as a bar chart for web apps. + * + * @param {json} freq + * @returns {html} + */ + present(freq, args) { + const [showZeroes, showAscii] = args; + + // Print + let output = `
+数据长度: ${freq.dataLength} +已展示的字节数: ${freq.bytesRepresented} +未展示的字节数: ${256 - freq.bytesRepresented} + + + + ${showAscii ? "" : ""}`; + + for (let i = 0; i < 256; i++) { + if (freq.distribution[i] || showZeroes) { + let c = ""; + if (showAscii) { + if (i <= 32) { + c = String.fromCharCode(0x2400 + i); + } else if (i === 127) { + c = String.fromCharCode(0x2421); + } else { + c = String.fromCharCode(i); + } + } + const bite = ``, + ascii = showAscii ? `` : "", + percentage = ``, + bars = ``; + + output += `${bite}${ascii}${percentage}${bars}`; + } + } + + output += "
字节ASCII百分比
${Utils.hex(i, 2)}${c}${(freq.percentages[i].toFixed(2).replace(".00", "") + "%").padEnd(8, " ")}${Array(Math.ceil(freq.percentages[i])+1).join("|")}
"; + return output; + } + +} + +export default FrequencyDistribution; diff --git a/plugins/srktoolbox/src/core/operations/FromBCD.mjs b/plugins/srktoolbox/src/core/operations/FromBCD.mjs new file mode 100644 index 00000000..ab54690a --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromBCD.mjs @@ -0,0 +1,125 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {ENCODING_SCHEME, ENCODING_LOOKUP, FORMAT} from "../lib/BCD.mjs"; +import BigNumber from "bignumber.js"; + +/** + * From BCD operation + */ +class FromBCD extends Operation { + + /** + * FromBCD constructor + */ + constructor() { + super(); + + this.name = "BCD码解码"; + this.module = "Default"; + this.description = "BCD码(Binary-Coded Decimal)是一种十进制数字编码的形式。在这种编码下,每个十进制数字用一串单独的二进制比特来存储与表示。常见的有以4位或8位表示1个十进制数字。有时会用特殊的码位表示特殊符号。"; + this.infoURL = "https://wikipedia.org/wiki/Binary-coded_decimal"; + this.inputType = "string"; + this.outputType = "BigNumber"; + this.args = [ + { + "name": "编码方式", + "type": "option", + "value": ENCODING_SCHEME + }, + { + "name": "压缩", + "type": "boolean", + "value": true + }, + { + "name": "有符号", + "type": "boolean", + "value": false + }, + { + "name": "输入格式", + "type": "option", + "value": FORMAT + } + ]; + this.checks = [ + { + pattern: "^(?:\\d{4} ){3,}\\d{4}$", + flags: "", + args: ["8 4 2 1", true, false, "半字节"] + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {BigNumber} + */ + run(input, args) { + const encoding = ENCODING_LOOKUP[args[0]], + packed = args[1], + signed = args[2], + inputFormat = args[3], + nibbles = []; + + let output = "", + byteArray; + + // Normalise the input + switch (inputFormat) { + case "半字节": + case "字节": + input = input.replace(/\s/g, ""); + for (let i = 0; i < input.length; i += 4) { + nibbles.push(parseInt(input.substr(i, 4), 2)); + } + break; + case "原始数据": + default: + byteArray = new Uint8Array(Utils.strToArrayBuffer(input)); + byteArray.forEach(b => { + nibbles.push(b >>> 4); + nibbles.push(b & 15); + }); + break; + } + + if (!packed) { + // Discard each high nibble + for (let i = 0; i < nibbles.length; i++) { + nibbles.splice(i, 1); // lgtm [js/loop-iteration-skipped-due-to-shifting] + } + } + + if (signed) { + const sign = nibbles.pop(); + if (sign === 13 || + sign === 11) { + // Negative + output += "-"; + } + } + + nibbles.forEach(n => { + if (isNaN(n)) throw new OperationError("无效输入"); + const val = encoding.indexOf(n); + if (val < 0) throw new OperationError(`值 ${Utils.bin(n, 4)} 无法被编码`); + output += val.toString(); + }); + + return new BigNumber(output); + } + +} + +export default FromBCD; diff --git a/plugins/srktoolbox/src/core/operations/FromBase.mjs b/plugins/srktoolbox/src/core/operations/FromBase.mjs new file mode 100644 index 00000000..ff1360a7 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromBase.mjs @@ -0,0 +1,66 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import BigNumber from "bignumber.js"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * From Base operation + */ +class FromBase extends Operation { + + /** + * FromBase constructor + */ + constructor() { + super(); + + this.name = "其它进制数转十进制"; + this.module = "Default"; + this.description = "把给定进制的数字转换成十进制"; + this.infoURL = "https://wikipedia.org/wiki/Radix"; + this.inputType = "string"; + this.outputType = "BigNumber"; + this.args = [ + { + "name": "进制", + "type": "number", + "value": 36 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {BigNumber} + */ + run(input, args) { + const radix = args[0]; + if (radix < 2 || radix > 36) { + throw new OperationError("错误:进制必须在2~36之间"); + } + + const number = input.replace(/\s/g, "").split("."); + let result = new BigNumber(number[0], radix); + + if (number.length === 1) return result; + + // Fractional part + for (let i = 0; i < number[1].length; i++) { + const digit = new BigNumber(number[1][i], radix); + result += digit.div(Math.pow(radix, i+1)); + } + + return result; + } + +} + +export default FromBase; diff --git a/plugins/srktoolbox/src/core/operations/FromBase32.mjs b/plugins/srktoolbox/src/core/operations/FromBase32.mjs new file mode 100644 index 00000000..f5e5da68 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromBase32.mjs @@ -0,0 +1,108 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {ALPHABET_OPTIONS} from "../lib/Base32.mjs"; + + +/** + * From Base32 operation + */ +class FromBase32 extends Operation { + + /** + * FromBase32 constructor + */ + constructor() { + super(); + + this.name = "Base32解码"; + this.module = "Default"; + this.description = "Base32是把字节数据转换成特定字符组合的编码方式,编码后便于人类阅读,也方便计算机读取。Base32比Base64使用的字母表小一些,通常只包含大写字母和数字2到7。"; + this.infoURL = "https://wikipedia.org/wiki/Base32"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + name: "可用字符", + type: "editableOption", + value: ALPHABET_OPTIONS + }, + { + name: "移除输入中的非可用字符", + type: "boolean", + value: true + } + ]; + this.checks = [ + { + pattern: "^(?:[A-Z2-7]{8})+(?:[A-Z2-7]{2}={6}|[A-Z2-7]{4}={4}|[A-Z2-7]{5}={3}|[A-Z2-7]{7}={1})?$", + flags: "", + args: ["A-Z2-7=", false] + }, + { + pattern: "^(?:[0-9A-V]{8})+(?:[0-9A-V]{2}={6}|[0-9A-V]{4}={4}|[0-9A-V]{5}={3}|[0-9A-V]{7}={1})?$", + flags: "", + args: ["0-9A-V=", false] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + if (!input) return []; + + const alphabet = args[0] ? + Utils.expandAlphRange(args[0]).join("") : "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=", + removeNonAlphChars = args[1], + output = []; + + let chr1, chr2, chr3, chr4, chr5, + enc1, enc2, enc3, enc4, enc5, enc6, enc7, enc8, + i = 0; + + if (removeNonAlphChars) { + const re = new RegExp("[^" + alphabet.replace(/[\]\\\-^]/g, "\\$&") + "]", "g"); + input = input.replace(re, ""); + } + + while (i < input.length) { + enc1 = alphabet.indexOf(input.charAt(i++)); + enc2 = alphabet.indexOf(input.charAt(i++) || "="); + enc3 = alphabet.indexOf(input.charAt(i++) || "="); + enc4 = alphabet.indexOf(input.charAt(i++) || "="); + enc5 = alphabet.indexOf(input.charAt(i++) || "="); + enc6 = alphabet.indexOf(input.charAt(i++) || "="); + enc7 = alphabet.indexOf(input.charAt(i++) || "="); + enc8 = alphabet.indexOf(input.charAt(i++) || "="); + + chr1 = (enc1 << 3) | (enc2 >> 2); + chr2 = ((enc2 & 3) << 6) | (enc3 << 1) | (enc4 >> 4); + chr3 = ((enc4 & 15) << 4) | (enc5 >> 1); + chr4 = ((enc5 & 1) << 7) | (enc6 << 2) | (enc7 >> 3); + chr5 = ((enc7 & 7) << 5) | enc8; + + output.push(chr1); + if ((enc2 & 3) !== 0 || enc3 !== 32) output.push(chr2); + if ((enc4 & 15) !== 0 || enc5 !== 32) output.push(chr3); + if ((enc5 & 1) !== 0 || enc6 !== 32) output.push(chr4); + if ((enc7 & 7) !== 0 || enc8 !== 32) output.push(chr5); + } + + return output; + } + +} + +export default FromBase32; + diff --git a/plugins/srktoolbox/src/core/operations/FromBase45.mjs b/plugins/srktoolbox/src/core/operations/FromBase45.mjs new file mode 100644 index 00000000..d527bffc --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromBase45.mjs @@ -0,0 +1,103 @@ +/** + * @author Thomas Weißschuh [thomas@t-8ch.de] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import {ALPHABET, highlightToBase45, highlightFromBase45} from "../lib/Base45.mjs"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; + + +/** + * From Base45 operation + */ +class FromBase45 extends Operation { + + /** + * FromBase45 constructor + */ + constructor() { + super(); + + this.name = "Base45解码"; + this.module = "Default"; + this.description = "Base45是把字节数据转换成特定字符组合的编码方式,编码后便于人类阅读,也方便计算机读取。越高的Base数目会生成越短的字符串。Base45是为二维码优化的编码方式。"; + this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + name: "可用字符", + type: "string", + value: ALPHABET + }, + { + name: "移除输入中的非可用字符", + type: "boolean", + value: true + }, + ]; + + this.highlight = highlightFromBase45; + this.highlightReverse = highlightToBase45; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + if (!input) return []; + const alphabet = Utils.expandAlphRange(args[0]).join(""); + const removeNonAlphChars = args[1]; + + const res = []; + + // Remove non-alphabet characters + if (removeNonAlphChars) { + const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g"); + input = input.replace(re, ""); + } + + for (const triple of Utils.chunked(input, 3)) { + triple.reverse(); + let b = 0; + for (const c of triple) { + const idx = alphabet.indexOf(c); + if (idx === -1) { + throw new OperationError(`非可用字符: '${c}'`); + } + b *= 45; + b += idx; + } + + if (b > 65535) { + throw new OperationError(`超出编码范围: '${triple.join("")}'`); + } + + if (triple.length > 2) { + /** + * The last triple may only have 2 bytes so we push the MSB when we got 3 bytes + * Pushing MSB + */ + res.push(b >> 8); + } + + /** + * Pushing LSB + */ + res.push(b & 0xff); + + } + + return res; + } + +} + +export default FromBase45; diff --git a/plugins/srktoolbox/src/core/operations/FromBase58.mjs b/plugins/srktoolbox/src/core/operations/FromBase58.mjs new file mode 100644 index 00000000..adb2878e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromBase58.mjs @@ -0,0 +1,115 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {ALPHABET_OPTIONS} from "../lib/Base58.mjs"; + +/** + * From Base58 operation + */ +class FromBase58 extends Operation { + + /** + * FromBase58 constructor + */ + constructor() { + super(); + + this.name = "Base58解码"; + this.module = "Default"; + this.description = "Base58(类似于Base64)是把字节数据转换成特定字符组合的编码方式。和Base64的区别是移除了形状相近的易混字符(例如l、I、0和O)来提高可读性。

此操作将已编码成ASCII字符的Base58字符串解码为原始数据。

例: StV1DL6CwTryKyV 解码为 hello world

Base58常见于加密货币(比特币、Ripple等)。"; + this.infoURL = "https://wikipedia.org/wiki/Base58"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "可用字符", + "type": "editableOption", + "value": ALPHABET_OPTIONS + }, + { + "name": "移除输入中的非可用字符", + "type": "boolean", + "value": true + } + ]; + this.checks = [ + { + pattern: "^[1-9A-HJ-NP-Za-km-z]{20,}$", + flags: "", + args: ["123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz", false] + }, + { + pattern: "^[1-9A-HJ-NP-Za-km-z]{20,}$", + flags: "", + args: ["rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz", false] + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + let alphabet = args[0] || ALPHABET_OPTIONS[0].value; + const removeNonAlphaChars = args[1] === undefined ? true : args[1], + result = []; + + alphabet = Utils.expandAlphRange(alphabet).join(""); + + if (alphabet.length !== 58 || + [].unique.call(alphabet).length !== 58) { + throw new OperationError("错误:可用字符必须是58个"); + } + + if (input.length === 0) return []; + + let zeroPrefix = 0; + for (let i = 0; i < input.length && input[i] === alphabet[0]; i++) { + zeroPrefix++; + } + + [].forEach.call(input, function(c, charIndex) { + const index = alphabet.indexOf(c); + + if (index === -1) { + if (removeNonAlphaChars) { + return; + } else { + throw new OperationError(`字符'${c}'(位置 ${charIndex})不是可用字符`); + } + } + + let carry = index; + + for (let i = 0; i < result.length; i++) { + carry += result[i] * 58; + result[i] = carry & 0xFF; + carry = carry >> 8; + } + + while (carry > 0) { + result.push(carry & 0xFF); + carry = carry >> 8; + } + }); + + while (zeroPrefix--) { + result.push(0); + } + + return result.reverse(); + } + +} + +export default FromBase58; diff --git a/plugins/srktoolbox/src/core/operations/FromBase62.mjs b/plugins/srktoolbox/src/core/operations/FromBase62.mjs new file mode 100644 index 00000000..9d1b3f8e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromBase62.mjs @@ -0,0 +1,67 @@ +/** + * @author tcode2k16 [tcode2k16@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import Operation from "../Operation.mjs"; +import BigNumber from "bignumber.js"; +import Utils from "../Utils.mjs"; + + +/** + * From Base62 operation + */ +class FromBase62 extends Operation { + + /** + * FromBase62 constructor + */ + constructor() { + super(); + + this.name = "Base62解码"; + this.module = "Default"; + this.description = "Base62是把字节数据转换成特定字符组合的编码方式,编码后便于人类阅读,也方便计算机读取。

此操作将已编码成ASCII字符的Base62字符串解码为原始数据。"; + this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + name: "可用字符", + type: "string", + value: "0-9A-Za-z" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + if (input.length < 1) return []; + const alphabet = Utils.expandAlphRange(args[0]).join(""); + const BN62 = BigNumber.clone({ ALPHABET: alphabet }); + + const re = new RegExp("[^" + alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g"); + input = input.replace(re, ""); + + // Read number in using Base62 alphabet + const number = new BN62(input, 62); + // Copy to new BigNumber object that uses the default alphabet + const normalized = new BigNumber(number); + + // Convert to hex and add leading 0 if required + let hex = normalized.toString(16); + if (hex.length % 2 !== 0) hex = "0" + hex; + + return Utils.convertToByteArray(hex, "Hex"); + } + +} + +export default FromBase62; diff --git a/plugins/srktoolbox/src/core/operations/FromBase64.mjs b/plugins/srktoolbox/src/core/operations/FromBase64.mjs new file mode 100644 index 00000000..5f4bcce6 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromBase64.mjs @@ -0,0 +1,177 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {fromBase64, ALPHABET_OPTIONS} from "../lib/Base64.mjs"; + +/** + * From Base64 operation + */ +class FromBase64 extends Operation { + + /** + * FromBase64 constructor + */ + constructor() { + super(); + + this.name = "Base64解码"; + this.module = "Default"; + this.description = "Base64是把字节数据转换成特定字符组合的编码方式,编码后便于人类阅读,也方便计算机读取。

此操作将已编码成ASCII字符的Base64字符串解码为原始数据。

例: aGVsbG8= 解码成 hello"; + this.infoURL = "https://wikipedia.org/wiki/Base64"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + name: "可用字符", + type: "editableOption", + value: ALPHABET_OPTIONS + }, + { + name: "移除输入中的非可用字符", + type: "boolean", + value: true + }, + { + name: "严格模式", + type: "boolean", + value: false + } + ]; + this.checks = [ + { + pattern: "^\\s*(?:[A-Z\\d+/]{4})+(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$", + flags: "i", + args: ["A-Za-z0-9+/=", true, false] + }, + { + pattern: "^\\s*[A-Z\\d\\-_]{20,}\\s*$", + flags: "i", + args: ["A-Za-z0-9-_", true, false] + }, + { + pattern: "^\\s*(?:[A-Z\\d+\\-]{4}){5,}(?:[A-Z\\d+\\-]{2}==|[A-Z\\d+\\-]{3}=)?\\s*$", + flags: "i", + args: ["A-Za-z0-9+\\-=", true, false] + }, + { + pattern: "^\\s*(?:[A-Z\\d./]{4}){5,}(?:[A-Z\\d./]{2}==|[A-Z\\d./]{3}=)?\\s*$", + flags: "i", + args: ["./0-9A-Za-z=", true, false] + }, + { + pattern: "^\\s*[A-Z\\d_.]{20,}\\s*$", + flags: "i", + args: ["A-Za-z0-9_.", true, false] + }, + { + pattern: "^\\s*(?:[A-Z\\d._]{4}){5,}(?:[A-Z\\d._]{2}--|[A-Z\\d._]{3}-)?\\s*$", + flags: "i", + args: ["A-Za-z0-9._-", true, false] + }, + { + pattern: "^\\s*(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$", + flags: "i", + args: ["0-9a-zA-Z+/=", true, false] + }, + { + pattern: "^\\s*(?:[A-Z\\d+/]{4}){5,}(?:[A-Z\\d+/]{2}==|[A-Z\\d+/]{3}=)?\\s*$", + flags: "i", + args: ["0-9A-Za-z+/=", true, false] + }, + { + pattern: "^[ !\"#$%&'()*+,\\-./\\d:;<=>?@A-Z[\\\\\\]^_]{20,}$", + flags: "", + args: [" -_", false, false] + }, + { + pattern: "^\\s*[A-Z\\d+\\-]{20,}\\s*$", + flags: "i", + args: ["+\\-0-9A-Za-z", true, false] + }, + { + pattern: "^\\s*[!\"#$%&'()*+,\\-0-689@A-NP-VX-Z[`a-fh-mp-r]{20,}\\s*$", + flags: "", + args: ["!-,-0-689@A-NP-VX-Z[`a-fh-mp-r", true, false] + }, + { + pattern: "^\\s*(?:[N-ZA-M\\d+/]{4}){5,}(?:[N-ZA-M\\d+/]{2}==|[N-ZA-M\\d+/]{3}=)?\\s*$", + flags: "i", + args: ["N-ZA-Mn-za-m0-9+/=", true, false] + }, + { + pattern: "^\\s*[A-Z\\d./]{20,}\\s*$", + flags: "i", + args: ["./0-9A-Za-z", true, false] + }, + { + pattern: "^\\s*(?:[A-Z=\\d\\+/]{4}){5,}(?:[A-Z=\\d\\+/]{2}CC|[A-Z=\\d\\+/]{3}C)?\\s*$", + flags: "i", + args: ["/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC", true, false] + }, + { + pattern: "^\\s*(?:[A-Z=\\d\\+/]{4}){5,}(?:[A-Z=\\d\\+/]{2}55|[A-Z=\\d\\+/]{3}5)?\\s*$", + flags: "i", + args: ["3GHIJKLMNOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5", true, false] + }, + { + pattern: "^\\s*(?:[A-Z=\\d\\+/]{4}){5,}(?:[A-Z=\\d\\+/]{2}22|[A-Z=\\d\\+/]{3}2)?\\s*$", + flags: "i", + args: ["ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2", true, false] + }, + { + pattern: "^\\s*(?:[A-Z=\\d\\+/]{4}){5,}(?:[A-Z=\\d\\+/]{2}55|[A-Z=\\d\\+/]{3}5)?\\s*$", + flags: "i", + args: ["HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5", true, false] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const [alphabet, removeNonAlphChars, strictMode] = args; + + return fromBase64(input, alphabet, "byteArray", removeNonAlphChars, strictMode); + } + + /** + * Highlight to Base64 + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + pos[0].start = Math.ceil(pos[0].start / 4 * 3); + pos[0].end = Math.floor(pos[0].end / 4 * 3); + return pos; + } + + /** + * Highlight from Base64 + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + pos[0].start = Math.floor(pos[0].start / 3 * 4); + pos[0].end = Math.ceil(pos[0].end / 3 * 4); + return pos; + } +} + +export default FromBase64; diff --git a/plugins/srktoolbox/src/core/operations/FromBase85.mjs b/plugins/srktoolbox/src/core/operations/FromBase85.mjs new file mode 100644 index 00000000..e828d049 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromBase85.mjs @@ -0,0 +1,162 @@ +/** + * @author PenguinGeorge [george@penguingeorge.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import {ALPHABET_OPTIONS} from "../lib/Base85.mjs"; + +/** + * From Base85 operation + */ +class FromBase85 extends Operation { + + /** + * From Base85 constructor + */ + constructor() { + super(); + + this.name = "Base85解码"; + this.module = "Default"; + this.description = "Base85(也叫Ascii85)是把字节数据转换成特定字符组合的编码方式。通常比Base64效率更高。

此操作将使用ASCII字符的Base64字符串解码成原始数据。字符表可选,带有预设。

例: BOu!rD]j7BEbo7 解码成 hello world

Base85在Adobe的PostScript和PDF格式中较为常见。"; + this.infoURL = "https://wikipedia.org/wiki/Ascii85"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + name: "可用字符", + type: "editableOption", + value: ALPHABET_OPTIONS + }, + { + name: "移除不可用字符", + type: "boolean", + value: true + }, + { + name: "全零分组字符", + type: "binaryShortString", + value: "z", + maxLength: 1 + } + ]; + this.checks = [ + { + pattern: + "^\\s*(?:<~)?" + // Optional whitespace and starting marker + "[\\s!-uz]*" + // Any amount of base85 characters and whitespace + "[!-uz]{15}" + // At least 15 continoues base85 characters without whitespace + "[\\s!-uz]*" + // Any amount of base85 characters and whitespace + "(?:~>)?\\s*$", // Optional ending marker and whitespace + args: ["!-u"], + }, + { + pattern: + "^" + + "[\\s0-9a-zA-Z.\\-:+=^!/*?&<>()[\\]{}@%$#]*" + + "[0-9a-zA-Z.\\-:+=^!/*?&<>()[\\]{}@%$#]{15}" + // At least 15 continoues base85 characters without whitespace + "[\\s0-9a-zA-Z.\\-:+=^!/*?&<>()[\\]{}@%$#]*" + + "$", + args: ["0-9a-zA-Z.\\-:+=^!/*?&<>()[]{}@%$#"], + }, + { + pattern: + "^" + + "[\\s0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~]*" + + "[0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~]{15}" + // At least 15 continoues base85 characters without whitespace + "[\\s0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~]*" + + "$", + args: ["0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~"], + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const alphabet = Utils.expandAlphRange(args[0]).join(""), + removeNonAlphChars = args[1], + allZeroGroupChar = typeof args[2] === "string" ? args[2].slice(0, 1) : "", + result = []; + + if (alphabet.length !== 85 || + [].unique.call(alphabet).length !== 85) { + throw new OperationError("可用字符必须为85个"); + } + + if (allZeroGroupChar && alphabet.includes(allZeroGroupChar)) { + throw new OperationError("全零分组字符不能出现在可用字符中"); + } + + // Remove delimiters if present + const matches = input.match(/^<~(.+?)~>$/); + if (matches !== null) input = matches[1]; + + // Remove non-alphabet characters + if (removeNonAlphChars) { + const re = new RegExp("[^~" + allZeroGroupChar +alphabet.replace(/[[\]\\\-^$]/g, "\\$&") + "]", "g"); + input = input.replace(re, ""); + // Remove delimiters again if present (incase of non-alphabet characters in front/behind delimiters) + const matches = input.match(/^<~(.+?)~>$/); + if (matches !== null) input = matches[1]; + } + + if (input.length === 0) return []; + + let i = 0; + let block, blockBytes; + while (i < input.length) { + if (input[i] === allZeroGroupChar) { + result.push(0, 0, 0, 0); + i++; + } else { + let digits = []; + digits = input + .substr(i, 5) + .split("") + .map((chr, idx) => { + const digit = alphabet.indexOf(chr); + if ((digit < 0 || digit > 84) && chr !== allZeroGroupChar) { + throw `无效的字符 '${chr}' ,位置: ${i + idx}`; + } + return digit; + }); + + block = + digits[0] * 52200625 + + digits[1] * 614125 + + (i + 2 < input.length ? digits[2] : 84) * 7225 + + (i + 3 < input.length ? digits[3] : 84) * 85 + + (i + 4 < input.length ? digits[4] : 84); + + blockBytes = [ + (block >> 24) & 0xff, + (block >> 16) & 0xff, + (block >> 8) & 0xff, + block & 0xff + ]; + + if (input.length < i + 5) { + blockBytes.splice(input.length - (i + 5), 5); + } + + result.push.apply(result, blockBytes); + i += 5; + } + } + + return result; + } + +} + +export default FromBase85; diff --git a/plugins/srktoolbox/src/core/operations/FromBase92.mjs b/plugins/srktoolbox/src/core/operations/FromBase92.mjs new file mode 100644 index 00000000..416ea9bc --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromBase92.mjs @@ -0,0 +1,57 @@ +/** + * @author sg5506844 [sg5506844@gmail.com] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import { base92Ord } from "../lib/Base92.mjs"; +import Operation from "../Operation.mjs"; + +/** + * From Base92 operation + */ +class FromBase92 extends Operation { + /** + * FromBase92 constructor + */ + constructor() { + super(); + + this.name = "Base92解码"; + this.module = "Default"; + this.description = "Base92是把字节数据转换成特定字符组合的编码方式,编码后便于人类阅读,也方便计算机读取。"; + this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems"; + this.inputType = "string"; + this.outputType = "byteArray"; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const res = []; + let bitString = ""; + + for (let i = 0; i < input.length; i += 2) { + if (i + 1 !== input.length) { + const x = base92Ord(input[i]) * 91 + base92Ord(input[i + 1]); + bitString += x.toString(2).padStart(13, "0"); + } else { + const x = base92Ord(input[i]); + bitString += x.toString(2).padStart(6, "0"); + } + while (bitString.length >= 8) { + res.push(parseInt(bitString.slice(0, 8), 2)); + bitString = bitString.slice(8); + } + } + + return res; + } +} + +export default FromBase92; diff --git a/plugins/srktoolbox/src/core/operations/FromBech32.mjs b/plugins/srktoolbox/src/core/operations/FromBech32.mjs new file mode 100644 index 00000000..1464096a --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromBech32.mjs @@ -0,0 +1,151 @@ +/** + * @author Medjedtxm + * @copyright Crown Copyright 2025 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { decode } from "../lib/Bech32.mjs"; +import { toHex } from "../lib/Hex.mjs"; + +/** + * From Bech32 operation + */ +class FromBech32 extends Operation { + + /** + * FromBech32 constructor + */ + constructor() { + super(); + + this.name = "Bech32解码"; + this.module = "Default"; + this.description = "Bech32 是一种编码方案,主要应用于比特币隔离见证地址(BIP-0173)。它采用 32 字符字母表,其中排除了易混淆的字符(1、b、i、o),并包含用于错误检测的校验和。

Bech32m(BIP-0350)是其更新版本,用于比特币 Taproot 地址。

自动检测功能会先尝试以 Bech32 格式解码,若校验和失败则尝试 Bech32m 格式。

输出格式选项允许您查看人类可读部分(HRP)及解码后的数据。"; + this.infoURL = "https://wikipedia.org/wiki/Bech32"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "编码方式", + "type": "option", + "value": ["自动检测", "Bech32", "Bech32m"] + }, + { + "name": "输出格式", + "type": "option", + "value": ["原始", "十六进制", "Bitcoin scriptPubKey", "HRP: Hex", "JSON"] + } + ]; + this.checks = [ + { + // Bitcoin mainnet SegWit/Taproot addresses + pattern: "^bc1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,87}$", + flags: "i", + args: ["自动检测", "十六进制"] + }, + { + // Bitcoin testnet addresses + pattern: "^tb1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,87}$", + flags: "i", + args: ["自动检测", "十六进制"] + }, + { + // AGE public keys + pattern: "^age1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,87}$", + flags: "i", + args: ["自动检测", "HRP: Hex"] + }, + { + // AGE secret keys + pattern: "^AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{6,87}$", + flags: "", + args: ["自动检测", "HRP: Hex"] + }, + { + // Litecoin mainnet addresses + pattern: "^ltc1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,87}$", + flags: "i", + args: ["自动检测", "十六进制"] + }, + { + // Generic bech32 pattern + pattern: "^[a-z]{1,83}1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]{6,}$", + flags: "i", + args: ["自动检测", "十六进制"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const encoding = args[0]; + const outputFormat = args[1]; + + input = input.trim(); + + if (input.length === 0) { + return ""; + } + + const decoded = decode(input, encoding); + + // Format output based on selected option + switch (outputFormat) { + case "原始": + return decoded.data.map(b => String.fromCharCode(b)).join(""); + + case "十六进制": + return toHex(decoded.data, ""); + + case "Bitcoin scriptPubKey": { + // Convert to Bitcoin scriptPubKey format as shown in BIP-0173/BIP-0350 + // Format: [OP_version][length][witness_program] + // OP_0 = 0x00, OP_1-OP_16 = 0x51-0x60 + if (decoded.witnessVersion === null || decoded.data.length < 2) { + // Not a SegWit address, fall back to hex + return toHex(decoded.data, ""); + } + const witnessVersion = decoded.data[0]; + const witnessProgram = decoded.data.slice(1); + + // Convert witness version to OP code + let opCode; + if (witnessVersion === 0) { + opCode = 0x00; // OP_0 + } else if (witnessVersion >= 1 && witnessVersion <= 16) { + opCode = 0x50 + witnessVersion; // OP_1 = 0x51, ..., OP_16 = 0x60 + } else { + // Invalid witness version, fall back to hex + return toHex(decoded.data, ""); + } + + // Build scriptPubKey: [OP_version][length][program] + const scriptPubKey = [opCode, witnessProgram.length, ...witnessProgram]; + return toHex(scriptPubKey, ""); + } + + case "HRP: Hex": + return `${decoded.hrp}: ${toHex(decoded.data, "")}`; + + case "JSON": + return JSON.stringify({ + hrp: decoded.hrp, + encoding: decoded.encoding, + data: toHex(decoded.data, "") + }, null, 2); + + default: + return toHex(decoded.data, ""); + } + } + +} + +export default FromBech32; diff --git a/plugins/srktoolbox/src/core/operations/FromBinary.mjs b/plugins/srktoolbox/src/core/operations/FromBinary.mjs new file mode 100644 index 00000000..358fbcf8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromBinary.mjs @@ -0,0 +1,127 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {BIN_DELIM_OPTIONS} from "../lib/Delim.mjs"; +import {fromBinary} from "../lib/Binary.mjs"; + +/** + * From Binary operation + */ +class FromBinary extends Operation { + + /** + * FromBinary constructor + */ + constructor() { + super(); + + this.name = "二进制转字符"; + this.module = "Default"; + this.description = "把二进制字符串解码为原先的内容

01001000 01101001 解码为 Hi"; + this.infoURL = "https://wikipedia.org/wiki/Binary_code"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": BIN_DELIM_OPTIONS + }, + { + "name": "字节长度", + "type": "number", + "value": 8, + "min": 1 + } + ]; + this.checks = [ + { + pattern: "^(?:[01]{8})+$", + flags: "", + args: ["None"] + }, + { + pattern: "^(?:[01]{8})(?: [01]{8})*$", + flags: "", + args: ["Space"] + }, + { + pattern: "^(?:[01]{8})(?:,[01]{8})*$", + flags: "", + args: ["Comma"] + }, + { + pattern: "^(?:[01]{8})(?:;[01]{8})*$", + flags: "", + args: ["Semi-colon"] + }, + { + pattern: "^(?:[01]{8})(?::[01]{8})*$", + flags: "", + args: ["Colon"] + }, + { + pattern: "^(?:[01]{8})(?:\\n[01]{8})*$", + flags: "", + args: ["Line feed"] + }, + { + pattern: "^(?:[01]{8})(?:\\r\\n[01]{8})*$", + flags: "", + args: ["CRLF"] + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const byteLen = args[1] ? args[1] : 8; + return fromBinary(input, args[0], byteLen); + } + + /** + * Highlight From Binary + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + const delim = Utils.charRep(args[0] || "Space"); + pos[0].start = pos[0].start === 0 ? 0 : Math.floor(pos[0].start / (8 + delim.length)); + pos[0].end = pos[0].end === 0 ? 0 : Math.ceil(pos[0].end / (8 + delim.length)); + return pos; + } + + /** + * Highlight From Binary in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + const delim = Utils.charRep(args[0] || "Space"); + pos[0].start = pos[0].start * (8 + delim.length); + pos[0].end = pos[0].end * (8 + delim.length) - delim.length; + return pos; + } + +} + +export default FromBinary; diff --git a/plugins/srktoolbox/src/core/operations/FromBraille.mjs b/plugins/srktoolbox/src/core/operations/FromBraille.mjs new file mode 100644 index 00000000..f335f54e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromBraille.mjs @@ -0,0 +1,72 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {BRAILLE_LOOKUP} from "../lib/Braille.mjs"; + +/** + * From Braille operation + */ +class FromBraille extends Operation { + + /** + * FromBraille constructor + */ + constructor() { + super(); + + this.name = "盲文解码"; + this.module = "Default"; + this.description = "把六点盲文转换成文字。"; + this.infoURL = "https://wikipedia.org/wiki/Braille"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return input.split("").map(b => { + const idx = BRAILLE_LOOKUP.dot6.indexOf(b); + return idx < 0 ? b : BRAILLE_LOOKUP.ascii[idx]; + }).join(""); + } + + /** + * Highlight From Braille + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight From Braille in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default FromBraille; diff --git a/plugins/srktoolbox/src/core/operations/FromCaseInsensitiveRegex.mjs b/plugins/srktoolbox/src/core/operations/FromCaseInsensitiveRegex.mjs new file mode 100644 index 00000000..183a6c16 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromCaseInsensitiveRegex.mjs @@ -0,0 +1,41 @@ +/** + * @author masq [github.cyberchef@masq.cc] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * From Case Insensitive Regex operation + */ +class FromCaseInsensitiveRegex extends Operation { + + /** + * FromCaseInsensitiveRegex constructor + */ + constructor() { + super(); + + this.name = "从大小写不敏感正则恢复"; + this.module = "Default"; + this.description = "将大小写不敏感正则字符串恢复为大小写敏感形式(无法保证转换后的大小写形式正确),用于之前正则i选项不能用但现在能用了,所以你想转换回来的场合。

例如:[mM][oO][zZ][iI][lL][lL][aA]/[0-9].[0-9] .* 转换为 Mozilla/[0-9].[0-9] .*"; + this.infoURL = "https://wikipedia.org/wiki/Regular_expression"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return input.replace(/\[[a-z]{2}\]/ig, m => m[1].toUpperCase() === m[2].toUpperCase() ? m[1] : m); + } +} + +export default FromCaseInsensitiveRegex; diff --git a/plugins/srktoolbox/src/core/operations/FromCharcode.mjs b/plugins/srktoolbox/src/core/operations/FromCharcode.mjs new file mode 100644 index 00000000..809af3d7 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromCharcode.mjs @@ -0,0 +1,87 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import { DELIM_OPTIONS } from "../lib/Delim.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * From Charcode operation + */ +class FromCharcode extends Operation { + + /** + * FromCharcode constructor + */ + constructor() { + super(); + + this.name = "从字符码提取"; + this.module = "Default"; + this.description = "把Unicode字符码还原为字符。

例: 0393 03b5 03b9 03ac 20 03c3 03bf 03c5 解码为 Γειά σου"; + this.infoURL = "https://wikipedia.org/wiki/Plane_(Unicode)"; + this.inputType = "string"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": DELIM_OPTIONS + }, + { + "name": "进制", + "type": "number", + "value": 16 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {ArrayBuffer} + * + * @throws {OperationError} if base out of range + */ + run(input, args) { + const delim = Utils.charRep(args[0] || "空格"), + base = args[1]; + let bites = input.split(delim), + i = 0; + + if (base < 2 || base > 36) { + throw new OperationError("错误:进制必须在2~36之间"); + } + + if (input.length === 0) { + return new ArrayBuffer; + } + + if (base !== 16 && isWorkerEnvironment()) self.setOption("attemptHighlight", false); + + // Split into groups of 2 if the whole string is concatenated and + // too long to be a single character + if (bites.length === 1 && input.length > 17) { + bites = []; + for (i = 0; i < input.length; i += 2) { + bites.push(input.slice(i, i+2)); + } + } + + let latin1 = ""; + for (i = 0; i < bites.length; i++) { + latin1 += Utils.chr(parseInt(bites[i], base)); + } + return Utils.strToArrayBuffer(latin1); + } + +} + +export default FromCharcode; diff --git a/plugins/srktoolbox/src/core/operations/FromDecimal.mjs b/plugins/srktoolbox/src/core/operations/FromDecimal.mjs new file mode 100644 index 00000000..ef689312 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromDecimal.mjs @@ -0,0 +1,90 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {DELIM_OPTIONS} from "../lib/Delim.mjs"; +import {fromDecimal} from "../lib/Decimal.mjs"; + +/** + * From Decimal operation + */ +class FromDecimal extends Operation { + + /** + * FromDecimal constructor + */ + constructor() { + super(); + + this.name = "十进制转字符"; + this.module = "Default"; + this.description = "把十进制字符串解码为原先的内容。

例: 72 101 108 108 111 解码为 Hello"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": DELIM_OPTIONS + }, + { + "name": "支持带符号数字(signed int)", + "type": "boolean", + "value": false + } + ]; + this.checks = [ + { + pattern: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?: (?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$", + flags: "", + args: ["空格", false] + }, + { + pattern: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:,(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$", + flags: "", + args: ["逗号", false] + }, + { + pattern: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:;(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$", + flags: "", + args: ["分号", false] + }, + { + pattern: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?::(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$", + flags: "", + args: ["冒号", false] + }, + { + pattern: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:\\n(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$", + flags: "", + args: ["换行符", false] + }, + { + pattern: "^(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5])(?:\\r\\n(?:\\d{1,2}|1\\d{2}|2[0-4]\\d|25[0-5]))*$", + flags: "", + args: ["CRLF", false] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + let data = fromDecimal(input, args[0]); + if (args[1]) { // Convert negatives + data = data.map(v => v < 0 ? 0xFF + v + 1 : v); + } + return data; + } + +} + +export default FromDecimal; diff --git a/plugins/srktoolbox/src/core/operations/FromFloat.mjs b/plugins/srktoolbox/src/core/operations/FromFloat.mjs new file mode 100644 index 00000000..2e272379 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromFloat.mjs @@ -0,0 +1,80 @@ +/** + * @author tcode2k16 [tcode2k16@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import ieee754 from "ieee754"; +import {DELIM_OPTIONS} from "../lib/Delim.mjs"; + +/** + * From Float operation + */ +class FromFloat extends Operation { + + /** + * FromFloat constructor + */ + constructor() { + super(); + + this.name = "浮点数转字符"; + this.module = "Default"; + this.description = "将 IEEE754 浮点数转换为字符"; + this.infoURL = "https://wikipedia.org/wiki/IEEE_754"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "端序", + "type": "option", + "value": [ + "大端序", + "小端序" + ] + }, + { + "name": "类型", + "type": "option", + "value": [ + "Float (4字节)", + "Double (8字节)" + ] + }, + { + "name": "分隔符", + "type": "option", + "value": DELIM_OPTIONS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + if (input.length === 0) return []; + + const [endianness, size, delimiterName] = args; + const delim = Utils.charRep(delimiterName || "空格"); + const byteSize = size === "Double (8字节)" ? 8 : 4; + const isLE = endianness === "小端序"; + const mLen = byteSize === 4 ? 23 : 52; + const floats = input.split(delim); + + const output = new Array(floats.length*byteSize); + for (let i = 0; i < floats.length; i++) { + ieee754.write(output, parseFloat(floats[i]), i*byteSize, isLE, mLen, byteSize); + } + return output; + } + +} + +export default FromFloat; diff --git a/plugins/srktoolbox/src/core/operations/FromHTMLEntity.mjs b/plugins/srktoolbox/src/core/operations/FromHTMLEntity.mjs new file mode 100644 index 00000000..8468503c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromHTMLEntity.mjs @@ -0,0 +1,1541 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * From HTML Entity operation + */ +class FromHTMLEntity extends Operation { + + /** + * FromHTMLEntity constructor + */ + constructor() { + super(); + + this.name = "HTML实体解码"; + this.module = "Encodings"; + this.description = "把HTML实体解码为原始字符。

例: &amp; 解码为 &"; + this.infoURL = "https://wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + this.checks = [ + { + pattern: "&(?:#\\d{2,3}|#x[\\da-f]{2}|[a-z]{2,6});", + flags: "i", + args: [] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const regex = /&(#?x?[a-zA-Z0-9]{1,20});/g; + let output = "", + m, + i = 0; + + while ((m = regex.exec(input))) { + // Add up to match + for (; i < m.index;) + output += input[i++]; + + // Add match + const bite = entityToByte[m[1]]; + if (bite) { + output += Utils.chr(bite); + } else if (!bite && m[1][0] === "#" && m[1].length > 1 && /^#\d{1,6}$/.test(m[1])) { + // Numeric entity (e.g. ) + const num = m[1].slice(1, m[1].length); + output += Utils.chr(parseInt(num, 10)); + } else if (!bite && m[1][0] === "#" && m[1].length > 3 && /^#x[\dA-F]{2,8}$/i.test(m[1])) { + // Hex entity (e.g. :) + const hex = m[1].slice(2, m[1].length); + output += Utils.chr(parseInt(hex, 16)); + } else { + // Not a valid entity, print as normal + for (; i < regex.lastIndex;) + output += input[i++]; + } + + i = regex.lastIndex; + } + // Add all after final match + for (; i < input.length;) + output += input[i++]; + + return output; + } + +} + + +/** + * Lookup table to translate HTML entity codes to their byte values. + */ +const entityToByte = { + "Tab": 9, + "NewLine": 10, + "excl": 33, + "quot": 34, + "num": 35, + "dollar": 36, + "percnt": 37, + "amp": 38, + "apos": 39, + "lpar": 40, + "rpar": 41, + "ast": 42, + "plus": 43, + "comma": 44, + "period": 46, + "sol": 47, + "colon": 58, + "semi": 59, + "lt": 60, + "equals": 61, + "gt": 62, + "quest": 63, + "commat": 64, + "lsqb": 91, + "bsol": 92, + "rsqb": 93, + "Hat": 94, + "lowbar": 95, + "grave": 96, + "lcub": 123, + "verbar": 124, + "rcub": 125, + "nbsp": 160, + "iexcl": 161, + "cent": 162, + "pound": 163, + "curren": 164, + "yen": 165, + "brvbar": 166, + "sect": 167, + "uml": 168, + "copy": 169, + "ordf": 170, + "laquo": 171, + "not": 172, + "shy": 173, + "reg": 174, + "macr": 175, + "deg": 176, + "plusmn": 177, + "sup2": 178, + "sup3": 179, + "acute": 180, + "micro": 181, + "para": 182, + "middot": 183, + "cedil": 184, + "sup1": 185, + "ordm": 186, + "raquo": 187, + "frac14": 188, + "frac12": 189, + "frac34": 190, + "iquest": 191, + "Agrave": 192, + "Aacute": 193, + "Acirc": 194, + "Atilde": 195, + "Auml": 196, + "Aring": 197, + "AElig": 198, + "Ccedil": 199, + "Egrave": 200, + "Eacute": 201, + "Ecirc": 202, + "Euml": 203, + "Igrave": 204, + "Iacute": 205, + "Icirc": 206, + "Iuml": 207, + "ETH": 208, + "Ntilde": 209, + "Ograve": 210, + "Oacute": 211, + "Ocirc": 212, + "Otilde": 213, + "Ouml": 214, + "times": 215, + "Oslash": 216, + "Ugrave": 217, + "Uacute": 218, + "Ucirc": 219, + "Uuml": 220, + "Yacute": 221, + "THORN": 222, + "szlig": 223, + "agrave": 224, + "aacute": 225, + "acirc": 226, + "atilde": 227, + "auml": 228, + "aring": 229, + "aelig": 230, + "ccedil": 231, + "egrave": 232, + "eacute": 233, + "ecirc": 234, + "euml": 235, + "igrave": 236, + "iacute": 237, + "icirc": 238, + "iuml": 239, + "eth": 240, + "ntilde": 241, + "ograve": 242, + "oacute": 243, + "ocirc": 244, + "otilde": 245, + "ouml": 246, + "divide": 247, + "oslash": 248, + "ugrave": 249, + "uacute": 250, + "ucirc": 251, + "uuml": 252, + "yacute": 253, + "thorn": 254, + "yuml": 255, + "Amacr": 256, + "amacr": 257, + "Abreve": 258, + "abreve": 259, + "Aogon": 260, + "aogon": 261, + "Cacute": 262, + "cacute": 263, + "Ccirc": 264, + "ccirc": 265, + "Cdot": 266, + "cdot": 267, + "Ccaron": 268, + "ccaron": 269, + "Dcaron": 270, + "dcaron": 271, + "Dstrok": 272, + "dstrok": 273, + "Emacr": 274, + "emacr": 275, + "Edot": 278, + "edot": 279, + "Eogon": 280, + "eogon": 281, + "Ecaron": 282, + "ecaron": 283, + "Gcirc": 284, + "gcirc": 285, + "Gbreve": 286, + "gbreve": 287, + "Gdot": 288, + "gdot": 289, + "Gcedil": 290, + "Hcirc": 292, + "hcirc": 293, + "Hstrok": 294, + "hstrok": 295, + "Itilde": 296, + "itilde": 297, + "Imacr": 298, + "imacr": 299, + "Iogon": 302, + "iogon": 303, + "Idot": 304, + "imath": 305, + "IJlig": 306, + "ijlig": 307, + "Jcirc": 308, + "jcirc": 309, + "Kcedil": 310, + "kcedil": 311, + "kgreen": 312, + "Lacute": 313, + "lacute": 314, + "Lcedil": 315, + "lcedil": 316, + "Lcaron": 317, + "lcaron": 318, + "Lmidot": 319, + "lmidot": 320, + "Lstrok": 321, + "lstrok": 322, + "Nacute": 323, + "nacute": 324, + "Ncedil": 325, + "ncedil": 326, + "Ncaron": 327, + "ncaron": 328, + "napos": 329, + "ENG": 330, + "eng": 331, + "Omacr": 332, + "omacr": 333, + "Odblac": 336, + "odblac": 337, + "OElig": 338, + "oelig": 339, + "Racute": 340, + "racute": 341, + "Rcedil": 342, + "rcedil": 343, + "Rcaron": 344, + "rcaron": 345, + "Sacute": 346, + "sacute": 347, + "Scirc": 348, + "scirc": 349, + "Scedil": 350, + "scedil": 351, + "Scaron": 352, + "scaron": 353, + "Tcedil": 354, + "tcedil": 355, + "Tcaron": 356, + "tcaron": 357, + "Tstrok": 358, + "tstrok": 359, + "Utilde": 360, + "utilde": 361, + "Umacr": 362, + "umacr": 363, + "Ubreve": 364, + "ubreve": 365, + "Uring": 366, + "uring": 367, + "Udblac": 368, + "udblac": 369, + "Uogon": 370, + "uogon": 371, + "Wcirc": 372, + "wcirc": 373, + "Ycirc": 374, + "ycirc": 375, + "Yuml": 376, + "Zacute": 377, + "zacute": 378, + "Zdot": 379, + "zdot": 380, + "Zcaron": 381, + "zcaron": 382, + "fnof": 402, + "imped": 437, + "gacute": 501, + "jmath": 567, + "circ": 710, + "caron": 711, + "breve": 728, + "dot": 729, + "ring": 730, + "ogon": 731, + "tilde": 732, + "dblac": 733, + "DownBreve": 785, + "UnderBar": 818, + "Alpha": 913, + "Beta": 914, + "Gamma": 915, + "Delta": 916, + "Epsilon": 917, + "Zeta": 918, + "Eta": 919, + "Theta": 920, + "Iota": 921, + "Kappa": 922, + "Lambda": 923, + "Mu": 924, + "Nu": 925, + "Xi": 926, + "Omicron": 927, + "Pi": 928, + "Rho": 929, + "Sigma": 931, + "Tau": 932, + "Upsilon": 933, + "Phi": 934, + "Chi": 935, + "Psi": 936, + "Omega": 937, + "alpha": 945, + "beta": 946, + "gamma": 947, + "delta": 948, + "epsilon": 949, + "zeta": 950, + "eta": 951, + "theta": 952, + "iota": 953, + "kappa": 954, + "lambda": 955, + "mu": 956, + "nu": 957, + "xi": 958, + "omicron": 959, + "pi": 960, + "rho": 961, + "sigmaf": 962, + "sigma": 963, + "tau": 964, + "upsilon": 965, + "phi": 966, + "chi": 967, + "psi": 968, + "omega": 969, + "thetasym": 977, + "upsih": 978, + "straightphi": 981, + "piv": 982, + "Gammad": 988, + "gammad": 989, + "kappav": 1008, + "rhov": 1009, + "epsi": 1013, + "bepsi": 1014, + "IOcy": 1025, + "DJcy": 1026, + "GJcy": 1027, + "Jukcy": 1028, + "DScy": 1029, + "Iukcy": 1030, + "YIcy": 1031, + "Jsercy": 1032, + "LJcy": 1033, + "NJcy": 1034, + "TSHcy": 1035, + "KJcy": 1036, + "Ubrcy": 1038, + "DZcy": 1039, + "Acy": 1040, + "Bcy": 1041, + "Vcy": 1042, + "Gcy": 1043, + "Dcy": 1044, + "IEcy": 1045, + "ZHcy": 1046, + "Zcy": 1047, + "Icy": 1048, + "Jcy": 1049, + "Kcy": 1050, + "Lcy": 1051, + "Mcy": 1052, + "Ncy": 1053, + "Ocy": 1054, + "Pcy": 1055, + "Rcy": 1056, + "Scy": 1057, + "Tcy": 1058, + "Ucy": 1059, + "Fcy": 1060, + "KHcy": 1061, + "TScy": 1062, + "CHcy": 1063, + "SHcy": 1064, + "SHCHcy": 1065, + "HARDcy": 1066, + "Ycy": 1067, + "SOFTcy": 1068, + "Ecy": 1069, + "YUcy": 1070, + "YAcy": 1071, + "acy": 1072, + "bcy": 1073, + "vcy": 1074, + "gcy": 1075, + "dcy": 1076, + "iecy": 1077, + "zhcy": 1078, + "zcy": 1079, + "icy": 1080, + "jcy": 1081, + "kcy": 1082, + "lcy": 1083, + "mcy": 1084, + "ncy": 1085, + "ocy": 1086, + "pcy": 1087, + "rcy": 1088, + "scy": 1089, + "tcy": 1090, + "ucy": 1091, + "fcy": 1092, + "khcy": 1093, + "tscy": 1094, + "chcy": 1095, + "shcy": 1096, + "shchcy": 1097, + "hardcy": 1098, + "ycy": 1099, + "softcy": 1100, + "ecy": 1101, + "yucy": 1102, + "yacy": 1103, + "iocy": 1105, + "djcy": 1106, + "gjcy": 1107, + "jukcy": 1108, + "dscy": 1109, + "iukcy": 1110, + "yicy": 1111, + "jsercy": 1112, + "ljcy": 1113, + "njcy": 1114, + "tshcy": 1115, + "kjcy": 1116, + "ubrcy": 1118, + "dzcy": 1119, + "ensp": 8194, + "emsp": 8195, + "emsp13": 8196, + "emsp14": 8197, + "numsp": 8199, + "puncsp": 8200, + "thinsp": 8201, + "hairsp": 8202, + "ZeroWidthSpace": 8203, + "zwnj": 8204, + "zwj": 8205, + "lrm": 8206, + "rlm": 8207, + "hyphen": 8208, + "ndash": 8211, + "mdash": 8212, + "horbar": 8213, + "Verbar": 8214, + "lsquo": 8216, + "rsquo": 8217, + "sbquo": 8218, + "ldquo": 8220, + "rdquo": 8221, + "bdquo": 8222, + "dagger": 8224, + "Dagger": 8225, + "bull": 8226, + "nldr": 8229, + "hellip": 8230, + "permil": 8240, + "pertenk": 8241, + "prime": 8242, + "Prime": 8243, + "tprime": 8244, + "bprime": 8245, + "lsaquo": 8249, + "rsaquo": 8250, + "oline": 8254, + "caret": 8257, + "hybull": 8259, + "frasl": 8260, + "bsemi": 8271, + "qprime": 8279, + "MediumSpace": 8287, + "NoBreak": 8288, + "ApplyFunction": 8289, + "InvisibleTimes": 8290, + "InvisibleComma": 8291, + "euro": 8364, + "tdot": 8411, + "TripleDot": 8411, + "DotDot": 8412, + "Copf": 8450, + "incare": 8453, + "gscr": 8458, + "hamilt": 8459, + "Hfr": 8460, + "quaternions": 8461, + "planckh": 8462, + "planck": 8463, + "Iscr": 8464, + "image": 8465, + "Lscr": 8466, + "ell": 8467, + "Nopf": 8469, + "numero": 8470, + "copysr": 8471, + "weierp": 8472, + "Popf": 8473, + "rationals": 8474, + "Rscr": 8475, + "real": 8476, + "reals": 8477, + "rx": 8478, + "trade": 8482, + "integers": 8484, + "ohm": 8486, + "mho": 8487, + "Zfr": 8488, + "iiota": 8489, + "angst": 8491, + "bernou": 8492, + "Cfr": 8493, + "escr": 8495, + "Escr": 8496, + "Fscr": 8497, + "phmmat": 8499, + "order": 8500, + "alefsym": 8501, + "beth": 8502, + "gimel": 8503, + "daleth": 8504, + "CapitalDifferentialD": 8517, + "DifferentialD": 8518, + "ExponentialE": 8519, + "ImaginaryI": 8520, + "frac13": 8531, + "frac23": 8532, + "frac15": 8533, + "frac25": 8534, + "frac35": 8535, + "frac45": 8536, + "frac16": 8537, + "frac56": 8538, + "frac18": 8539, + "frac38": 8540, + "frac58": 8541, + "frac78": 8542, + "larr": 8592, + "uarr": 8593, + "rarr": 8594, + "darr": 8595, + "harr": 8596, + "varr": 8597, + "nwarr": 8598, + "nearr": 8599, + "searr": 8600, + "swarr": 8601, + "nlarr": 8602, + "nrarr": 8603, + "rarrw": 8605, + "Larr": 8606, + "Uarr": 8607, + "Rarr": 8608, + "Darr": 8609, + "larrtl": 8610, + "rarrtl": 8611, + "LeftTeeArrow": 8612, + "UpTeeArrow": 8613, + "map": 8614, + "DownTeeArrow": 8615, + "larrhk": 8617, + "rarrhk": 8618, + "larrlp": 8619, + "rarrlp": 8620, + "harrw": 8621, + "nharr": 8622, + "lsh": 8624, + "rsh": 8625, + "ldsh": 8626, + "rdsh": 8627, + "crarr": 8629, + "cularr": 8630, + "curarr": 8631, + "olarr": 8634, + "orarr": 8635, + "lharu": 8636, + "lhard": 8637, + "uharr": 8638, + "uharl": 8639, + "rharu": 8640, + "rhard": 8641, + "dharr": 8642, + "dharl": 8643, + "rlarr": 8644, + "udarr": 8645, + "lrarr": 8646, + "llarr": 8647, + "uuarr": 8648, + "rrarr": 8649, + "ddarr": 8650, + "lrhar": 8651, + "rlhar": 8652, + "nlArr": 8653, + "nhArr": 8654, + "nrArr": 8655, + "lArr": 8656, + "uArr": 8657, + "rArr": 8658, + "dArr": 8659, + "hArr": 8660, + "vArr": 8661, + "nwArr": 8662, + "neArr": 8663, + "seArr": 8664, + "swArr": 8665, + "lAarr": 8666, + "rAarr": 8667, + "zigrarr": 8669, + "larrb": 8676, + "rarrb": 8677, + "duarr": 8693, + "loarr": 8701, + "roarr": 8702, + "hoarr": 8703, + "forall": 8704, + "comp": 8705, + "part": 8706, + "exist": 8707, + "nexist": 8708, + "empty": 8709, + "nabla": 8711, + "isin": 8712, + "notin": 8713, + "ni": 8715, + "notni": 8716, + "prod": 8719, + "coprod": 8720, + "sum": 8721, + "minus": 8722, + "mnplus": 8723, + "plusdo": 8724, + "setmn": 8726, + "lowast": 8727, + "compfn": 8728, + "radic": 8730, + "prop": 8733, + "infin": 8734, + "angrt": 8735, + "ang": 8736, + "angmsd": 8737, + "angsph": 8738, + "mid": 8739, + "nmid": 8740, + "par": 8741, + "npar": 8742, + "and": 8743, + "or": 8744, + "cap": 8745, + "cup": 8746, + "int": 8747, + "Int": 8748, + "tint": 8749, + "conint": 8750, + "Conint": 8751, + "Cconint": 8752, + "cwint": 8753, + "cwconint": 8754, + "awconint": 8755, + "there4": 8756, + "becaus": 8757, + "ratio": 8758, + "Colon": 8759, + "minusd": 8760, + "mDDot": 8762, + "homtht": 8763, + "sim": 8764, + "bsim": 8765, + "ac": 8766, + "acd": 8767, + "wreath": 8768, + "nsim": 8769, + "esim": 8770, + "sime": 8771, + "nsime": 8772, + "cong": 8773, + "simne": 8774, + "ncong": 8775, + "asymp": 8776, + "nap": 8777, + "ape": 8778, + "apid": 8779, + "bcong": 8780, + "asympeq": 8781, + "bump": 8782, + "bumpe": 8783, + "esdot": 8784, + "eDot": 8785, + "efDot": 8786, + "erDot": 8787, + "colone": 8788, + "ecolon": 8789, + "ecir": 8790, + "cire": 8791, + "wedgeq": 8793, + "veeeq": 8794, + "trie": 8796, + "equest": 8799, + "ne": 8800, + "equiv": 8801, + "nequiv": 8802, + "le": 8804, + "ge": 8805, + "lE": 8806, + "gE": 8807, + "lnE": 8808, + "gnE": 8809, + "Lt": 8810, + "Gt": 8811, + "twixt": 8812, + "NotCupCap": 8813, + "nlt": 8814, + "ngt": 8815, + "nle": 8816, + "nge": 8817, + "lsim": 8818, + "gsim": 8819, + "nlsim": 8820, + "ngsim": 8821, + "lg": 8822, + "gl": 8823, + "ntlg": 8824, + "ntgl": 8825, + "pr": 8826, + "sc": 8827, + "prcue": 8828, + "sccue": 8829, + "prsim": 8830, + "scsim": 8831, + "npr": 8832, + "nsc": 8833, + "sub": 8834, + "sup": 8835, + "nsub": 8836, + "nsup": 8837, + "sube": 8838, + "supe": 8839, + "nsube": 8840, + "nsupe": 8841, + "subne": 8842, + "supne": 8843, + "cupdot": 8845, + "uplus": 8846, + "sqsub": 8847, + "sqsup": 8848, + "sqsube": 8849, + "sqsupe": 8850, + "sqcap": 8851, + "sqcup": 8852, + "oplus": 8853, + "ominus": 8854, + "otimes": 8855, + "osol": 8856, + "odot": 8857, + "ocir": 8858, + "oast": 8859, + "odash": 8861, + "plusb": 8862, + "minusb": 8863, + "timesb": 8864, + "sdotb": 8865, + "vdash": 8866, + "dashv": 8867, + "top": 8868, + "perp": 8869, + "models": 8871, + "vDash": 8872, + "Vdash": 8873, + "Vvdash": 8874, + "VDash": 8875, + "nvdash": 8876, + "nvDash": 8877, + "nVdash": 8878, + "nVDash": 8879, + "prurel": 8880, + "vltri": 8882, + "vrtri": 8883, + "ltrie": 8884, + "rtrie": 8885, + "origof": 8886, + "imof": 8887, + "mumap": 8888, + "hercon": 8889, + "intcal": 8890, + "veebar": 8891, + "barvee": 8893, + "angrtvb": 8894, + "lrtri": 8895, + "xwedge": 8896, + "xvee": 8897, + "xcap": 8898, + "xcup": 8899, + "diam": 8900, + "sdot": 8901, + "sstarf": 8902, + "divonx": 8903, + "bowtie": 8904, + "ltimes": 8905, + "rtimes": 8906, + "lthree": 8907, + "rthree": 8908, + "bsime": 8909, + "cuvee": 8910, + "cuwed": 8911, + "Sub": 8912, + "Sup": 8913, + "Cap": 8914, + "Cup": 8915, + "fork": 8916, + "epar": 8917, + "ltdot": 8918, + "gtdot": 8919, + "Ll": 8920, + "Gg": 8921, + "leg": 8922, + "gel": 8923, + "cuepr": 8926, + "cuesc": 8927, + "nprcue": 8928, + "nsccue": 8929, + "nsqsube": 8930, + "nsqsupe": 8931, + "lnsim": 8934, + "gnsim": 8935, + "prnsim": 8936, + "scnsim": 8937, + "nltri": 8938, + "nrtri": 8939, + "nltrie": 8940, + "nrtrie": 8941, + "vellip": 8942, + "ctdot": 8943, + "utdot": 8944, + "dtdot": 8945, + "disin": 8946, + "isinsv": 8947, + "isins": 8948, + "isindot": 8949, + "notinvc": 8950, + "notinvb": 8951, + "isinE": 8953, + "nisd": 8954, + "xnis": 8955, + "nis": 8956, + "notnivc": 8957, + "notnivb": 8958, + "barwed": 8965, + "Barwed": 8966, + "lceil": 8968, + "rceil": 8969, + "lfloor": 8970, + "rfloor": 8971, + "drcrop": 8972, + "dlcrop": 8973, + "urcrop": 8974, + "ulcrop": 8975, + "bnot": 8976, + "profline": 8978, + "profsurf": 8979, + "telrec": 8981, + "target": 8982, + "ulcorn": 8988, + "urcorn": 8989, + "dlcorn": 8990, + "drcorn": 8991, + "frown": 8994, + "smile": 8995, + "lang": 9001, + "rang": 9002, + "cylcty": 9005, + "profalar": 9006, + "topbot": 9014, + "ovbar": 9021, + "solbar": 9023, + "angzarr": 9084, + "lmoust": 9136, + "rmoust": 9137, + "tbrk": 9140, + "bbrk": 9141, + "bbrktbrk": 9142, + "OverParenthesis": 9180, + "UnderParenthesis": 9181, + "OverBrace": 9182, + "UnderBrace": 9183, + "trpezium": 9186, + "elinters": 9191, + "blank": 9251, + "oS": 9416, + "boxh": 9472, + "boxv": 9474, + "boxdr": 9484, + "boxdl": 9488, + "boxur": 9492, + "boxul": 9496, + "boxvr": 9500, + "boxvl": 9508, + "boxhd": 9516, + "boxhu": 9524, + "boxvh": 9532, + "boxH": 9552, + "boxV": 9553, + "boxdR": 9554, + "boxDr": 9555, + "boxDR": 9556, + "boxdL": 9557, + "boxDl": 9558, + "boxDL": 9559, + "boxuR": 9560, + "boxUr": 9561, + "boxUR": 9562, + "boxuL": 9563, + "boxUl": 9564, + "boxUL": 9565, + "boxvR": 9566, + "boxVr": 9567, + "boxVR": 9568, + "boxvL": 9569, + "boxVl": 9570, + "boxVL": 9571, + "boxHd": 9572, + "boxhD": 9573, + "boxHD": 9574, + "boxHu": 9575, + "boxhU": 9576, + "boxHU": 9577, + "boxvH": 9578, + "boxVh": 9579, + "boxVH": 9580, + "uhblk": 9600, + "lhblk": 9604, + "block": 9608, + "blk14": 9617, + "blk12": 9618, + "blk34": 9619, + "squ": 9633, + "squf": 9642, + "EmptyVerySmallSquare": 9643, + "rect": 9645, + "marker": 9646, + "fltns": 9649, + "xutri": 9651, + "utrif": 9652, + "utri": 9653, + "rtrif": 9656, + "rtri": 9657, + "xdtri": 9661, + "dtrif": 9662, + "dtri": 9663, + "ltrif": 9666, + "ltri": 9667, + "loz": 9674, + "cir": 9675, + "tridot": 9708, + "xcirc": 9711, + "ultri": 9720, + "urtri": 9721, + "lltri": 9722, + "EmptySmallSquare": 9723, + "FilledSmallSquare": 9724, + "starf": 9733, + "bigstar": 9733, + "star": 9734, + "phone": 9742, + "female": 9792, + "male": 9794, + "spades": 9824, + "clubs": 9827, + "hearts": 9829, + "diams": 9830, + "sung": 9834, + "flat": 9837, + "natur": 9838, + "sharp": 9839, + "check": 10003, + "cross": 10007, + "malt": 10016, + "sext": 10038, + "VerticalSeparator": 10072, + "lbbrk": 10098, + "rbbrk": 10099, + "lobrk": 10214, + "robrk": 10215, + "Lang": 10218, + "Rang": 10219, + "loang": 10220, + "roang": 10221, + "xlarr": 10229, + "xrarr": 10230, + "xharr": 10231, + "xlArr": 10232, + "xrArr": 10233, + "xhArr": 10234, + "xmap": 10236, + "dzigrarr": 10239, + "nvlArr": 10498, + "nvrArr": 10499, + "nvHarr": 10500, + "Map": 10501, + "lbarr": 10508, + "rbarr": 10509, + "lBarr": 10510, + "rBarr": 10511, + "RBarr": 10512, + "DDotrahd": 10513, + "UpArrowBar": 10514, + "DownArrowBar": 10515, + "Rarrtl": 10518, + "latail": 10521, + "ratail": 10522, + "lAtail": 10523, + "rAtail": 10524, + "larrfs": 10525, + "rarrfs": 10526, + "larrbfs": 10527, + "rarrbfs": 10528, + "nwarhk": 10531, + "nearhk": 10532, + "searhk": 10533, + "swarhk": 10534, + "nwnear": 10535, + "nesear": 10536, + "seswar": 10537, + "swnwar": 10538, + "rarrc": 10547, + "cudarrr": 10549, + "ldca": 10550, + "rdca": 10551, + "cudarrl": 10552, + "larrpl": 10553, + "curarrm": 10556, + "cularrp": 10557, + "rarrpl": 10565, + "harrcir": 10568, + "Uarrocir": 10569, + "lurdshar": 10570, + "ldrushar": 10571, + "LeftRightVector": 10574, + "RightUpDownVector": 10575, + "DownLeftRightVector": 10576, + "LeftUpDownVector": 10577, + "LeftVectorBar": 10578, + "RightVectorBar": 10579, + "RightUpVectorBar": 10580, + "RightDownVectorBar": 10581, + "DownLeftVectorBar": 10582, + "DownRightVectorBar": 10583, + "LeftUpVectorBar": 10584, + "LeftDownVectorBar": 10585, + "LeftTeeVector": 10586, + "RightTeeVector": 10587, + "RightUpTeeVector": 10588, + "RightDownTeeVector": 10589, + "DownLeftTeeVector": 10590, + "DownRightTeeVector": 10591, + "LeftUpTeeVector": 10592, + "LeftDownTeeVector": 10593, + "lHar": 10594, + "uHar": 10595, + "rHar": 10596, + "dHar": 10597, + "luruhar": 10598, + "ldrdhar": 10599, + "ruluhar": 10600, + "rdldhar": 10601, + "lharul": 10602, + "llhard": 10603, + "rharul": 10604, + "lrhard": 10605, + "udhar": 10606, + "duhar": 10607, + "RoundImplies": 10608, + "erarr": 10609, + "simrarr": 10610, + "larrsim": 10611, + "rarrsim": 10612, + "rarrap": 10613, + "ltlarr": 10614, + "gtrarr": 10616, + "subrarr": 10617, + "suplarr": 10619, + "lfisht": 10620, + "rfisht": 10621, + "ufisht": 10622, + "dfisht": 10623, + "lopar": 10629, + "ropar": 10630, + "lbrke": 10635, + "rbrke": 10636, + "lbrkslu": 10637, + "rbrksld": 10638, + "lbrksld": 10639, + "rbrkslu": 10640, + "langd": 10641, + "rangd": 10642, + "lparlt": 10643, + "rpargt": 10644, + "gtlPar": 10645, + "ltrPar": 10646, + "vzigzag": 10650, + "vangrt": 10652, + "angrtvbd": 10653, + "ange": 10660, + "range": 10661, + "dwangle": 10662, + "uwangle": 10663, + "angmsdaa": 10664, + "angmsdab": 10665, + "angmsdac": 10666, + "angmsdad": 10667, + "angmsdae": 10668, + "angmsdaf": 10669, + "angmsdag": 10670, + "angmsdah": 10671, + "bemptyv": 10672, + "demptyv": 10673, + "cemptyv": 10674, + "raemptyv": 10675, + "laemptyv": 10676, + "ohbar": 10677, + "omid": 10678, + "opar": 10679, + "operp": 10681, + "olcross": 10683, + "odsold": 10684, + "olcir": 10686, + "ofcir": 10687, + "olt": 10688, + "ogt": 10689, + "cirscir": 10690, + "cirE": 10691, + "solb": 10692, + "bsolb": 10693, + "boxbox": 10697, + "trisb": 10701, + "rtriltri": 10702, + "LeftTriangleBar": 10703, + "RightTriangleBar": 10704, + "race": 10714, + "iinfin": 10716, + "infintie": 10717, + "nvinfin": 10718, + "eparsl": 10723, + "smeparsl": 10724, + "eqvparsl": 10725, + "lozf": 10731, + "RuleDelayed": 10740, + "dsol": 10742, + "xodot": 10752, + "xoplus": 10753, + "xotime": 10754, + "xuplus": 10756, + "xsqcup": 10758, + "qint": 10764, + "fpartint": 10765, + "cirfnint": 10768, + "awint": 10769, + "rppolint": 10770, + "scpolint": 10771, + "npolint": 10772, + "pointint": 10773, + "quatint": 10774, + "intlarhk": 10775, + "pluscir": 10786, + "plusacir": 10787, + "simplus": 10788, + "plusdu": 10789, + "plussim": 10790, + "plustwo": 10791, + "mcomma": 10793, + "minusdu": 10794, + "loplus": 10797, + "roplus": 10798, + "Cross": 10799, + "timesd": 10800, + "timesbar": 10801, + "smashp": 10803, + "lotimes": 10804, + "rotimes": 10805, + "otimesas": 10806, + "Otimes": 10807, + "odiv": 10808, + "triplus": 10809, + "triminus": 10810, + "tritime": 10811, + "iprod": 10812, + "amalg": 10815, + "capdot": 10816, + "ncup": 10818, + "ncap": 10819, + "capand": 10820, + "cupor": 10821, + "cupcap": 10822, + "capcup": 10823, + "cupbrcap": 10824, + "capbrcup": 10825, + "cupcup": 10826, + "capcap": 10827, + "ccups": 10828, + "ccaps": 10829, + "ccupssm": 10832, + "And": 10835, + "Or": 10836, + "andand": 10837, + "oror": 10838, + "orslope": 10839, + "andslope": 10840, + "andv": 10842, + "orv": 10843, + "andd": 10844, + "ord": 10845, + "wedbar": 10847, + "sdote": 10854, + "simdot": 10858, + "congdot": 10861, + "easter": 10862, + "apacir": 10863, + "apE": 10864, + "eplus": 10865, + "pluse": 10866, + "Esim": 10867, + "Colone": 10868, + "Equal": 10869, + "eDDot": 10871, + "equivDD": 10872, + "ltcir": 10873, + "gtcir": 10874, + "ltquest": 10875, + "gtquest": 10876, + "les": 10877, + "ges": 10878, + "lesdot": 10879, + "gesdot": 10880, + "lesdoto": 10881, + "gesdoto": 10882, + "lesdotor": 10883, + "gesdotol": 10884, + "lap": 10885, + "gap": 10886, + "lne": 10887, + "gne": 10888, + "lnap": 10889, + "gnap": 10890, + "lEg": 10891, + "gEl": 10892, + "lsime": 10893, + "gsime": 10894, + "lsimg": 10895, + "gsiml": 10896, + "lgE": 10897, + "glE": 10898, + "lesges": 10899, + "gesles": 10900, + "els": 10901, + "egs": 10902, + "elsdot": 10903, + "egsdot": 10904, + "el": 10905, + "eg": 10906, + "siml": 10909, + "simg": 10910, + "simlE": 10911, + "simgE": 10912, + "LessLess": 10913, + "GreaterGreater": 10914, + "glj": 10916, + "gla": 10917, + "ltcc": 10918, + "gtcc": 10919, + "lescc": 10920, + "gescc": 10921, + "smt": 10922, + "lat": 10923, + "smte": 10924, + "late": 10925, + "bumpE": 10926, + "pre": 10927, + "sce": 10928, + "prE": 10931, + "scE": 10932, + "prnE": 10933, + "scnE": 10934, + "prap": 10935, + "scap": 10936, + "prnap": 10937, + "scnap": 10938, + "Pr": 10939, + "Sc": 10940, + "subdot": 10941, + "supdot": 10942, + "subplus": 10943, + "supplus": 10944, + "submult": 10945, + "supmult": 10946, + "subedot": 10947, + "supedot": 10948, + "subE": 10949, + "supE": 10950, + "subsim": 10951, + "supsim": 10952, + "subnE": 10955, + "supnE": 10956, + "csub": 10959, + "csup": 10960, + "csube": 10961, + "csupe": 10962, + "subsup": 10963, + "supsub": 10964, + "subsub": 10965, + "supsup": 10966, + "suphsub": 10967, + "supdsub": 10968, + "forkv": 10969, + "topfork": 10970, + "mlcp": 10971, + "Dashv": 10980, + "Vdashl": 10982, + "Barv": 10983, + "vBar": 10984, + "vBarv": 10985, + "Vbar": 10987, + "Not": 10988, + "bNot": 10989, + "rnmid": 10990, + "cirmid": 10991, + "midcir": 10992, + "topcir": 10993, + "nhpar": 10994, + "parsim": 10995, + "parsl": 11005, + "fflig": 64256, + "filig": 64257, + "fllig": 64258, + "ffilig": 64259, + "ffllig": 64260, + "Ascr": 119964, + "Cscr": 119966, + "Dscr": 119967, + "Gscr": 119970, + "Jscr": 119973, + "Kscr": 119974, + "Nscr": 119977, + "Oscr": 119978, + "Pscr": 119979, + "Qscr": 119980, + "Sscr": 119982, + "Tscr": 119983, + "Uscr": 119984, + "Vscr": 119985, + "Wscr": 119986, + "Xscr": 119987, + "Yscr": 119988, + "Zscr": 119989, + "ascr": 119990, + "bscr": 119991, + "cscr": 119992, + "dscr": 119993, + "fscr": 119995, + "hscr": 119997, + "iscr": 119998, + "jscr": 119999, + "kscr": 120000, + "lscr": 120001, + "mscr": 120002, + "nscr": 120003, + "pscr": 120005, + "qscr": 120006, + "rscr": 120007, + "sscr": 120008, + "tscr": 120009, + "uscr": 120010, + "vscr": 120011, + "wscr": 120012, + "xscr": 120013, + "yscr": 120014, + "zscr": 120015, + "Afr": 120068, + "Bfr": 120069, + "Dfr": 120071, + "Efr": 120072, + "Ffr": 120073, + "Gfr": 120074, + "Jfr": 120077, + "Kfr": 120078, + "Lfr": 120079, + "Mfr": 120080, + "Nfr": 120081, + "Ofr": 120082, + "Pfr": 120083, + "Qfr": 120084, + "Sfr": 120086, + "Tfr": 120087, + "Ufr": 120088, + "Vfr": 120089, + "Wfr": 120090, + "Xfr": 120091, + "Yfr": 120092, + "afr": 120094, + "bfr": 120095, + "cfr": 120096, + "dfr": 120097, + "efr": 120098, + "ffr": 120099, + "gfr": 120100, + "hfr": 120101, + "ifr": 120102, + "jfr": 120103, + "kfr": 120104, + "lfr": 120105, + "mfr": 120106, + "nfr": 120107, + "ofr": 120108, + "pfr": 120109, + "qfr": 120110, + "rfr": 120111, + "sfr": 120112, + "tfr": 120113, + "ufr": 120114, + "vfr": 120115, + "wfr": 120116, + "xfr": 120117, + "yfr": 120118, + "zfr": 120119, + "Aopf": 120120, + "Bopf": 120121, + "Dopf": 120123, + "Eopf": 120124, + "Fopf": 120125, + "Gopf": 120126, + "Iopf": 120128, + "Jopf": 120129, + "Kopf": 120130, + "Lopf": 120131, + "Mopf": 120132, + "Oopf": 120134, + "Sopf": 120138, + "Topf": 120139, + "Uopf": 120140, + "Vopf": 120141, + "Wopf": 120142, + "Xopf": 120143, + "Yopf": 120144, + "aopf": 120146, + "bopf": 120147, + "copf": 120148, + "dopf": 120149, + "eopf": 120150, + "fopf": 120151, + "gopf": 120152, + "hopf": 120153, + "iopf": 120154, + "jopf": 120155, + "kopf": 120156, + "lopf": 120157, + "mopf": 120158, + "nopf": 120159, + "oopf": 120160, + "popf": 120161, + "qopf": 120162, + "ropf": 120163, + "sopf": 120164, + "topf": 120165, + "uopf": 120166, + "vopf": 120167, + "wopf": 120168, + "xopf": 120169, + "yopf": 120170, + "zopf": 120171 +}; + +export default FromHTMLEntity; diff --git a/plugins/srktoolbox/src/core/operations/FromHex.mjs b/plugins/srktoolbox/src/core/operations/FromHex.mjs new file mode 100644 index 00000000..10abebe8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromHex.mjs @@ -0,0 +1,154 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {fromHex, FROM_HEX_DELIM_OPTIONS} from "../lib/Hex.mjs"; +import Utils from "../Utils.mjs"; + +/** + * From Hex operation + */ +class FromHex extends Operation { + + /** + * FromHex constructor + */ + constructor() { + super(); + + this.name = "十六进制转字符"; + this.module = "Default"; + this.description = "把十六进制字符串解码为原先的内容。

例如: ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a 解码为UTF-8字符串 Γειά σου"; + this.infoURL = "https://wikipedia.org/wiki/Hexadecimal"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + name: "分隔符", + type: "option", + value: FROM_HEX_DELIM_OPTIONS + } + ]; + this.checks = [ + { + pattern: "^(?:[\\dA-F]{2})+$", + flags: "i", + args: ["无"] + }, + { + pattern: "^[\\dA-F]{2}(?: [\\dA-F]{2})*$", + flags: "i", + args: ["空格"] + }, + { + pattern: "^[\\dA-F]{2}(?:,[\\dA-F]{2})*$", + flags: "i", + args: ["逗号"] + }, + { + pattern: "^[\\dA-F]{2}(?:;[\\dA-F]{2})*$", + flags: "i", + args: ["分号"] + }, + { + pattern: "^[\\dA-F]{2}(?::[\\dA-F]{2})*$", + flags: "i", + args: ["冒号"] + }, + { + pattern: "^[\\dA-F]{2}(?:\\n[\\dA-F]{2})*$", + flags: "i", + args: ["换行"] + }, + { + pattern: "^[\\dA-F]{2}(?:\\r\\n[\\dA-F]{2})*$", + flags: "i", + args: ["CRLF"] + }, + { + pattern: "^(?:0x[\\dA-F]{2})+$", + flags: "i", + args: ["0x"] + }, + { + pattern: "^0x[\\dA-F]{2}(?:,0x[\\dA-F]{2})*$", + flags: "i", + args: ["0x和逗号"] + }, + { + pattern: "^(?:\\\\x[\\dA-F]{2})+$", + flags: "i", + args: ["\\x"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const delim = args[0] || "自动"; + return fromHex(input, delim, 2); + } + + /** + * Highlight to Hex + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + if (args[0] === "自动") return false; + const delim = Utils.charRep(args[0] || "空格"), + len = delim === "\r\n" ? 1 : delim.length, + width = len + 2; + + // 0x and \x are added to the beginning if they are selected, so increment the positions accordingly + if (delim === "0x" || delim === "\\x") { + if (pos[0].start > 1) pos[0].start -= 2; + else pos[0].start = 0; + if (pos[0].end > 1) pos[0].end -= 2; + else pos[0].end = 0; + } + + pos[0].start = pos[0].start === 0 ? 0 : Math.round(pos[0].start / width); + pos[0].end = pos[0].end === 0 ? 0 : Math.ceil(pos[0].end / width); + return pos; + } + + /** + * Highlight from Hex + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + const delim = Utils.charRep(args[0] || "空格"), + len = delim === "\r\n" ? 1 : delim.length; + + pos[0].start = pos[0].start * (2 + len); + pos[0].end = pos[0].end * (2 + len) - len; + + // 0x and \x are added to the beginning if they are selected, so increment the positions accordingly + if (delim === "0x" || delim === "\\x") { + pos[0].start += 2; + pos[0].end += 2; + } + return pos; + } +} + +export default FromHex; diff --git a/plugins/srktoolbox/src/core/operations/FromHexContent.mjs b/plugins/srktoolbox/src/core/operations/FromHexContent.mjs new file mode 100644 index 00000000..8931f51f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromHexContent.mjs @@ -0,0 +1,76 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {fromHex} from "../lib/Hex.mjs"; + +/** + * From Hex Content operation + */ +class FromHexContent extends Operation { + + /** + * FromHexContent constructor + */ + constructor() { + super(); + + this.name = "Snort Content解码"; + this.module = "Default"; + this.description = "把十六进制恢复成原始字符。SNORT的Content关键字使用此格式。

例: foo|3d|bar 解码为foo=bar."; + this.infoURL = "http://manual-snort-org.s3-website-us-east-1.amazonaws.com/node32.html#SECTION00451000000000000000"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = []; + this.checks = [ + { + pattern: "\\|([\\da-f]{2} ?)+\\|", + flags: "i", + args: [] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const regex = /\|([a-f\d ]{2,})\|/gi, + output = []; + let m, i = 0; + while ((m = regex.exec(input))) { + // Add up to match + for (; i < m.index;) + output.push(Utils.ord(input[i++])); + + // Add match + const bytes = fromHex(m[1]); + if (bytes) { + for (let a = 0; a < bytes.length;) + output.push(bytes[a++]); + } else { + // Not valid hex, print as normal + for (; i < regex.lastIndex;) + output.push(Utils.ord(input[i++])); + } + + i = regex.lastIndex; + } + // Add all after final match + for (; i < input.length;) + output.push(Utils.ord(input[i++])); + + return output; + } + +} + +export default FromHexContent; diff --git a/plugins/srktoolbox/src/core/operations/FromHexdump.mjs b/plugins/srktoolbox/src/core/operations/FromHexdump.mjs new file mode 100644 index 00000000..7b4f507d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromHexdump.mjs @@ -0,0 +1,168 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { fromHex } from "../lib/Hex.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; + + +/** + * From Hexdump operation + */ +class FromHexdump extends Operation { + + /** + * FromHexdump constructor + */ + constructor() { + super(); + + this.name = "从Hexdump提取"; + this.module = "Default"; + this.description = "尝试提取hexdump包含的原始数据。此操作支持大部分hexdump类型。在进行下一步分析之前务必确认输入数据的正确性。"; + this.infoURL = "https://wikipedia.org/wiki/Hex_dump"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = []; + this.checks = [ + { + pattern: "^(?:(?:[\\dA-F]{4,16}h?:?)?[ \\t]*((?:[\\dA-F]{2} ){1,8}(?:[ \\t]|[\\dA-F]{2}-)(?:[\\dA-F]{2} ){1,8}|(?:[\\dA-F]{4} )*[\\dA-F]{4}|(?:[\\dA-F]{2} )*[\\dA-F]{2})[^\\n]*\\n?){2,}$", + flags: "i", + args: [] + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const output = [], + regex = /^\s*(?:[\dA-F]{4,16}h?:?)?[ \t]+((?:[\dA-F]{2} ){1,8}(?:[ \t]|[\dA-F]{2}-)(?:[\dA-F]{2} ){1,8}|(?:[\dA-F]{4} )+(?:[\dA-F]{2})?|(?:[\dA-F]{2} )*[\dA-F]{2})/igm; + let block, line; + + while ((block = regex.exec(input))) { + line = fromHex(block[1].replace(/-/g, " ")); + for (let i = 0; i < line.length; i++) { + output.push(line[i]); + } + } + // Is this a CyberChef hexdump or is it from a different tool? + const width = input.indexOf("\n"); + const w = (width - 13) / 4; + // w should be the specified width of the hexdump and therefore a round number + if (Math.floor(w) !== w || input.indexOf("\r") !== -1 || output.indexOf(13) !== -1) { + if (isWorkerEnvironment()) self.setOption("attemptHighlight", false); + } + return output; + } + + /** + * Highlight From Hexdump + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + const w = args[0] || 16; + const width = 14 + (w*4); + + let line = Math.floor(pos[0].start / width); + let offset = pos[0].start % width; + + if (offset < 10) { // In line number section + pos[0].start = line*w; + } else if (offset > 10+(w*3)) { // In ASCII section + pos[0].start = (line+1)*w; + } else { // In byte section + pos[0].start = line*w + Math.floor((offset-10)/3); + } + + line = Math.floor(pos[0].end / width); + offset = pos[0].end % width; + + if (offset < 10) { // In line number section + pos[0].end = line*w; + } else if (offset > 10+(w*3)) { // In ASCII section + pos[0].end = (line+1)*w; + } else { // In byte section + pos[0].end = line*w + Math.ceil((offset-10)/3); + } + + return pos; + } + + /** + * Highlight From Hexdump in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + // Calculate overall selection + const w = args[0] || 16, + width = 14 + (w*4); + let line = Math.floor(pos[0].start / w), + offset = pos[0].start % w, + start = 0, + end = 0; + + pos[0].start = line*width + 10 + offset*3; + + line = Math.floor(pos[0].end / w); + offset = pos[0].end % w; + if (offset === 0) { + line--; + offset = w; + } + pos[0].end = line*width + 10 + offset*3 - 1; + + // Set up multiple selections for bytes + let startLineNum = Math.floor(pos[0].start / width); + const endLineNum = Math.floor(pos[0].end / width); + + if (startLineNum === endLineNum) { + pos.push(pos[0]); + } else { + start = pos[0].start; + end = (startLineNum+1) * width - w - 5; + pos.push({ start: start, end: end }); + while (end < pos[0].end) { + startLineNum++; + start = startLineNum * width + 10; + end = (startLineNum+1) * width - w - 5; + if (end > pos[0].end) end = pos[0].end; + pos.push({ start: start, end: end }); + } + } + + // Set up multiple selections for ASCII + const len = pos.length; + let lineNum = 0; + start = 0; + end = 0; + for (let i = 1; i < len; i++) { + lineNum = Math.floor(pos[i].start / width); + start = (((pos[i].start - (lineNum * width)) - 10) / 3) + (width - w -2) + (lineNum * width); + end = (((pos[i].end + 1 - (lineNum * width)) - 10) / 3) + (width - w -2) + (lineNum * width); + pos.push({ start: start, end: end }); + } + return pos; + } + +} + +export default FromHexdump; diff --git a/plugins/srktoolbox/src/core/operations/FromMessagePack.mjs b/plugins/srktoolbox/src/core/operations/FromMessagePack.mjs new file mode 100644 index 00000000..12bcf69e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromMessagePack.mjs @@ -0,0 +1,49 @@ +/** + * @author Matt C [matt@artemisbot.uk] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import notepack from "notepack.io"; + +/** + * From MessagePack operation + */ +class FromMessagePack extends Operation { + + /** + * FromMessagePack constructor + */ + constructor() { + super(); + + this.name = "MessagePack解码"; + this.module = "Code"; + this.description = "把MessagePack编码的内容还原为JSON。MessagePack是一种计算机数据交换格式。它是一种二进制形式,用于表示简单的数据结构,如数组和关联数组。"; + this.infoURL = "https://wikipedia.org/wiki/MessagePack"; + this.inputType = "ArrayBuffer"; + this.outputType = "JSON"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {JSON} + */ + run(input, args) { + try { + const buf = Buffer.from(new Uint8Array(input)); + return notepack.decode(buf); + } catch (err) { + throw new OperationError(`无法将 MessagePack 转换为 JSON: ${err}`); + } + } + +} + +export default FromMessagePack; diff --git a/plugins/srktoolbox/src/core/operations/FromModhex.mjs b/plugins/srktoolbox/src/core/operations/FromModhex.mjs new file mode 100644 index 00000000..0bfb0780 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromModhex.mjs @@ -0,0 +1,86 @@ +/** + * @author linuxgemini [ilteris@asenkron.com.tr] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import Operation from "../Operation.mjs"; +import { FROM_MODHEX_DELIM_OPTIONS, fromModhex } from "../lib/Modhex.mjs"; + +/** + * From Modhex operation + */ +class FromModhex extends Operation { + + /** + * FromModhex constructor + */ + constructor() { + super(); + + this.name = "Modhex解码"; + this.module = "Default"; + this.description = "将modhex字符串转换为原始值。"; + this.infoURL = "https://en.wikipedia.org/wiki/YubiKey#ModHex"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + name: "分隔符", + type: "option", + value: FROM_MODHEX_DELIM_OPTIONS + } + ]; + this.checks = [ + { + pattern: "^(?:[cbdefghijklnrtuv]{2})+$", + flags: "i", + args: ["无"] + }, + { + pattern: "^[cbdefghijklnrtuv]{2}(?: [cbdefghijklnrtuv]{2})*$", + flags: "i", + args: ["空格"] + }, + { + pattern: "^[cbdefghijklnrtuv]{2}(?:,[cbdefghijklnrtuv]{2})*$", + flags: "i", + args: ["逗号"] + }, + { + pattern: "^[cbdefghijklnrtuv]{2}(?:;[cbdefghijklnrtuv]{2})*$", + flags: "i", + args: ["分号"] + }, + { + pattern: "^[cbdefghijklnrtuv]{2}(?::[cbdefghijklnrtuv]{2})*$", + flags: "i", + args: ["冒号"] + }, + { + pattern: "^[cbdefghijklnrtuv]{2}(?:\\n[cbdefghijklnrtuv]{2})*$", + flags: "i", + args: ["换行"] + }, + { + pattern: "^[cbdefghijklnrtuv]{2}(?:\\r\\n[cbdefghijklnrtuv]{2})*$", + flags: "i", + args: ["CRLF"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const delim = args[0] || "自动"; + return fromModhex(input, delim, 2); + } +} + +export default FromModhex; diff --git a/plugins/srktoolbox/src/core/operations/FromMorseCode.mjs b/plugins/srktoolbox/src/core/operations/FromMorseCode.mjs new file mode 100644 index 00000000..66085bc9 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromMorseCode.mjs @@ -0,0 +1,156 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {LETTER_DELIM_OPTIONS, WORD_DELIM_OPTIONS} from "../lib/Delim.mjs"; + +/** + * From Morse Code operation + */ +class FromMorseCode extends Operation { + + /** + * FromMorseCode constructor + */ + constructor() { + super(); + + this.name = "摩尔斯电码解码"; + this.module = "Default"; + this.description = "把摩尔斯电码还原为大写字母。"; + this.infoURL = "https://wikipedia.org/wiki/Morse_code"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "字母分隔符", + "type": "option", + "value": LETTER_DELIM_OPTIONS + }, + { + "name": "单词分隔符", + "type": "option", + "value": WORD_DELIM_OPTIONS + } + ]; + this.checks = [ + { + pattern: "(?:^[-. \\n]{5,}$|^[_. \\n]{5,}$|^(?:dash|dot| |\\n){5,}$)", + flags: "i", + args: ["Space", "Line feed"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (!this.reversedTable) { + this.reverseTable(); + } + + const letterDelim = Utils.charRep(args[0]); + const wordDelim = Utils.charRep(args[1]); + + input = input.replace(/-|‐|−|_|–|—|dash/ig, ""); // hyphen-minus|hyphen|minus-sign|undersore|en-dash|em-dash + input = input.replace(/\.|·|dot/ig, ""); + + let words = input.split(wordDelim); + const self = this; + words = Array.prototype.map.call(words, function(word) { + const signals = word.split(letterDelim); + + const letters = signals.map(function(signal) { + return self.reversedTable[signal]; + }); + + return letters.join(""); + }); + words = words.join(" "); + + return words; + } + + + /** + * Reverses the Morse Code lookup table + */ + reverseTable() { + this.reversedTable = {}; + + for (const letter in MORSE_TABLE) { + const signal = MORSE_TABLE[letter]; + this.reversedTable[signal] = letter; + } + } + +} + +const MORSE_TABLE = { + "A": "", + "B": "", + "C": "", + "D": "", + "E": "", + "F": "", + "G": "", + "H": "", + "I": "", + "J": "", + "K": "", + "L": "", + "M": "", + "N": "", + "O": "", + "P": "", + "Q": "", + "R": "", + "S": "", + "T": "", + "U": "", + "V": "", + "W": "", + "X": "", + "Y": "", + "Z": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "", + "6": "", + "7": "", + "8": "", + "9": "", + "0": "", + ".": "", + ",": "", + ":": "", + ";": "", + "!": "", + "?": "", + "'": "", + "\"": "", + "/": "", + "-": "", + "+": "", + "(": "", + ")": "", + "@": "", + "=": "", + "&": "", + "_": "", + "$": "", + " ": "" +}; + +export default FromMorseCode; diff --git a/plugins/srktoolbox/src/core/operations/FromOctal.mjs b/plugins/srktoolbox/src/core/operations/FromOctal.mjs new file mode 100644 index 00000000..62fa6853 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromOctal.mjs @@ -0,0 +1,84 @@ +/** + * @author Matt C [matt@artemisbot.uk] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {DELIM_OPTIONS} from "../lib/Delim.mjs"; + +/** + * From Octal operation + */ +class FromOctal extends Operation { + + /** + * FromOctal constructor + */ + constructor() { + super(); + + this.name = "八进制转字符"; + this.module = "Default"; + this.description = "把八进制字符串解码为原先的内容。

例: 316 223 316 265 316 271 316 254 40 317 203 316 277 317 205 解码成UTF-8字符串 Γειά σου"; + this.infoURL = "https://wikipedia.org/wiki/Octal"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": DELIM_OPTIONS + } + ]; + this.checks = [ + { + pattern: "^(?:[0-7]{1,2}|[123][0-7]{2})(?: (?:[0-7]{1,2}|[123][0-7]{2}))*$", + flags: "", + args: ["空格"] + }, + { + pattern: "^(?:[0-7]{1,2}|[123][0-7]{2})(?:,(?:[0-7]{1,2}|[123][0-7]{2}))*$", + flags: "", + args: ["逗号"] + }, + { + pattern: "^(?:[0-7]{1,2}|[123][0-7]{2})(?:;(?:[0-7]{1,2}|[123][0-7]{2}))*$", + flags: "", + args: ["分号"] + }, + { + pattern: "^(?:[0-7]{1,2}|[123][0-7]{2})(?::(?:[0-7]{1,2}|[123][0-7]{2}))*$", + flags: "", + args: ["冒号"] + }, + { + pattern: "^(?:[0-7]{1,2}|[123][0-7]{2})(?:\\n(?:[0-7]{1,2}|[123][0-7]{2}))*$", + flags: "", + args: ["换行"] + }, + { + pattern: "^(?:[0-7]{1,2}|[123][0-7]{2})(?:\\r\\n(?:[0-7]{1,2}|[123][0-7]{2}))*$", + flags: "", + args: ["CRLF"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const delim = Utils.charRep(args[0] || "Space"); + if (input.length === 0) return []; + return input.split(delim).map(val => parseInt(val, 8)); + } + +} + +export default FromOctal; diff --git a/plugins/srktoolbox/src/core/operations/FromPunycode.mjs b/plugins/srktoolbox/src/core/operations/FromPunycode.mjs new file mode 100644 index 00000000..83113e46 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromPunycode.mjs @@ -0,0 +1,55 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import punycode from "punycode"; + +/** + * From Punycode operation + */ +class FromPunycode extends Operation { + + /** + * FromPunycode constructor + */ + constructor() { + super(); + + this.name = "Punycode解码"; + this.module = "Encodings"; + this.description = "Punycode是用ASCII字符的一个子集来编码Unicode域名的一种方法。

例: mnchen-3ya 解码为 m\xfcnchen"; + this.infoURL = "https://wikipedia.org/wiki/Punycode"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "国际化域名(带xn--)", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const idn = args[0]; + + if (idn) { + return punycode.toUnicode(input); + } else { + return punycode.decode(input); + } + } + +} + +export default FromPunycode; diff --git a/plugins/srktoolbox/src/core/operations/FromQuotedPrintable.mjs b/plugins/srktoolbox/src/core/operations/FromQuotedPrintable.mjs new file mode 100644 index 00000000..767ce270 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromQuotedPrintable.mjs @@ -0,0 +1,71 @@ +/** + * Some parts taken from mimelib (http://github.com/andris9/mimelib) + * @author Andris Reinman + * @license MIT + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * From Quoted Printable operation + */ +class FromQuotedPrintable extends Operation { + + /** + * FromQuotedPrintable constructor + */ + constructor() { + super(); + + this.name = "QP解码"; + this.module = "Default"; + this.description = "Converts QP-encoded text back to standard text. This format is a content transfer encoding common in email messages.

e.g. The quoted-printable encoded string hello=20world becomes hello world"; + this.infoURL = "https://wikipedia.org/wiki/Quoted-printable"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = []; + this.checks = [ + { + pattern: "^[\\x21-\\x3d\\x3f-\\x7e \\t]{0,76}(?:=[\\da-f]{2}|=\\r?\\n)(?:[\\x21-\\x3d\\x3f-\\x7e \\t]|=[\\da-f]{2}|=\\r?\\n)*$", + flags: "i", + args: [] + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const str = input.replace(/=(?:\r?\n|$)/g, ""); + + const encodedBytesCount = (str.match(/=[\da-fA-F]{2}/g) || []).length, + bufferLength = str.length - encodedBytesCount * 2, + buffer = new Array(bufferLength); + let chr, hex, + bufferPos = 0; + + for (let i = 0, len = str.length; i < len; i++) { + chr = str.charAt(i); + if (chr === "=" && (hex = str.substr(i + 1, 2)) && /[\da-fA-F]{2}/.test(hex)) { + buffer[bufferPos++] = parseInt(hex, 16); + i += 2; + continue; + } + buffer[bufferPos++] = chr.charCodeAt(0); + } + + return buffer; + } + +} + +export default FromQuotedPrintable; diff --git a/plugins/srktoolbox/src/core/operations/FromUNIXTimestamp.mjs b/plugins/srktoolbox/src/core/operations/FromUNIXTimestamp.mjs new file mode 100644 index 00000000..c75440d1 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FromUNIXTimestamp.mjs @@ -0,0 +1,94 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import moment from "moment-timezone"; +import {UNITS} from "../lib/DateTime.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * From UNIX Timestamp operation + */ +class FromUNIXTimestamp extends Operation { + + /** + * FromUNIXTimestamp constructor + */ + constructor() { + super(); + + this.name = "从UNIX时间戳提取"; + this.module = "Default"; + this.description = "将UNIX时间戳转换为DateTime字符串。

例: 978346800 转换为 Mon 1 January 2001 11:00:00 UTC

UNIX时间,或称POSIX时间是UNIX或类UNIX系统使用的时间表示方式:从UTC1970年1月1日0时0分0秒起至现在的总秒数,不考虑闰秒。"; + this.infoURL = "https://wikipedia.org/wiki/Unix_time"; + this.inputType = "number"; + this.outputType = "string"; + this.args = [ + { + "name": "单位", + "type": "option", + "value": UNITS + } + ]; + this.checks = [ + { + pattern: "^1?\\d{9}$", + flags: "", + args: ["秒 (s)"] + }, + { + pattern: "^1?\\d{12}$", + flags: "", + args: ["毫秒 (ms)"] + }, + { + pattern: "^1?\\d{15}$", + flags: "", + args: ["微秒 (μs)"] + }, + { + pattern: "^1?\\d{18}$", + flags: "", + args: ["纳秒 (ns)"] + } + ]; + } + + /** + * @param {number} input + * @param {Object[]} args + * @returns {string} + * + * @throws {OperationError} if invalid unit + */ + run(input, args) { + const units = args[0]; + let d; + + input = parseFloat(input); + + if (units === "秒 (s)") { + d = moment.unix(input); + return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss") + " UTC"; + } else if (units === "毫秒 (ms)") { + d = moment(input); + return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC"; + } else if (units === "微秒 (μs)") { + d = moment(input / 1000); + return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC"; + } else if (units === "纳秒 (ns)") { + d = moment(input / 1000000); + return d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss.SSS") + " UTC"; + } else { + throw new OperationError("无效单位"); + } + } + +} + +export default FromUNIXTimestamp; diff --git a/plugins/srktoolbox/src/core/operations/FuzzyMatch.mjs b/plugins/srktoolbox/src/core/operations/FuzzyMatch.mjs new file mode 100644 index 00000000..fc8cf776 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/FuzzyMatch.mjs @@ -0,0 +1,123 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {fuzzyMatch, calcMatchRanges, DEFAULT_WEIGHTS} from "../lib/FuzzyMatch.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Fuzzy Match operation + */ +class FuzzyMatch extends Operation { + + /** + * FuzzyMatch constructor + */ + constructor() { + super(); + + this.name = "模糊匹配"; + this.module = "Default"; + this.description = "根据指定的权重对输入进行模糊匹配。

例如:搜索 dpan 可匹配 Don't Panic"; + this.infoURL = "https://wikipedia.org/wiki/Fuzzy_matching_(computer-assisted_translation)"; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + name: "查找内容", + type: "binaryString", + value: "" + }, + { + name: "顺序加成", + type: "number", + value: DEFAULT_WEIGHTS.sequentialBonus, + hint: "如果匹配内容相邻则提高权重" + }, + { + name: "分隔符加成", + type: "number", + value: DEFAULT_WEIGHTS.separatorBonus, + hint: "如果匹配内容刚好在分隔符后则提高权重" + }, + { + name: "驼峰加成", + type: "number", + value: DEFAULT_WEIGHTS.camelBonus, + hint: "如果匹配内容是大写而上一个匹配是小写则提高权重" + }, + { + name: "首字母加成", + type: "number", + value: DEFAULT_WEIGHTS.firstLetterBonus, + hint: "如果首字母匹配则提高权重" + }, + { + name: "前置字母惩罚", + type: "number", + value: DEFAULT_WEIGHTS.leadingLetterPenalty, + hint: "根据首个匹配之前的字符数降低权重" + }, + { + name: "前置字母惩罚最大值", + type: "number", + value: DEFAULT_WEIGHTS.maxLeadingLetterPenalty, + hint: "前置字母惩罚可降低权重的最大值" + }, + { + name: "不匹配字母惩罚", + type: "number", + value: DEFAULT_WEIGHTS.unmatchedLetterPenalty + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const searchStr = args[0]; + const weights = { + sequentialBonus: args[1], + separatorBonus: args[2], + camelBonus: args[3], + firstLetterBonus: args[4], + leadingLetterPenalty: args[5], + maxLeadingLetterPenalty: args[6], + unmatchedLetterPenalty: args[7] + }; + const matches = fuzzyMatch(searchStr, input, true, weights); + + if (!matches) { + return "未找到对应内容。"; + } + + let result = "", pos = 0, hlClass = "hl1"; + matches.forEach(([matches, score, idxs]) => { + const matchRanges = calcMatchRanges(idxs); + + matchRanges.forEach(([start, length], i) => { + result += Utils.escapeHtml(input.slice(pos, start)); + if (i === 0) result += ``; + pos = start + length; + result += `${Utils.escapeHtml(input.slice(start, pos))}`; + }); + result += ""; + hlClass = hlClass === "hl1" ? "hl2" : "hl1"; + }); + + result += Utils.escapeHtml(input.slice(pos, input.length)); + + return result; + } + +} + +export default FuzzyMatch; diff --git a/plugins/srktoolbox/src/core/operations/GOSTDecrypt.mjs b/plugins/srktoolbox/src/core/operations/GOSTDecrypt.mjs new file mode 100644 index 00000000..644d6cf6 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GOSTDecrypt.mjs @@ -0,0 +1,153 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { toHexFast, fromHex } from "../lib/Hex.mjs"; +import { CryptoGost, GostEngine } from "@wavesenterprise/crypto-gost-js/index.js"; + +/** + * GOST Decrypt operation + */ +class GOSTDecrypt extends Operation { + + /** + * GOSTDecrypt constructor + */ + constructor() { + super(); + + this.name = "GOST解密"; + this.module = "Ciphers"; + this.description = "GOST块密码(Magma)是苏联和俄罗斯政府标准的对称密钥块密码,块大小为64位,定义在标准GOST 28147-89(RFC 5830)中。最初的标准于1989年发布,未为密码命名,但最新修订的标准GOST R 34.12-2015(RFC 7801,RFC 8891)指定它可以被称为Magma。GOST哈希函数基于该密码。新标准还指定了一个名为Kuznyechik的新的128位块密码。

该标准在1970年代开发,曾被标记为“绝密”,1990年降级为“机密”。苏联解体后不久,该标准被解密,并在1994年向公众发布。GOST 28147是苏联替代美国标准算法DES的选择,因此两者在结构上非常相似。"; + this.infoURL = "https://wikipedia.org/wiki/GOST_(block_cipher)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Key", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "IV", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "输入类型", + type: "option", + value: ["十六进制", "原始字节"] + }, + { + name: "输出类型", + type: "option", + value: ["原始字节", "十六进制"] + }, + { + name: "算法", + type: "argSelector", + value: [ + { + name: "GOST 28147 (1989)", + on: [5] + }, + { + name: "GOST R 34.12 (Magma, 2015)", + off: [5] + }, + { + name: "GOST R 34.12 (Kuznyechik, 2015)", + off: [5] + } + ] + }, + { + name: "sBox", + type: "option", + value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"] + }, + { + name: "块模式", + type: "option", + value: ["ECB", "CFB", "OFB", "CTR", "CBC"] + }, + { + name: "Key meshing模式", + type: "option", + value: ["NO", "CP"] + }, + { + name: "填充", + type: "option", + value: ["NO", "PKCS5", "ZERO", "RANDOM", "BIT"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const [keyObj, ivObj, inputType, outputType, version, sBox, blockMode, keyMeshing, padding] = args; + + const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option)); + const iv = toHexFast(Utils.convertToByteArray(ivObj.string, ivObj.option)); + input = inputType === "十六进制" ? input : toHexFast(Utils.strToArrayBuffer(input)); + + let blockLength, versionNum; + switch (version) { + case "GOST 28147 (1989)": + versionNum = 1989; + blockLength = 64; + break; + case "GOST R 34.12 (Magma, 2015)": + versionNum = 2015; + blockLength = 64; + break; + case "GOST R 34.12 (Kuznyechik, 2015)": + versionNum = 2015; + blockLength = 128; + break; + default: + throw new OperationError(`Unknown algorithm version: ${version}`); + } + + const sBoxVal = versionNum === 1989 ? sBox : null; + + const algorithm = { + version: versionNum, + length: blockLength, + mode: "ES", + sBox: sBoxVal, + block: blockMode, + keyMeshing: keyMeshing, + padding: padding + }; + + try { + const Hex = CryptoGost.coding.Hex; + if (iv) algorithm.iv = Hex.decode(iv); + + const cipher = GostEngine.getGostCipher(algorithm); + const out = Hex.encode(cipher.decrypt(Hex.decode(key), Hex.decode(input))); + + return outputType === "十六进制" ? out : Utils.byteArrayToChars(fromHex(out)); + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default GOSTDecrypt; diff --git a/plugins/srktoolbox/src/core/operations/GOSTEncrypt.mjs b/plugins/srktoolbox/src/core/operations/GOSTEncrypt.mjs new file mode 100644 index 00000000..f184e118 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GOSTEncrypt.mjs @@ -0,0 +1,153 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { toHexFast, fromHex } from "../lib/Hex.mjs"; +import { CryptoGost, GostEngine } from "@wavesenterprise/crypto-gost-js/index.js"; + +/** + * GOST Encrypt operation + */ +class GOSTEncrypt extends Operation { + + /** + * GOSTEncrypt constructor + */ + constructor() { + super(); + + this.name = "GOST加密"; + this.module = "Ciphers"; + this.description = "GOST块密码(Magma)是苏联和俄罗斯政府标准的对称密钥块密码,块大小为64位,定义在标准GOST 28147-89(RFC 5830)中。最初的标准于1989年发布,未为密码命名,但最新修订的标准GOST R 34.12-2015(RFC 7801,RFC 8891)指定它可以被称为Magma。GOST哈希函数基于该密码。新标准还指定了一个名为Kuznyechik的新的128位块密码。

该标准在1970年代开发,曾被标记为“绝密”,1990年降级为“机密”。苏联解体后不久,该标准被解密,并在1994年向公众发布。GOST 28147是苏联替代美国标准算法DES的选择,因此两者在结构上非常相似。"; + this.infoURL = "https://wikipedia.org/wiki/GOST_(block_cipher)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Key", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "IV", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "输入类型", + type: "option", + value: ["原始字节", "十六进制"] + }, + { + name: "输出类型", + type: "option", + value: ["十六进制", "原始字节"] + }, + { + name: "算法", + type: "argSelector", + value: [ + { + name: "GOST 28147 (1989)", + on: [5] + }, + { + name: "GOST R 34.12 (Magma, 2015)", + off: [5] + }, + { + name: "GOST R 34.12 (Kuznyechik, 2015)", + off: [5] + } + ] + }, + { + name: "sBox", + type: "option", + value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"] + }, + { + name: "块类型", + type: "option", + value: ["ECB", "CFB", "OFB", "CTR", "CBC"] + }, + { + name: "Key meshing模式", + type: "option", + value: ["NO", "CP"] + }, + { + name: "填充", + type: "option", + value: ["NO", "PKCS5", "ZERO", "RANDOM", "BIT"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const [keyObj, ivObj, inputType, outputType, version, sBox, blockMode, keyMeshing, padding] = args; + + const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option)); + const iv = toHexFast(Utils.convertToByteArray(ivObj.string, ivObj.option)); + input = inputType === "十六进制" ? input : toHexFast(Utils.strToArrayBuffer(input)); + + let blockLength, versionNum; + switch (version) { + case "GOST 28147 (1989)": + versionNum = 1989; + blockLength = 64; + break; + case "GOST R 34.12 (Magma, 2015)": + versionNum = 2015; + blockLength = 64; + break; + case "GOST R 34.12 (Kuznyechik, 2015)": + versionNum = 2015; + blockLength = 128; + break; + default: + throw new OperationError(`Unknown algorithm version: ${version}`); + } + + const sBoxVal = versionNum === 1989 ? sBox : null; + + const algorithm = { + version: versionNum, + length: blockLength, + mode: "ES", + sBox: sBoxVal, + block: blockMode, + keyMeshing: keyMeshing, + padding: padding + }; + + try { + const Hex = CryptoGost.coding.Hex; + if (iv) algorithm.iv = Hex.decode(iv); + + const cipher = GostEngine.getGostCipher(algorithm); + const out = Hex.encode(cipher.encrypt(Hex.decode(key), Hex.decode(input))); + + return outputType === "十六进制" ? out : Utils.byteArrayToChars(fromHex(out)); + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default GOSTEncrypt; diff --git a/plugins/srktoolbox/src/core/operations/GOSTHash.mjs b/plugins/srktoolbox/src/core/operations/GOSTHash.mjs new file mode 100644 index 00000000..c76c3342 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GOSTHash.mjs @@ -0,0 +1,93 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import GostDigest from "../vendor/gost/gostDigest.mjs"; +import { toHexFast } from "../lib/Hex.mjs"; + +/** + * GOST hash operation + */ +class GOSTHash extends Operation { + + /** + * GOSTHash constructor + */ + constructor() { + super(); + + this.name = "GOST哈希"; + this.module = "Hashing"; + this.description = "GOST哈希算法,由标准GOST R 34.11-94和GOST 34.311-95定义,是一种256位哈希算法。最初为俄罗斯国家标准GOST R 34.11-94 Information Technology – Cryptographic Information Security – Hash Function。由其它独联体国家使用的等效标准是GOST 34.311-95。

此算法不是新标准GOST R 34.11-2012当中定义的Streebog哈希算法。

GOST哈希算法基于GOST块加密算法。"; + this.infoURL = "https://wikipedia.org/wiki/GOST_(hash_function)"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "算法", + type: "argSelector", + value: [ + { + name: "GOST 28147 (1994)", + off: [1], + on: [2] + }, + { + name: "GOST R 34.11 (Streebog, 2012)", + on: [1], + off: [2] + } + ] + }, + { + name: "摘要长度", + type: "option", + value: ["256", "512"] + }, + { + name: "sBox", + type: "option", + value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"] + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [version, length, sBox] = args; + + const versionNum = version === "GOST 28147 (1994)" ? 1994 : 2012; + const algorithm = { + name: versionNum === 1994 ? "GOST 28147" : "GOST R 34.10", + version: versionNum, + mode: "HASH" + }; + + if (versionNum === 1994) { + algorithm.sBox = sBox; + } else { + algorithm.length = parseInt(length, 10); + } + + try { + const gostDigest = new GostDigest(algorithm); + + return toHexFast(gostDigest.digest(input)); + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default GOSTHash; diff --git a/plugins/srktoolbox/src/core/operations/GOSTKeyUnwrap.mjs b/plugins/srktoolbox/src/core/operations/GOSTKeyUnwrap.mjs new file mode 100644 index 00000000..16bfac67 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GOSTKeyUnwrap.mjs @@ -0,0 +1,144 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { toHexFast, fromHex } from "../lib/Hex.mjs"; +import { CryptoGost, GostEngine } from "@wavesenterprise/crypto-gost-js/index.js"; + +/** + * GOST Key Unwrap operation + */ +class GOSTKeyUnwrap extends Operation { + + /** + * GOSTKeyUnwrap constructor + */ + constructor() { + super(); + + this.name = "GOST密钥解包装"; + this.module = "Ciphers"; + this.description = "对使用GOST块加密包装的密钥解包装。"; + this.infoURL = "https://wikipedia.org/wiki/GOST_(block_cipher)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Key", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "User Key Material", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "Input type", + type: "option", + value: ["十六进制", "原始字节"] + }, + { + name: "Output type", + type: "option", + value: ["原始字节", "十六进制"] + }, + { + name: "算法", + type: "argSelector", + value: [ + { + name: "GOST 28147 (1989)", + on: [5] + }, + { + name: "GOST R 34.12 (Magma, 2015)", + off: [5] + }, + { + name: "GOST R 34.12 (Kuznyechik, 2015)", + off: [5] + } + ] + }, + { + name: "sBox", + type: "option", + value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"] + }, + { + name: "Key包装", + type: "option", + value: ["NO", "CP", "SC"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const [keyObj, ukmObj, inputType, outputType, version, sBox, keyWrapping] = args; + + const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option)); + const ukm = toHexFast(Utils.convertToByteArray(ukmObj.string, ukmObj.option)); + input = inputType === "十六进制" ? input : toHexFast(Utils.strToArrayBuffer(input)); + + let blockLength, versionNum; + switch (version) { + case "GOST 28147 (1989)": + versionNum = 1989; + blockLength = 64; + break; + case "GOST R 34.12 (Magma, 2015)": + versionNum = 2015; + blockLength = 64; + break; + case "GOST R 34.12 (Kuznyechik, 2015)": + versionNum = 2015; + blockLength = 128; + break; + default: + throw new OperationError(`Unknown algorithm version: ${version}`); + } + + const sBoxVal = versionNum === 1989 ? sBox : null; + + const algorithm = { + version: versionNum, + length: blockLength, + mode: "KW", + sBox: sBoxVal, + keyWrapping: keyWrapping + }; + + try { + const Hex = CryptoGost.coding.Hex; + algorithm.ukm = Hex.decode(ukm); + + const cipher = GostEngine.getGostCipher(algorithm); + const out = Hex.encode(cipher.unwrapKey(Hex.decode(key), Hex.decode(input))); + + return outputType === "十六进制" ? out : Utils.byteArrayToChars(fromHex(out)); + } catch (err) { + if (err.toString().includes("Invalid typed array length")) { + throw new OperationError("无效的输入长度:必须为块大小的整数倍。"); + } + throw new OperationError(err); + } + } + +} + +export default GOSTKeyUnwrap; diff --git a/plugins/srktoolbox/src/core/operations/GOSTKeyWrap.mjs b/plugins/srktoolbox/src/core/operations/GOSTKeyWrap.mjs new file mode 100644 index 00000000..b10bcbf4 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GOSTKeyWrap.mjs @@ -0,0 +1,144 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { toHexFast, fromHex } from "../lib/Hex.mjs"; +import { CryptoGost, GostEngine } from "@wavesenterprise/crypto-gost-js/index.js"; + +/** + * GOST Key Wrap operation + */ +class GOSTKeyWrap extends Operation { + + /** + * GOSTKeyWrap constructor + */ + constructor() { + super(); + + this.name = "GOST密钥包装"; + this.module = "Ciphers"; + this.description = "使用GOST块密码对密钥在不可信环境中进行包装。"; + this.infoURL = "https://wikipedia.org/wiki/GOST_(block_cipher)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Key", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "User Key Material", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "输入类型", + type: "option", + value: ["原始字节", "十六进制"] + }, + { + name: "输出类型", + type: "option", + value: ["十六进制", "原始字节"] + }, + { + name: "算法", + type: "argSelector", + value: [ + { + name: "GOST 28147 (1989)", + on: [5] + }, + { + name: "GOST R 34.12 (Magma, 2015)", + off: [5] + }, + { + name: "GOST R 34.12 (Kuznyechik, 2015)", + off: [5] + } + ] + }, + { + name: "sBox", + type: "option", + value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"] + }, + { + name: "Key包装", + type: "option", + value: ["NO", "CP", "SC"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const [keyObj, ukmObj, inputType, outputType, version, sBox, keyWrapping] = args; + + const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option)); + const ukm = toHexFast(Utils.convertToByteArray(ukmObj.string, ukmObj.option)); + input = inputType === "十六进制" ? input : toHexFast(Utils.strToArrayBuffer(input)); + + let blockLength, versionNum; + switch (version) { + case "GOST 28147 (1989)": + versionNum = 1989; + blockLength = 64; + break; + case "GOST R 34.12 (Magma, 2015)": + versionNum = 2015; + blockLength = 64; + break; + case "GOST R 34.12 (Kuznyechik, 2015)": + versionNum = 2015; + blockLength = 128; + break; + default: + throw new OperationError(`Unknown algorithm version: ${version}`); + } + + const sBoxVal = versionNum === 1989 ? sBox : null; + + const algorithm = { + version: versionNum, + length: blockLength, + mode: "KW", + sBox: sBoxVal, + keyWrapping: keyWrapping + }; + + try { + const Hex = CryptoGost.coding.Hex; + algorithm.ukm = Hex.decode(ukm); + + const cipher = GostEngine.getGostCipher(algorithm); + const out = Hex.encode(cipher.wrapKey(Hex.decode(key), Hex.decode(input))); + + return outputType === "十六进制" ? out : Utils.byteArrayToChars(fromHex(out)); + } catch (err) { + if (err.toString().includes("Invalid typed array length")) { + throw new OperationError("无效的输入长度:必须为块大小的整数倍。"); + } + throw new OperationError(err); + } + } + +} + +export default GOSTKeyWrap; diff --git a/plugins/srktoolbox/src/core/operations/GOSTSign.mjs b/plugins/srktoolbox/src/core/operations/GOSTSign.mjs new file mode 100644 index 00000000..260f100f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GOSTSign.mjs @@ -0,0 +1,144 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { toHexFast, fromHex } from "../lib/Hex.mjs"; +import { CryptoGost, GostEngine } from "@wavesenterprise/crypto-gost-js/index.js"; + +/** + * GOST Sign operation + */ +class GOSTSign extends Operation { + + /** + * GOSTSign constructor + */ + constructor() { + super(); + + this.name = "GOST签名"; + this.module = "Ciphers"; + this.description = "使用GOST块加密对明文信息签名。"; + this.infoURL = "https://wikipedia.org/wiki/GOST_(block_cipher)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Key", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "IV", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "输入类型", + type: "option", + value: ["原始字节", "十六进制"] + }, + { + name: "输出类型", + type: "option", + value: ["十六进制", "原始字节"] + }, + { + name: "算法", + type: "argSelector", + value: [ + { + name: "GOST 28147 (1989)", + on: [5] + }, + { + name: "GOST R 34.12 (Magma, 2015)", + off: [5] + }, + { + name: "GOST R 34.12 (Kuznyechik, 2015)", + off: [5] + } + ] + }, + { + name: "sBox", + type: "option", + value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"] + }, + { + name: "MAC长度", + type: "number", + value: 32, + min: 8, + max: 64, + step: 8 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const [keyObj, ivObj, inputType, outputType, version, sBox, macLength] = args; + + const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option)); + const iv = toHexFast(Utils.convertToByteArray(ivObj.string, ivObj.option)); + input = inputType === "十六进制" ? input : toHexFast(Utils.strToArrayBuffer(input)); + + let blockLength, versionNum; + switch (version) { + case "GOST 28147 (1989)": + versionNum = 1989; + blockLength = 64; + break; + case "GOST R 34.12 (Magma, 2015)": + versionNum = 2015; + blockLength = 64; + break; + case "GOST R 34.12 (Kuznyechik, 2015)": + versionNum = 2015; + blockLength = 128; + break; + default: + throw new OperationError(`Unknown algorithm version: ${version}`); + } + + const sBoxVal = versionNum === 1989 ? sBox : null; + + const algorithm = { + version: versionNum, + length: blockLength, + mode: "MAC", + sBox: sBoxVal, + macLength: macLength + }; + + try { + const Hex = CryptoGost.coding.Hex; + if (iv) algorithm.iv = Hex.decode(iv); + + const cipher = GostEngine.getGostCipher(algorithm); + const out = Hex.encode(cipher.sign(Hex.decode(key), Hex.decode(input))); + + return outputType === "十六进制" ? out : Utils.byteArrayToChars(fromHex(out)); + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default GOSTSign; diff --git a/plugins/srktoolbox/src/core/operations/GOSTVerify.mjs b/plugins/srktoolbox/src/core/operations/GOSTVerify.mjs new file mode 100644 index 00000000..e828b291 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GOSTVerify.mjs @@ -0,0 +1,138 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { toHexFast } from "../lib/Hex.mjs"; +import { CryptoGost, GostEngine } from "@wavesenterprise/crypto-gost-js/index.js"; + +/** + * GOST Verify operation + */ +class GOSTVerify extends Operation { + + /** + * GOSTVerify constructor + */ + constructor() { + super(); + + this.name = "GOST验证"; + this.module = "Ciphers"; + this.description = "使用GOST块加密算法验证明文信息的签名。将签名输入到MAC框中。"; + this.infoURL = "https://wikipedia.org/wiki/GOST_(block_cipher)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Key", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "IV", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "MAC", + type: "toggleString", + value: "", + toggleValues: ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + name: "输入类型", + type: "option", + value: ["原始字节", "十六进制"] + }, + { + name: "算法", + type: "argSelector", + value: [ + { + name: "GOST 28147 (1989)", + on: [5] + }, + { + name: "GOST R 34.12 (Magma, 2015)", + off: [5] + }, + { + name: "GOST R 34.12 (Kuznyechik, 2015)", + off: [5] + } + ] + }, + { + name: "sBox", + type: "option", + value: ["E-TEST", "E-A", "E-B", "E-C", "E-D", "E-SC", "E-Z", "D-TEST", "D-A", "D-SC"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const [keyObj, ivObj, macObj, inputType, version, sBox] = args; + + const key = toHexFast(Utils.convertToByteArray(keyObj.string, keyObj.option)); + const iv = toHexFast(Utils.convertToByteArray(ivObj.string, ivObj.option)); + const mac = toHexFast(Utils.convertToByteArray(macObj.string, macObj.option)); + input = inputType === "十六进制" ? input : toHexFast(Utils.strToArrayBuffer(input)); + + let blockLength, versionNum; + switch (version) { + case "GOST 28147 (1989)": + versionNum = 1989; + blockLength = 64; + break; + case "GOST R 34.12 (Magma, 2015)": + versionNum = 2015; + blockLength = 64; + break; + case "GOST R 34.12 (Kuznyechik, 2015)": + versionNum = 2015; + blockLength = 128; + break; + default: + throw new OperationError(`Unknown algorithm version: ${version}`); + } + + const sBoxVal = versionNum === 1989 ? sBox : null; + + const algorithm = { + version: versionNum, + length: blockLength, + mode: "MAC", + sBox: sBoxVal, + macLength: mac.length * 4 + }; + + try { + const Hex = CryptoGost.coding.Hex; + if (iv) algorithm.iv = Hex.decode(iv); + + const cipher = GostEngine.getGostCipher(algorithm); + const out = cipher.verify(Hex.decode(key), Hex.decode(mac), Hex.decode(input)); + + return out ? "签名相符" : "签名不符"; + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default GOSTVerify; diff --git a/plugins/srktoolbox/src/core/operations/GenerateAllChecksums.mjs b/plugins/srktoolbox/src/core/operations/GenerateAllChecksums.mjs new file mode 100644 index 00000000..a5c65b46 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GenerateAllChecksums.mjs @@ -0,0 +1,256 @@ +/** + * @author r4mos [2k95ljkhg@mozmail.com] + * @copyright Crown Copyright 2025 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Adler32Checksum from "./Adler32Checksum.mjs"; +import CRCChecksum from "./CRCChecksum.mjs"; +import Fletcher8Checksum from "./Fletcher8Checksum.mjs"; +import Fletcher16Checksum from "./Fletcher16Checksum.mjs"; +import Fletcher32Checksum from "./Fletcher32Checksum.mjs"; +import Fletcher64Checksum from "./Fletcher64Checksum.mjs"; + +/** + * Generate all checksums operation + */ +class GenerateAllChecksums extends Operation { + + /** + * GenerateAllChecksums constructor + */ + constructor() { + super(); + + this.name = "生成所有校验和"; + this.module = "Crypto"; + this.description = "对给定的输入生成所有支持的校验和。"; + this.infoURL = "https://wikipedia.org/wiki/Checksum"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "长度(位)", + type: "option", + value: [ + "全部", "3", "4", "5", "6", "7", "8", "10", "11", "12", "13", "14", "15", "16", "17", "21", "24", "30", "31", "32", "40", "64", "82" + ] + }, + { + name: "包括名称", + type: "boolean", + value: true + }, + ]; + + const adler32 = new Adler32Checksum; + const crc = new CRCChecksum; + const fletcher8 = new Fletcher8Checksum; + const fletcher16 = new Fletcher16Checksum; + const fletcher32 = new Fletcher32Checksum; + const fletcher64 = new Fletcher64Checksum; + this.checksums = [ + {name: "CRC-3/GSM", algo: crc, params: ["CRC-3/GSM"]}, + {name: "CRC-3/ROHC", algo: crc, params: ["CRC-3/ROHC"]}, + {name: "CRC-4/G-704", algo: crc, params: ["CRC-4/G-704"]}, + {name: "CRC-4/INTERLAKEN", algo: crc, params: ["CRC-4/INTERLAKEN"]}, + {name: "CRC-4/ITU", algo: crc, params: ["CRC-4/ITU"]}, + {name: "CRC-5/EPC", algo: crc, params: ["CRC-5/EPC"]}, + {name: "CRC-5/EPC-C1G2", algo: crc, params: ["CRC-5/EPC-C1G2"]}, + {name: "CRC-5/G-704", algo: crc, params: ["CRC-5/G-704"]}, + {name: "CRC-5/ITU", algo: crc, params: ["CRC-5/ITU"]}, + {name: "CRC-5/USB", algo: crc, params: ["CRC-5/USB"]}, + {name: "CRC-6/CDMA2000-A", algo: crc, params: ["CRC-6/CDMA2000-A"]}, + {name: "CRC-6/CDMA2000-B", algo: crc, params: ["CRC-6/CDMA2000-B"]}, + {name: "CRC-6/DARC", algo: crc, params: ["CRC-6/DARC"]}, + {name: "CRC-6/G-704", algo: crc, params: ["CRC-6/G-704"]}, + {name: "CRC-6/GSM", algo: crc, params: ["CRC-6/GSM"]}, + {name: "CRC-6/ITU", algo: crc, params: ["CRC-6/ITU"]}, + {name: "CRC-7/MMC", algo: crc, params: ["CRC-7/MMC"]}, + {name: "CRC-7/ROHC", algo: crc, params: ["CRC-7/ROHC"]}, + {name: "CRC-7/UMTS", algo: crc, params: ["CRC-7/UMTS"]}, + {name: "CRC-8", algo: crc, params: ["CRC-8"]}, + {name: "CRC-8/8H2F", algo: crc, params: ["CRC-8/8H2F"]}, + {name: "CRC-8/AES", algo: crc, params: ["CRC-8/AES"]}, + {name: "CRC-8/AUTOSAR", algo: crc, params: ["CRC-8/AUTOSAR"]}, + {name: "CRC-8/BLUETOOTH", algo: crc, params: ["CRC-8/BLUETOOTH"]}, + {name: "CRC-8/CDMA2000", algo: crc, params: ["CRC-8/CDMA2000"]}, + {name: "CRC-8/DARC", algo: crc, params: ["CRC-8/DARC"]}, + {name: "CRC-8/DVB-S2", algo: crc, params: ["CRC-8/DVB-S2"]}, + {name: "CRC-8/EBU", algo: crc, params: ["CRC-8/EBU"]}, + {name: "CRC-8/GSM-A", algo: crc, params: ["CRC-8/GSM-A"]}, + {name: "CRC-8/GSM-B", algo: crc, params: ["CRC-8/GSM-B"]}, + {name: "CRC-8/HITAG", algo: crc, params: ["CRC-8/HITAG"]}, + {name: "CRC-8/I-432-1", algo: crc, params: ["CRC-8/I-432-1"]}, + {name: "CRC-8/I-CODE", algo: crc, params: ["CRC-8/I-CODE"]}, + {name: "CRC-8/ITU", algo: crc, params: ["CRC-8/ITU"]}, + {name: "CRC-8/LTE", algo: crc, params: ["CRC-8/LTE"]}, + {name: "CRC-8/MAXIM", algo: crc, params: ["CRC-8/MAXIM"]}, + {name: "CRC-8/MAXIM-DOW", algo: crc, params: ["CRC-8/MAXIM-DOW"]}, + {name: "CRC-8/MIFARE-MAD", algo: crc, params: ["CRC-8/MIFARE-MAD"]}, + {name: "CRC-8/NRSC-5", algo: crc, params: ["CRC-8/NRSC-5"]}, + {name: "CRC-8/OPENSAFETY", algo: crc, params: ["CRC-8/OPENSAFETY"]}, + {name: "CRC-8/ROHC", algo: crc, params: ["CRC-8/ROHC"]}, + {name: "CRC-8/SAE-J1850", algo: crc, params: ["CRC-8/SAE-J1850"]}, + {name: "CRC-8/SAE-J1850-ZERO", algo: crc, params: ["CRC-8/SAE-J1850-ZERO"]}, + {name: "CRC-8/SMBUS", algo: crc, params: ["CRC-8/SMBUS"]}, + {name: "CRC-8/TECH-3250", algo: crc, params: ["CRC-8/TECH-3250"]}, + {name: "CRC-8/WCDMA", algo: crc, params: ["CRC-8/WCDMA"]}, + {name: "Fletcher-8", algo: fletcher8, params: []}, + {name: "CRC-10/ATM", algo: crc, params: ["CRC-10/ATM"]}, + {name: "CRC-10/CDMA2000", algo: crc, params: ["CRC-10/CDMA2000"]}, + {name: "CRC-10/GSM", algo: crc, params: ["CRC-10/GSM"]}, + {name: "CRC-10/I-610", algo: crc, params: ["CRC-10/I-610"]}, + {name: "CRC-11/FLEXRAY", algo: crc, params: ["CRC-11/FLEXRAY"]}, + {name: "CRC-11/UMTS", algo: crc, params: ["CRC-11/UMTS"]}, + {name: "CRC-12/3GPP", algo: crc, params: ["CRC-12/3GPP"]}, + {name: "CRC-12/CDMA2000", algo: crc, params: ["CRC-12/CDMA2000"]}, + {name: "CRC-12/DECT", algo: crc, params: ["CRC-12/DECT"]}, + {name: "CRC-12/GSM", algo: crc, params: ["CRC-12/GSM"]}, + {name: "CRC-12/UMTS", algo: crc, params: ["CRC-12/UMTS"]}, + {name: "CRC-13/BBC", algo: crc, params: ["CRC-13/BBC"]}, + {name: "CRC-14/DARC", algo: crc, params: ["CRC-14/DARC"]}, + {name: "CRC-14/GSM", algo: crc, params: ["CRC-14/GSM"]}, + {name: "CRC-15/CAN", algo: crc, params: ["CRC-15/CAN"]}, + {name: "CRC-15/MPT1327", algo: crc, params: ["CRC-15/MPT1327"]}, + {name: "CRC-16", algo: crc, params: ["CRC-16"]}, + {name: "CRC-16/A", algo: crc, params: ["CRC-16/A"]}, + {name: "CRC-16/ACORN", algo: crc, params: ["CRC-16/ACORN"]}, + {name: "CRC-16/ARC", algo: crc, params: ["CRC-16/ARC"]}, + {name: "CRC-16/AUG-CCITT", algo: crc, params: ["CRC-16/AUG-CCITT"]}, + {name: "CRC-16/AUTOSAR", algo: crc, params: ["CRC-16/AUTOSAR"]}, + {name: "CRC-16/B", algo: crc, params: ["CRC-16/B"]}, + {name: "CRC-16/BLUETOOTH", algo: crc, params: ["CRC-16/BLUETOOTH"]}, + {name: "CRC-16/BUYPASS", algo: crc, params: ["CRC-16/BUYPASS"]}, + {name: "CRC-16/CCITT", algo: crc, params: ["CRC-16/CCITT"]}, + {name: "CRC-16/CCITT-FALSE", algo: crc, params: ["CRC-16/CCITT-FALSE"]}, + {name: "CRC-16/CCITT-TRUE", algo: crc, params: ["CRC-16/CCITT-TRUE"]}, + {name: "CRC-16/CCITT-ZERO", algo: crc, params: ["CRC-16/CCITT-ZERO"]}, + {name: "CRC-16/CDMA2000", algo: crc, params: ["CRC-16/CDMA2000"]}, + {name: "CRC-16/CMS", algo: crc, params: ["CRC-16/CMS"]}, + {name: "CRC-16/DARC", algo: crc, params: ["CRC-16/DARC"]}, + {name: "CRC-16/DDS-110", algo: crc, params: ["CRC-16/DDS-110"]}, + {name: "CRC-16/DECT-R", algo: crc, params: ["CRC-16/DECT-R"]}, + {name: "CRC-16/DECT-X", algo: crc, params: ["CRC-16/DECT-X"]}, + {name: "CRC-16/DNP", algo: crc, params: ["CRC-16/DNP"]}, + {name: "CRC-16/EN-13757", algo: crc, params: ["CRC-16/EN-13757"]}, + {name: "CRC-16/EPC", algo: crc, params: ["CRC-16/EPC"]}, + {name: "CRC-16/EPC-C1G2", algo: crc, params: ["CRC-16/EPC-C1G2"]}, + {name: "CRC-16/GENIBUS", algo: crc, params: ["CRC-16/GENIBUS"]}, + {name: "CRC-16/GSM", algo: crc, params: ["CRC-16/GSM"]}, + {name: "CRC-16/I-CODE", algo: crc, params: ["CRC-16/I-CODE"]}, + {name: "CRC-16/IBM", algo: crc, params: ["CRC-16/IBM"]}, + {name: "CRC-16/IBM-3740", algo: crc, params: ["CRC-16/IBM-3740"]}, + {name: "CRC-16/IBM-SDLC", algo: crc, params: ["CRC-16/IBM-SDLC"]}, + {name: "CRC-16/IEC-61158-2", algo: crc, params: ["CRC-16/IEC-61158-2"]}, + {name: "CRC-16/ISO-HDLC", algo: crc, params: ["CRC-16/ISO-HDLC"]}, + {name: "CRC-16/ISO-IEC-14443-3-A", algo: crc, params: ["CRC-16/ISO-IEC-14443-3-A"]}, + {name: "CRC-16/ISO-IEC-14443-3-B", algo: crc, params: ["CRC-16/ISO-IEC-14443-3-B"]}, + {name: "CRC-16/KERMIT", algo: crc, params: ["CRC-16/KERMIT"]}, + {name: "CRC-16/LHA", algo: crc, params: ["CRC-16/LHA"]}, + {name: "CRC-16/LJ1200", algo: crc, params: ["CRC-16/LJ1200"]}, + {name: "CRC-16/LTE", algo: crc, params: ["CRC-16/LTE"]}, + {name: "CRC-16/M17", algo: crc, params: ["CRC-16/M17"]}, + {name: "CRC-16/MAXIM", algo: crc, params: ["CRC-16/MAXIM"]}, + {name: "CRC-16/MAXIM-DOW", algo: crc, params: ["CRC-16/MAXIM-DOW"]}, + {name: "CRC-16/MCRF4XX", algo: crc, params: ["CRC-16/MCRF4XX"]}, + {name: "CRC-16/MODBUS", algo: crc, params: ["CRC-16/MODBUS"]}, + {name: "CRC-16/NRSC-5", algo: crc, params: ["CRC-16/NRSC-5"]}, + {name: "CRC-16/OPENSAFETY-A", algo: crc, params: ["CRC-16/OPENSAFETY-A"]}, + {name: "CRC-16/OPENSAFETY-B", algo: crc, params: ["CRC-16/OPENSAFETY-B"]}, + {name: "CRC-16/PROFIBUS", algo: crc, params: ["CRC-16/PROFIBUS"]}, + {name: "CRC-16/RIELLO", algo: crc, params: ["CRC-16/RIELLO"]}, + {name: "CRC-16/SPI-FUJITSU", algo: crc, params: ["CRC-16/SPI-FUJITSU"]}, + {name: "CRC-16/T10-DIF", algo: crc, params: ["CRC-16/T10-DIF"]}, + {name: "CRC-16/TELEDISK", algo: crc, params: ["CRC-16/TELEDISK"]}, + {name: "CRC-16/TMS37157", algo: crc, params: ["CRC-16/TMS37157"]}, + {name: "CRC-16/UMTS", algo: crc, params: ["CRC-16/UMTS"]}, + {name: "CRC-16/USB", algo: crc, params: ["CRC-16/USB"]}, + {name: "CRC-16/V-41-LSB", algo: crc, params: ["CRC-16/V-41-LSB"]}, + {name: "CRC-16/V-41-MSB", algo: crc, params: ["CRC-16/V-41-MSB"]}, + {name: "CRC-16/VERIFONE", algo: crc, params: ["CRC-16/VERIFONE"]}, + {name: "CRC-16/X-25", algo: crc, params: ["CRC-16/X-25"]}, + {name: "CRC-16/XMODEM", algo: crc, params: ["CRC-16/XMODEM"]}, + {name: "CRC-16/ZMODEM", algo: crc, params: ["CRC-16/ZMODEM"]}, + {name: "Fletcher-16", algo: fletcher16, params: []}, + {name: "CRC-17/CAN-FD", algo: crc, params: ["CRC-17/CAN-FD"]}, + {name: "CRC-21/CAN-FD", algo: crc, params: ["CRC-21/CAN-FD"]}, + {name: "CRC-24/BLE", algo: crc, params: ["CRC-24/BLE"]}, + {name: "CRC-24/FLEXRAY-A", algo: crc, params: ["CRC-24/FLEXRAY-A"]}, + {name: "CRC-24/FLEXRAY-B", algo: crc, params: ["CRC-24/FLEXRAY-B"]}, + {name: "CRC-24/INTERLAKEN", algo: crc, params: ["CRC-24/INTERLAKEN"]}, + {name: "CRC-24/LTE-A", algo: crc, params: ["CRC-24/LTE-A"]}, + {name: "CRC-24/LTE-B", algo: crc, params: ["CRC-24/LTE-B"]}, + {name: "CRC-24/OPENPGP", algo: crc, params: ["CRC-24/OPENPGP"]}, + {name: "CRC-24/OS-9", algo: crc, params: ["CRC-24/OS-9"]}, + {name: "CRC-30/CDMA", algo: crc, params: ["CRC-30/CDMA"]}, + {name: "CRC-31/PHILIPS", algo: crc, params: ["CRC-31/PHILIPS"]}, + {name: "Adler-32", algo: adler32, params: []}, + {name: "CRC-32", algo: crc, params: ["CRC-32"]}, + {name: "CRC-32/AAL5", algo: crc, params: ["CRC-32/AAL5"]}, + {name: "CRC-32/ADCCP", algo: crc, params: ["CRC-32/ADCCP"]}, + {name: "CRC-32/AIXM", algo: crc, params: ["CRC-32/AIXM"]}, + {name: "CRC-32/AUTOSAR", algo: crc, params: ["CRC-32/AUTOSAR"]}, + {name: "CRC-32/BASE91-C", algo: crc, params: ["CRC-32/BASE91-C"]}, + {name: "CRC-32/BASE91-D", algo: crc, params: ["CRC-32/BASE91-D"]}, + {name: "CRC-32/BZIP2", algo: crc, params: ["CRC-32/BZIP2"]}, + {name: "CRC-32/C", algo: crc, params: ["CRC-32/C"]}, + {name: "CRC-32/CASTAGNOLI", algo: crc, params: ["CRC-32/CASTAGNOLI"]}, + {name: "CRC-32/CD-ROM-EDC", algo: crc, params: ["CRC-32/CD-ROM-EDC"]}, + {name: "CRC-32/CKSUM", algo: crc, params: ["CRC-32/CKSUM"]}, + {name: "CRC-32/D", algo: crc, params: ["CRC-32/D"]}, + {name: "CRC-32/DECT-B", algo: crc, params: ["CRC-32/DECT-B"]}, + {name: "CRC-32/INTERLAKEN", algo: crc, params: ["CRC-32/INTERLAKEN"]}, + {name: "CRC-32/ISCSI", algo: crc, params: ["CRC-32/ISCSI"]}, + {name: "CRC-32/ISO-HDLC", algo: crc, params: ["CRC-32/ISO-HDLC"]}, + {name: "CRC-32/JAMCRC", algo: crc, params: ["CRC-32/JAMCRC"]}, + {name: "CRC-32/MEF", algo: crc, params: ["CRC-32/MEF"]}, + {name: "CRC-32/MPEG-2", algo: crc, params: ["CRC-32/MPEG-2"]}, + {name: "CRC-32/NVME", algo: crc, params: ["CRC-32/NVME"]}, + {name: "CRC-32/PKZIP", algo: crc, params: ["CRC-32/PKZIP"]}, + {name: "CRC-32/POSIX", algo: crc, params: ["CRC-32/POSIX"]}, + {name: "CRC-32/Q", algo: crc, params: ["CRC-32/Q"]}, + {name: "CRC-32/SATA", algo: crc, params: ["CRC-32/SATA"]}, + {name: "CRC-32/V-42", algo: crc, params: ["CRC-32/V-42"]}, + {name: "CRC-32/XFER", algo: crc, params: ["CRC-32/XFER"]}, + {name: "CRC-32/XZ", algo: crc, params: ["CRC-32/XZ"]}, + {name: "Fletcher-32", algo: fletcher32, params: []}, + {name: "CRC-40/GSM", algo: crc, params: ["CRC-40/GSM"]}, + {name: "CRC-64/ECMA-182", algo: crc, params: ["CRC-64/ECMA-182"]}, + {name: "CRC-64/GO-ECMA", algo: crc, params: ["CRC-64/GO-ECMA"]}, + {name: "CRC-64/GO-ISO", algo: crc, params: ["CRC-64/GO-ISO"]}, + {name: "CRC-64/MS", algo: crc, params: ["CRC-64/MS"]}, + {name: "CRC-64/NVME", algo: crc, params: ["CRC-64/NVME"]}, + {name: "CRC-64/REDIS", algo: crc, params: ["CRC-64/REDIS"]}, + {name: "CRC-64/WE", algo: crc, params: ["CRC-64/WE"]}, + {name: "CRC-64/XZ", algo: crc, params: ["CRC-64/XZ"]}, + {name: "Fletcher-64", algo: fletcher64, params: []}, + {name: "CRC-82/DARC", algo: crc, params: ["CRC-82/DARC"]} + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [length, includeNames] = args; + let output = ""; + this.checksums.forEach(checksum => { + const checksumLength = checksum.name.match(new RegExp("-(\\d{1,2})(\\/|$)"))[1]; + if (length === "全部" || length === checksumLength) { + const value = checksum.algo.run(new Uint8Array(input), checksum.params || []); + output += includeNames ? + `${checksum.name}:${" ".repeat(25-checksum.name.length)}${value}\n`: + `${value}\n`; + } + }); + return output; + } +} + +export default GenerateAllChecksums; diff --git a/plugins/srktoolbox/src/core/operations/GenerateAllHashes.mjs b/plugins/srktoolbox/src/core/operations/GenerateAllHashes.mjs new file mode 100644 index 00000000..8a660dd0 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GenerateAllHashes.mjs @@ -0,0 +1,181 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @author john19696 [john19696@protonmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import MD2 from "./MD2.mjs"; +import MD4 from "./MD4.mjs"; +import MD5 from "./MD5.mjs"; +import MD6 from "./MD6.mjs"; +import SHA0 from "./SHA0.mjs"; +import SHA1 from "./SHA1.mjs"; +import SHA2 from "./SHA2.mjs"; +import SHA3 from "./SHA3.mjs"; +import Keccak from "./Keccak.mjs"; +import Shake from "./Shake.mjs"; +import RIPEMD from "./RIPEMD.mjs"; +import HAS160 from "./HAS160.mjs"; +import Whirlpool from "./Whirlpool.mjs"; +import SSDEEP from "./SSDEEP.mjs"; +import CTPH from "./CTPH.mjs"; +import BLAKE2b from "./BLAKE2b.mjs"; +import BLAKE2s from "./BLAKE2s.mjs"; +import Streebog from "./Streebog.mjs"; +import GOSTHash from "./GOSTHash.mjs"; +import LMHash from "./LMHash.mjs"; +import NTHash from "./NTHash.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Generate all hashes operation + */ +class GenerateAllHashes extends Operation { + + /** + * GenerateAllHashes constructor + */ + constructor() { + super(); + + this.name = "哈希生成"; + this.module = "Crypto"; + this.description = "对给定输入数据计算目前支持的所有哈希值和校验和。"; + this.infoURL = "https://wikipedia.org/wiki/Comparison_of_cryptographic_hash_functions"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "长度(位)", + type: "option", + value: [ + "所有", "128", "160", "224", "256", "320", "384", "512" + ] + }, + { + name: "包括算法名称", + type: "boolean", + value: true + }, + ]; + this.hashes = [ + {name: "MD2", algo: (new MD2()), inputType: "arrayBuffer", params: []}, + {name: "MD4", algo: (new MD4()), inputType: "arrayBuffer", params: []}, + {name: "MD5", algo: (new MD5()), inputType: "arrayBuffer", params: []}, + {name: "MD6", algo: (new MD6()), inputType: "str", params: []}, + {name: "SHA0", algo: (new SHA0()), inputType: "arrayBuffer", params: []}, + {name: "SHA1", algo: (new SHA1()), inputType: "arrayBuffer", params: []}, + {name: "SHA2 224", algo: (new SHA2()), inputType: "arrayBuffer", params: ["224"]}, + {name: "SHA2 256", algo: (new SHA2()), inputType: "arrayBuffer", params: ["256"]}, + {name: "SHA2 384", algo: (new SHA2()), inputType: "arrayBuffer", params: ["384"]}, + {name: "SHA2 512", algo: (new SHA2()), inputType: "arrayBuffer", params: ["512"]}, + {name: "SHA3 224", algo: (new SHA3()), inputType: "arrayBuffer", params: ["224"]}, + {name: "SHA3 256", algo: (new SHA3()), inputType: "arrayBuffer", params: ["256"]}, + {name: "SHA3 384", algo: (new SHA3()), inputType: "arrayBuffer", params: ["384"]}, + {name: "SHA3 512", algo: (new SHA3()), inputType: "arrayBuffer", params: ["512"]}, + {name: "Keccak 224", algo: (new Keccak()), inputType: "arrayBuffer", params: ["224"]}, + {name: "Keccak 256", algo: (new Keccak()), inputType: "arrayBuffer", params: ["256"]}, + {name: "Keccak 384", algo: (new Keccak()), inputType: "arrayBuffer", params: ["384"]}, + {name: "Keccak 512", algo: (new Keccak()), inputType: "arrayBuffer", params: ["512"]}, + {name: "Shake 128", algo: (new Shake()), inputType: "arrayBuffer", params: ["128", 256]}, + {name: "Shake 256", algo: (new Shake()), inputType: "arrayBuffer", params: ["256", 512]}, + {name: "RIPEMD-128", algo: (new RIPEMD()), inputType: "arrayBuffer", params: ["128"]}, + {name: "RIPEMD-160", algo: (new RIPEMD()), inputType: "arrayBuffer", params: ["160"]}, + {name: "RIPEMD-256", algo: (new RIPEMD()), inputType: "arrayBuffer", params: ["256"]}, + {name: "RIPEMD-320", algo: (new RIPEMD()), inputType: "arrayBuffer", params: ["320"]}, + {name: "HAS-160", algo: (new HAS160()), inputType: "arrayBuffer", params: []}, + {name: "Whirlpool-0", algo: (new Whirlpool()), inputType: "arrayBuffer", params: ["Whirlpool-0"]}, + {name: "Whirlpool-T", algo: (new Whirlpool()), inputType: "arrayBuffer", params: ["Whirlpool-T"]}, + {name: "Whirlpool", algo: (new Whirlpool()), inputType: "arrayBuffer", params: ["Whirlpool"]}, + {name: "BLAKE2b-128", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["128", "十六进制", {string: "", option: "UTF8"}]}, + {name: "BLAKE2b-160", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["160", "十六进制", {string: "", option: "UTF8"}]}, + {name: "BLAKE2b-256", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["256", "十六进制", {string: "", option: "UTF8"}]}, + {name: "BLAKE2b-384", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["384", "十六进制", {string: "", option: "UTF8"}]}, + {name: "BLAKE2b-512", algo: (new BLAKE2b), inputType: "arrayBuffer", params: ["512", "十六进制", {string: "", option: "UTF8"}]}, + {name: "BLAKE2s-128", algo: (new BLAKE2s), inputType: "arrayBuffer", params: ["128", "十六进制", {string: "", option: "UTF8"}]}, + {name: "BLAKE2s-160", algo: (new BLAKE2s), inputType: "arrayBuffer", params: ["160", "十六进制", {string: "", option: "UTF8"}]}, + {name: "BLAKE2s-256", algo: (new BLAKE2s), inputType: "arrayBuffer", params: ["256", "十六进制", {string: "", option: "UTF8"}]}, + {name: "Streebog-256", algo: (new Streebog), inputType: "arrayBuffer", params: ["256"]}, + {name: "Streebog-512", algo: (new Streebog), inputType: "arrayBuffer", params: ["512"]}, + {name: "GOST", algo: (new GOSTHash), inputType: "arrayBuffer", params: ["GOST 28147 (1994)", "256", "D-A"]}, + {name: "LM Hash", algo: (new LMHash), inputType: "str", params: []}, + {name: "NT Hash", algo: (new NTHash), inputType: "str", params: []}, + {name: "SSDEEP", algo: (new SSDEEP()), inputType: "str"}, + {name: "CTPH", algo: (new CTPH()), inputType: "str"} + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [length, includeNames] = args; + this.inputArrayBuffer = input; + this.inputStr = Utils.arrayBufferToStr(input, false); + this.inputByteArray = new Uint8Array(input); + + let digest, output = ""; + // iterate over each of the hashes + this.hashes.forEach(hash => { + digest = this.executeAlgo(hash.algo, hash.inputType, hash.params || []); + output += this.formatDigest(digest, length, includeNames, hash.name); + }); + + return output; + } + + /** + * Executes a hash or checksum algorithm + * + * @param {Function} algo - The hash or checksum algorithm + * @param {string} inputType + * @param {Object[]} [params=[]] + * @returns {string} + */ + executeAlgo(algo, inputType, params=[]) { + let digest = null; + switch (inputType) { + case "arrayBuffer": + digest = algo.run(this.inputArrayBuffer, params); + break; + case "str": + digest = algo.run(this.inputStr, params); + break; + case "byteArray": + digest = algo.run(this.inputByteArray, params); + break; + default: + throw new OperationError("未知哈希类型: " + inputType); + } + + return digest; + } + + /** + * Formats the digest depending on user-specified arguments + * @param {string} digest + * @param {string} length + * @param {boolean} includeNames + * @param {string} name + * @returns {string} + */ + formatDigest(digest, length, includeNames, name) { + if (length !== "所有" && (digest.length * 4) !== parseInt(length, 10)) + return ""; + + if (!includeNames) + return digest + "\n"; + + return `${name}:${" ".repeat(13-name.length)}${digest}\n`; + } + +} + +export default GenerateAllHashes; diff --git a/plugins/srktoolbox/src/core/operations/GenerateDeBruijnSequence.mjs b/plugins/srktoolbox/src/core/operations/GenerateDeBruijnSequence.mjs new file mode 100644 index 00000000..c0fa02ca --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GenerateDeBruijnSequence.mjs @@ -0,0 +1,87 @@ +/** + * @author gchq77703 [gchq77703@gchq.gov.uk] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Generate De Bruijn Sequence operation + */ +class GenerateDeBruijnSequence extends Operation { + + /** + * GenerateDeBruijnSequence constructor + */ + constructor() { + super(); + + this.name = "生成德布鲁因序列"; + this.module = "Default"; + this.description = "根据给定的元素表和密钥长度生成滚动码。De Bruijn sequence又译德布勒蕴序列、德布莱英序列。"; + this.infoURL = "https://wikipedia.org/wiki/De_Bruijn_sequence"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "元素表长度 (k)", + type: "number", + value: 2 + }, + { + name: "密钥长度 (n)", + type: "number", + value: 3 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [k, n] = args; + + if (k < 2 || k > 9) { + throw new OperationError("无效的元素表长度,必须位于2和9之间(包括2和9)。"); + } + + if (n < 2) { + throw new OperationError("无效的密钥长度,至少为2。"); + } + + if (Math.pow(k, n) > 50000) { + throw new OperationError("太多组合数量,请减少k^n到小于50000。"); + } + + const a = new Array(k * n).fill(0); + const sequence = []; + + (function db(t = 1, p = 1) { + if (t > n) { + if (n % p !== 0) return; + for (let j = 1; j <= p; j++) { + sequence.push(a[j]); + } + return; + } + + a[t] = a[t - p]; + db(t + 1, p); + for (let j = a[t - p] + 1; j < k; j++) { + a[t] = j; + db(t + 1, t); + } + })(); + + return sequence.join(""); + } +} + +export default GenerateDeBruijnSequence; diff --git a/plugins/srktoolbox/src/core/operations/GenerateECDSAKeyPair.mjs b/plugins/srktoolbox/src/core/operations/GenerateECDSAKeyPair.mjs new file mode 100644 index 00000000..fb21fdf4 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GenerateECDSAKeyPair.mjs @@ -0,0 +1,104 @@ +/** + * @author cplussharp + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { cryptNotice } from "../lib/Crypt.mjs"; +import r from "jsrsasign"; + +/** + * Generate ECDSA Key Pair operation + */ +class GenerateECDSAKeyPair extends Operation { + + /** + * GenerateECDSAKeyPair constructor + */ + constructor() { + super(); + + this.name = "生成ECDSA密钥对"; + this.module = "Ciphers"; + this.description = `使用给定的曲线生成ECDSA密钥对。

${cryptNotice}`; + this.infoURL = "https://wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "椭圆曲线", + type: "option", + value: [ + "P-256", + "P-384", + "P-521" + ] + }, + { + name: "输出格式", + type: "option", + value: [ + "PEM", + "DER", + "JWK" + ] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const [curveName, outputFormat] = args; + + return new Promise((resolve, reject) => { + let internalCurveName; + switch (curveName) { + case "P-256": + internalCurveName = "secp256r1"; + break; + case "P-384": + internalCurveName = "secp384r1"; + break; + case "P-521": + internalCurveName = "secp521r1"; + break; + } + const keyPair = r.KEYUTIL.generateKeypair("EC", internalCurveName); + + let pubKey; + let privKey; + let result; + switch (outputFormat) { + case "PEM": + pubKey = r.KEYUTIL.getPEM(keyPair.pubKeyObj).replace(/\r/g, ""); + privKey = r.KEYUTIL.getPEM(keyPair.prvKeyObj, "PKCS8PRV").replace(/\r/g, ""); + result = pubKey + "\n" + privKey; + break; + case "DER": + result = keyPair.prvKeyObj.prvKeyHex; + break; + case "JWK": + pubKey = r.KEYUTIL.getJWKFromKey(keyPair.pubKeyObj); + pubKey.key_ops = ["verify"]; // eslint-disable-line camelcase + pubKey.kid = "PublicKey"; + privKey = r.KEYUTIL.getJWKFromKey(keyPair.prvKeyObj); + privKey.key_ops = ["sign"]; // eslint-disable-line camelcase + privKey.kid = "PrivateKey"; + result = JSON.stringify({keys: [privKey, pubKey]}, null, 4); + break; + } + + resolve(result); + }); + } + +} + +export default GenerateECDSAKeyPair; diff --git a/plugins/srktoolbox/src/core/operations/GenerateHOTP.mjs b/plugins/srktoolbox/src/core/operations/GenerateHOTP.mjs new file mode 100644 index 00000000..cbc4b56f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GenerateHOTP.mjs @@ -0,0 +1,70 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import * as OTPAuth from "otpauth"; + +/** + * Generate HOTP operation + */ +class GenerateHOTP extends Operation { + /** + * + */ + constructor() { + super(); + + this.name = "生成HOTP"; + this.module = "Default"; + this.description = "基于HMAC的一次性密码算法(英语:HMAC-based One-time Password algorithm,HOTP)是一种基于散列消息验证码(HMAC)的一次性密码(OTP)算法,同时也是开放验证提案的基础(OATH)。HOTP在2005年由IETF发布在RFC 4226标准文档中。

在输入框输入secret,或者留空来生成一个随机值。"; + this.infoURL = "https://wikipedia.org/wiki/HMAC-based_One-time_Password_algorithm"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "名称", + "type": "string", + "value": "" + }, + { + "name": "动态码长度", + "type": "number", + "value": 6 + }, + { + "name": "计数器", + "type": "number", + "value": 0 + } + ]; + } + + /** + * + */ + run(input, args) { + const secretStr = new TextDecoder("utf-8").decode(input).trim(); + const secret = secretStr ? secretStr.toUpperCase().replace(/\s+/g, "") : ""; + + const hotp = new OTPAuth.HOTP({ + issuer: "", + label: args[0], + algorithm: "SHA1", + digits: args[1], + counter: args[2], + secret: OTPAuth.Secret.fromBase32(secret) + }); + + const uri = hotp.toString(); + const code = hotp.generate(); + + return `URI: ${uri}\n\n动态码: ${code}`; + } +} + +export default GenerateHOTP; diff --git a/plugins/srktoolbox/src/core/operations/GenerateImage.mjs b/plugins/srktoolbox/src/core/operations/GenerateImage.mjs new file mode 100644 index 00000000..82ec33bc --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GenerateImage.mjs @@ -0,0 +1,193 @@ +/** + * @author pointhi [thomas.pointhuber@gmx.at] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; +import { Jimp, JimpMime, ResizeStrategy, rgbaToInt } from "jimp"; + +/** + * Generate Image operation + */ +class GenerateImage extends Operation { + /** + * GenerateImage constructor + */ + constructor() { + super(); + + this.name = "生成图像"; + this.module = "Image"; + this.description = + "使用输入作为像素值生成图像。"; + this.infoURL = ""; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = [ + { + name: "模式", + type: "option", + value: ["灰度", "RG", "RGB", "RGBA", "位"], + }, + { + name: "像素缩放倍率", + type: "number", + value: 8, + }, + { + name: "每行像素数", + type: "number", + value: 64, + }, + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + async run(input, args) { + const [mode, scale, width] = args; + input = new Uint8Array(input); + + if (scale <= 0) { + throw new OperationError("像素缩放倍率必须大于0"); + } + + if (width <= 0) { + throw new OperationError("每行像素数必须大于0"); + } + + const bytePerPixelMap = { + 灰度: 1, + RG: 2, + RGB: 3, + RGBA: 4, + 位: 1 / 8, + }; + + const bytesPerPixel = bytePerPixelMap[mode]; + + if (bytesPerPixel > 0 && input.length % bytesPerPixel !== 0) { + throw new OperationError( + `字节数不是 ${bytesPerPixel} 的倍数`, + ); + } + + const height = Math.ceil(input.length / bytesPerPixel / width); + const image = new Jimp({ width, height }); + + if (isWorkerEnvironment()) + self.sendStatusMessage("从给定数据生成图像……"); + + if (mode === "位") { + let index = 0; + for (let j = 0; j < input.length; j++) { + const curByte = Utils.bin(input[j]); + for (let k = 0; k < 8; k++, index++) { + const x = index % width; + const y = Math.floor(index / width); + + const value = curByte[k] === "0" ? 0xff : 0x00; + const pixel = rgbaToInt(value, value, value, 0xff); + image.setPixelColor(pixel, x, y); + } + } + } else { + let i = 0; + while (i < input.length) { + const index = i / bytesPerPixel; + const x = index % width; + const y = Math.floor(index / width); + + let red = 0x00; + let green = 0x00; + let blue = 0x00; + let alpha = 0xff; + + switch (mode) { + case "灰度": + red = green = blue = input[i++]; + break; + + case "RG": + red = input[i++]; + green = input[i++]; + break; + + case "RGB": + red = input[i++]; + green = input[i++]; + blue = input[i++]; + break; + + case "RGBA": + red = input[i++]; + green = input[i++]; + blue = input[i++]; + alpha = input[i++]; + break; + + default: + throw new OperationError(`不支持的模式:(${mode})`); + } + + try { + const pixel = rgbaToInt(red, green, blue, alpha); + image.setPixelColor(pixel, x, y); + } catch (err) { + throw new OperationError( + `生成图像时报错:(${err})`, + ); + } + } + } + + if (scale !== 1) { + if (isWorkerEnvironment()) + self.sendStatusMessage("缩放图像……"); + + image.scaleToFit({ + w: width * scale, + h: height * scale, + mode: ResizeStrategy.NEAREST_NEIGHBOR, + }); + } + + try { + const imageBuffer = await image.getBuffer(JimpMime.png); + return imageBuffer.buffer; + } catch (err) { + throw new OperationError(`生成图像时报错:(${err})`); + } + } + + /** + * Displays the generated image using HTML for web apps + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const dataArray = new Uint8Array(data); + + const type = isImage(dataArray); + if (!type) { + throw new OperationError("无效的文件类型。"); + } + + return ``; + } +} + +export default GenerateImage; diff --git a/plugins/srktoolbox/src/core/operations/GenerateLoremIpsum.mjs b/plugins/srktoolbox/src/core/operations/GenerateLoremIpsum.mjs new file mode 100644 index 00000000..b95d8731 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GenerateLoremIpsum.mjs @@ -0,0 +1,72 @@ +/** + * @author klaxon [klaxon@veyr.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { GenerateParagraphs, GenerateSentences, GenerateWords, GenerateBytes } from "../lib/LoremIpsum.mjs"; + +/** + * Generate Lorem Ipsum operation + */ +class GenerateLoremIpsum extends Operation { + + /** + * GenerateLoremIpsum constructor + */ + constructor() { + super(); + + this.name = "生成Lorem Ipsum"; + this.module = "Default"; + this.description = "生成给定长度的lorem ipsum占位文本。"; + this.infoURL = "https://wikipedia.org/wiki/Lorem_ipsum"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "长度", + "type": "number", + "value": "3" + }, + { + "name": "长度单位", + "type": "option", + "value": ["段落", "句子", "单词", "字节"] + } + + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [length, lengthType] = args; + if (length < 1) { + throw new OperationError("长度必须大于0"); + } + switch (lengthType) { + case "段落": + return GenerateParagraphs(length); + case "句子": + return GenerateSentences(length); + case "单词": + return GenerateWords(length); + case "字节": + return GenerateBytes(length); + default: + throw new OperationError("无效的长度类型"); + + } + } + +} + +export default GenerateLoremIpsum; diff --git a/plugins/srktoolbox/src/core/operations/GeneratePGPKeyPair.mjs b/plugins/srktoolbox/src/core/operations/GeneratePGPKeyPair.mjs new file mode 100644 index 00000000..0a5d4a3f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GeneratePGPKeyPair.mjs @@ -0,0 +1,124 @@ +/** + * @author tlwr [toby@toby.codes] + * @author Matt C [matt@artemisbot.uk] + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import kbpgp from "kbpgp"; +import { getSubkeySize, ASP } from "../lib/PGP.mjs"; +import { cryptNotice } from "../lib/Crypt.mjs"; +import * as es6promisify from "es6-promisify"; +const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify; + + +/** + * Generate PGP Key Pair operation + */ +class GeneratePGPKeyPair extends Operation { + + /** + * GeneratePGPKeyPair constructor + */ + constructor() { + super(); + + this.name = "生成PGP密钥对"; + this.module = "PGP"; + this.description = `生成PGP公钥/私钥对。支持RSA和椭圆曲线(Eliptic Curve,EC)密钥。

${cryptNotice}`; + this.infoURL = "https://wikipedia.org/wiki/Pretty_Good_Privacy"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "密钥类型", + "type": "option", + "value": ["RSA-1024", "RSA-2048", "RSA-4096", "ECC-256", "ECC-384", "ECC-521"] + }, + { + "name": "口令(非必填)", + "type": "string", + "value": "" + }, + { + "name": "姓名(非必填)", + "type": "string", + "value": "" + }, + { + "name": "Email(非必填)", + "type": "string", + "value": "" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + let [keyType, keySize] = args[0].split("-"); + const password = args[1], + name = args[2], + email = args[3]; + let userIdentifier = ""; + + keyType = keyType.toLowerCase(); + keySize = parseInt(keySize, 10); + + if (name) userIdentifier += name; + if (email) userIdentifier += ` <${email}>`; + + let flags = kbpgp.const.openpgp.certify_keys; + flags |= kbpgp.const.openpgp.sign_data; + flags |= kbpgp.const.openpgp.auth; + flags |= kbpgp.const.openpgp.encrypt_comm; + flags |= kbpgp.const.openpgp.encrypt_storage; + + const keyGenerationOptions = { + userid: userIdentifier, + ecc: keyType === "ecc", + primary: { + "nbits": keySize, + "flags": flags, + "expire_in": 0 + }, + subkeys: [{ + "nbits": getSubkeySize(keySize), + "flags": kbpgp.const.openpgp.sign_data, + "expire_in": 86400 * 365 * 8 + }, { + "nbits": getSubkeySize(keySize), + "flags": kbpgp.const.openpgp.encrypt_comm | kbpgp.const.openpgp.encrypt_storage, + "expire_in": 86400 * 365 * 2 + }], + asp: ASP + }; + + return new Promise(async (resolve, reject) => { + try { + const unsignedKey = await promisify(kbpgp.KeyManager.generate)(keyGenerationOptions); + await promisify(unsignedKey.sign.bind(unsignedKey))({}); + + const signedKey = unsignedKey, + privateKeyExportOptions = {}; + + if (password) privateKeyExportOptions.passphrase = password; + const privateKey = await promisify(signedKey.export_pgp_private.bind(signedKey))(privateKeyExportOptions); + const publicKey = await promisify(signedKey.export_pgp_public.bind(signedKey))({}); + resolve(privateKey + "\n" + publicKey.trim()); + } catch (err) { + reject(`生成公私钥对出错: ${err}`); + } + }); + } + +} + +export default GeneratePGPKeyPair; diff --git a/plugins/srktoolbox/src/core/operations/GenerateQRCode.mjs b/plugins/srktoolbox/src/core/operations/GenerateQRCode.mjs new file mode 100644 index 00000000..62809da6 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GenerateQRCode.mjs @@ -0,0 +1,96 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { generateQrCode } from "../lib/QRCode.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Generate QR Code operation + */ +class GenerateQRCode extends Operation { + + /** + * GenerateQRCode constructor + */ + constructor() { + super(); + + this.name = "生成二维码"; + this.module = "Image"; + this.description = "从输入生成一个Quick Response (QR)二维码。

QR码/图码(英语:Quick Response Code;全称为快速响应矩阵图码)是二维码的一种,于1994年由日本汽车零组件大厂电装公司的原昌宏所发明。条形码或称条码(英语:barcode),是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符。"; + this.infoURL = "https://wikipedia.org/wiki/QR_code"; + this.inputType = "string"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = [ + { + "name": "图像格式", + "type": "option", + "value": ["PNG", "SVG", "EPS", "PDF"] + }, + { + "name": "码点大小 (px)", + "type": "number", + "value": 5, + "min": 1 + }, + { + "name": "留白 (码点数)", + "type": "number", + "value": 4, + "min": 0 + }, + { + "name": "错误检测", + "type": "option", + "value": ["Low", "Medium", "Quartile", "High"], + "defaultIndex": 1 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const [format, size, margin, errorCorrection] = args; + + return generateQrCode(input, format, size, margin, errorCorrection); + } + + /** + * Displays the QR image using HTML for web apps + * + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data, args) { + if (!data.byteLength && !data.length) return ""; + const dataArray = new Uint8Array(data), + [format] = args; + if (format === "PNG") { + const type = isImage(dataArray); + if (!type) { + throw new OperationError("无效的文件类型。"); + } + + return ``; + } + + return Utils.arrayBufferToStr(data); + } + +} + +export default GenerateQRCode; diff --git a/plugins/srktoolbox/src/core/operations/GenerateRSAKeyPair.mjs b/plugins/srktoolbox/src/core/operations/GenerateRSAKeyPair.mjs new file mode 100644 index 00000000..89358d84 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GenerateRSAKeyPair.mjs @@ -0,0 +1,90 @@ +/** + * @author Matt C [me@mitt.dev] + * @author gchq77703 [] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import forge from "node-forge"; +import { cryptNotice } from "../lib/Crypt.mjs"; + +/** + * Generate RSA Key Pair operation + */ +class GenerateRSAKeyPair extends Operation { + + /** + * GenerateRSAKeyPair constructor + */ + constructor() { + super(); + + this.name = "生成RSA密钥对"; + this.module = "Ciphers"; + this.description = `生成给定长度的RSA密钥对。

${cryptNotice}`; + this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "RSA密钥长度", + type: "option", + value: [ + "1024", + "2048", + "4096" + ] + }, + { + name: "输出格式", + type: "option", + value: [ + "PEM", + "JSON", + "DER" + ] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const [keyLength, outputFormat] = args; + + return new Promise((resolve, reject) => { + forge.pki.rsa.generateKeyPair({ + bits: Number(keyLength), + workers: -1, + workerScript: "assets/forge/prime.worker.min.js" + }, (err, keypair) => { + if (err) return reject(err); + + let result; + + switch (outputFormat) { + case "PEM": + result = forge.pki.publicKeyToPem(keypair.publicKey) + "\n" + forge.pki.privateKeyToPem(keypair.privateKey); + break; + case "JSON": + result = JSON.stringify(keypair); + break; + case "DER": + result = forge.asn1.toDer(forge.pki.privateKeyToAsn1(keypair.privateKey)).getBytes(); + break; + } + + resolve(result); + }); + }); + } + +} + +export default GenerateRSAKeyPair; diff --git a/plugins/srktoolbox/src/core/operations/GenerateTOTP.mjs b/plugins/srktoolbox/src/core/operations/GenerateTOTP.mjs new file mode 100644 index 00000000..4c9a92b0 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GenerateTOTP.mjs @@ -0,0 +1,75 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import * as OTPAuth from "otpauth"; + +/** + * Generate TOTP operation + */ +class GenerateTOTP extends Operation { + /** + * + */ + constructor() { + super(); + this.name = "生成TOTP"; + this.module = "Default"; + this.description = "基于时间的一次性密码算法(英语:Time-based One-Time Password,简称:TOTP)是一种根据预共享的密钥与当前时间计算一次性密码的算法。它已被互联网工程任务组接纳为RFC 6238标准,成为主动开放认证(英语:Initiative For Open Authentication)(OATH)的基石,并被用于众多多重要素验证系统当中。TOTP是散列消息认证码(HMAC)当中的一个例子。它结合一个私钥与当前时间戳,使用一个密码散列函数来生成一次性密码。

在输入框输入secret,或者留空来生成一个随机值。T0和T1的单位是秒。"; + this.infoURL = "https://wikipedia.org/wiki/Time-based_One-time_Password_algorithm"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "名称", + "type": "string", + "value": "" + }, + { + "name": "动态码长度", + "type": "number", + "value": 6 + }, + { + "name": "纪元偏移(Epoch offset, T0)", + "type": "number", + "value": 0 + }, + { + "name": "计算时间间隔(T1)", + "type": "number", + "value": 30 + } + ]; + } + + /** + * + */ + run(input, args) { + const secretStr = new TextDecoder("utf-8").decode(input).trim(); + const secret = secretStr ? secretStr.toUpperCase().replace(/\s+/g, "") : ""; + + const totp = new OTPAuth.TOTP({ + issuer: "", + label: args[0], + algorithm: "SHA1", + digits: args[1], + period: args[3], + epoch: args[2] * 1000, // Convert seconds to milliseconds + secret: OTPAuth.Secret.fromBase32(secret) + }); + + const uri = totp.toString(); + const code = totp.generate(); + + return `URI: ${uri}\n\nPassword: ${code}`; + } +} + +export default GenerateTOTP; diff --git a/plugins/srktoolbox/src/core/operations/GenerateUUID.mjs b/plugins/srktoolbox/src/core/operations/GenerateUUID.mjs new file mode 100644 index 00000000..d6193f3a --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GenerateUUID.mjs @@ -0,0 +1,80 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import * as uuid from "uuid"; +import OperationError from "../errors/OperationError.mjs"; +/** + * Generate UUID operation + */ +class GenerateUUID extends Operation { + + /** + * GenerateUUID constructor + */ + constructor() { + super(); + + this.name = "生成UUID"; + this.module = "Crypto"; + this.description = + "Generates an RFC 9562 (formerly RFC 4122) compliant Universally Unique Identifier (UUID), " + + "also known as a Globally Unique Identifier (GUID).
" + + "
" + + "We currently support generating the following UUID versions:
" + + "
    " + + "
  • v1: Timestamp-based
  • " + + "
  • v3: Namespace w/ MD5
  • " + + "
  • v4: Random (default)
  • " + + "
  • v5: Namespace w/ SHA-1
  • " + + "
  • v6: Timestamp, reordered
  • " + + "
  • v7: Unix Epoch time-based
  • " + + "
" + + "UUIDs are generated using the
uuid package.
"; + this.infoURL = "https://wikipedia.org/wiki/Universally_unique_identifier"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Version", + hint: "UUID version", + type: "option", + value: ["v1", "v3", "v4", "v5", "v6", "v7"], + defaultIndex: 2, + }, + { + name: "Namespace", + hint: "UUID namespace (UUID; valid for v3 and v5)", + type: "string", + value: "1b671a64-40d5-491e-99b0-da01ff1f3341" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [version, namespace] = args; + const hasDesiredVersion = typeof uuid[version] === "function"; + if (!hasDesiredVersion) throw new OperationError("Invalid UUID version"); + + const requiresNamespace = ["v3", "v5"].includes(version); + if (!requiresNamespace) return uuid[version](); + + const hasValidNamespace = typeof namespace === "string" && uuid.validate(namespace); + if (!hasValidNamespace) throw new OperationError("Invalid UUID namespace"); + + return uuid[version](input, namespace); + } + +} + +export default GenerateUUID; diff --git a/plugins/srktoolbox/src/core/operations/GenericCodeBeautify.mjs b/plugins/srktoolbox/src/core/operations/GenericCodeBeautify.mjs new file mode 100644 index 00000000..81ef93ea --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GenericCodeBeautify.mjs @@ -0,0 +1,163 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Generic Code Beautify operation + */ +class GenericCodeBeautify extends Operation { + + /** + * GenericCodeBeautify constructor + */ + constructor() { + super(); + + this.name = "通用代码美化"; + this.module = "Code"; + this.description = "尝试美化C风格语言,例如C, C++, C#, Java, PHP, JavaScript等等。

此操作并不保证美化后的代码一定可用,只是为了提高混淆或丑化后的代码可读性。

无法正常美化的内容:
  • For循环格式化
  • Do-While循环格式化
  • Switch/Case缩进
  • 特定的位移运算符
"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const preservedTokens = []; + let code = input, + t = 0, + m; + + // Remove strings + const sstrings = /'([^'\\]|\\.)*'/g; + while ((m = sstrings.exec(code))) { + code = preserveToken(code, m, t++); + sstrings.lastIndex = m.index; + } + + const dstrings = /"([^"\\]|\\.)*"/g; + while ((m = dstrings.exec(code))) { + code = preserveToken(code, m, t++); + dstrings.lastIndex = m.index; + } + + // Remove comments + const scomments = /\/\/[^\n\r]*/g; + while ((m = scomments.exec(code))) { + code = preserveToken(code, m, t++); + scomments.lastIndex = m.index; + } + + const mcomments = /\/\*[\s\S]*?\*\//gm; + while ((m = mcomments.exec(code))) { + code = preserveToken(code, m, t++); + mcomments.lastIndex = m.index; + } + + const hcomments = /(^|\n)#[^\n\r#]+/g; + while ((m = hcomments.exec(code))) { + code = preserveToken(code, m, t++); + hcomments.lastIndex = m.index; + } + + // Remove regexes + const regexes = /\/.*?[^\\]\/[gim]{0,3}/gi; + while ((m = regexes.exec(code))) { + code = preserveToken(code, m, t++); + regexes.lastIndex = m.index; + } + + code = code + // Create newlines after ; + .replace(/;/g, ";\n") + // Create newlines after { and around } + .replace(/{/g, "{\n") + .replace(/}/g, "\n}\n") + // Remove carriage returns + .replace(/\r/g, "") + // Remove all indentation + .replace(/^\s+/g, "") + .replace(/\n\s+/g, "\n") + // Remove trailing spaces + .replace(/\s*$/g, "") + .replace(/\n{/g, "{"); + + // Indent + let i = 0, + level = 0, + indent; + while (i < code.length) { + switch (code[i]) { + case "{": + level++; + break; + case "\n": + if (i+1 >= code.length) break; + + if (code[i+1] === "}") level--; + indent = (level >= 0) ? Array(level*4+1).join(" ") : ""; + + code = code.substring(0, i+1) + indent + code.substring(i+1); + if (level > 0) i += level*4; + break; + } + i++; + } + + code = code + // Add strategic spaces + .replace(/\s*([!<>=+-/*]?)=\s*/g, " $1= ") + .replace(/\s*<([=]?)\s*/g, " <$1 ") + .replace(/\s*>([=]?)\s*/g, " >$1 ") + .replace(/([^+])\+([^+=])/g, "$1 + $2") + .replace(/([^-])-([^-=])/g, "$1 - $2") + .replace(/([^*])\*([^*=])/g, "$1 * $2") + .replace(/([^/])\/([^/=])/g, "$1 / $2") + .replace(/\s*,\s*/g, ", ") + .replace(/\s*{/g, " {") + .replace(/}\n/g, "}\n\n") + // Hacky horribleness + .replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)\s*\n([^{])/gim, "$1 ($2)\n $3") + .replace(/(if|for|while|with|elif|elseif)\s*\(([^\n]*)\)([^{])/gim, "$1 ($2) $3") + .replace(/else\s*\n([^{])/gim, "else\n $1") + .replace(/else\s+([^{])/gim, "else $1") + // Remove strategic spaces + .replace(/\s+;/g, ";") + .replace(/\{\s+\}/g, "{}") + .replace(/\[\s+\]/g, "[]") + .replace(/}\s*(else|catch|except|finally|elif|elseif|else if)/gi, "} $1"); + + // Replace preserved tokens + const ptokens = /###preservedToken(\d+)###/g; + while ((m = ptokens.exec(code))) { + const ti = parseInt(m[1], 10); + code = code.substring(0, m.index) + preservedTokens[ti] + code.substring(m.index + m[0].length); + ptokens.lastIndex = m.index; + } + + return code; + + /** + * Replaces a matched token with a placeholder value. + */ + function preserveToken(str, match, t) { + preservedTokens[t] = match[0]; + return str.substring(0, match.index) + + "###preservedToken" + t + "###" + + str.substring(match.index + match[0].length); + } + } + +} + +export default GenericCodeBeautify; diff --git a/plugins/srktoolbox/src/core/operations/GetAllCasings.mjs b/plugins/srktoolbox/src/core/operations/GetAllCasings.mjs new file mode 100644 index 00000000..ab1450e7 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GetAllCasings.mjs @@ -0,0 +1,55 @@ +/** + * @author n1073645 [n1073645@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Permutate String operation + */ +class GetAllCasings extends Operation { + + /** + * GetAllCasings constructor + */ + constructor() { + super(); + + this.name = "大小写穷举"; + this.module = "Default"; + this.description = "输出一个字符串所有的大小写形式。

警告:显而易见是指数递增,输入字符串过长后果自负。"; + this.infoURL = ""; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const length = input.length; + const max = 1 << length; + input = input.toLowerCase(); + let result = ""; + + for (let i = 0; i < max; i++) { + const temp = input.split(""); + for (let j = 0; j < length; j++) { + if (((i >> j) & 1) === 1) { + temp[j] = temp[j].toUpperCase(); + } + } + result += temp.join("") + "\n"; + } + return result.slice(0, -1); + } +} + +export default GetAllCasings; diff --git a/plugins/srktoolbox/src/core/operations/GetTime.mjs b/plugins/srktoolbox/src/core/operations/GetTime.mjs new file mode 100644 index 00000000..3ddb0995 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GetTime.mjs @@ -0,0 +1,65 @@ +/** + * @author n1073645 [n1073645@gmail.com] + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {UNITS} from "../lib/DateTime.mjs"; + +/** + * Get Time operation + */ +class GetTime extends Operation { + + /** + * GetTime constructor + */ + constructor() { + super(); + + this.name = "获取当前时间"; + this.module = "Default"; + this.description = "获取当前时间的UNIX时间戳 (从1970-01-01 00:00:00 UTC开始的秒数)。使用W3C High Resolution Time API。"; + this.infoURL = "https://wikipedia.org/wiki/Unix_time"; + this.inputType = "string"; + this.outputType = "number"; + this.args = [ + { + name: "粒度", + type: "option", + value: UNITS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {number} + */ + run(input, args) { + const nowMs = (performance.timeOrigin + performance.now()), + granularity = args[0]; + + switch (granularity) { + case "纳秒 (ns)": + return Math.round(nowMs * 1000 * 1000); + case "微秒 (μs)": + return Math.round(nowMs * 1000); + case "毫秒 (ms)": + return Math.round(nowMs); + case "秒 (s)": + return Math.round(nowMs / 1000); + default: + throw new OperationError("无效的单位: " + granularity); + } + } + +} + +export default GetTime; diff --git a/plugins/srktoolbox/src/core/operations/GroupIPAddresses.mjs b/plugins/srktoolbox/src/core/operations/GroupIPAddresses.mjs new file mode 100644 index 00000000..0b96852d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/GroupIPAddresses.mjs @@ -0,0 +1,139 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {IP_DELIM_OPTIONS} from "../lib/Delim.mjs"; +import {ipv6ToStr, genIpv6Mask, IPV4_REGEX, strToIpv6, ipv4ToStr, IPV6_REGEX, strToIpv4} from "../lib/IP.mjs"; + +/** + * Group IP addresses operation + */ +class GroupIPAddresses extends Operation { + + /** + * GroupIPAddresses constructor + */ + constructor() { + super(); + + this.name = "IP地址分组"; + this.module = "Default"; + this.description = "把IP地址分组汇总列出到对应的子网范围下。支持IPv4和IPv6。"; + this.infoURL = "https://wikipedia.org/wiki/Subnetwork"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": IP_DELIM_OPTIONS + }, + { + "name": "子网 (CIDR)", + "type": "number", + "value": 24 + }, + { + "name": "只显示子网", + "type": "boolean", + "value": false, + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0]), + cidr = args[1], + onlySubnets = args[2], + ipv4Mask = cidr < 32 ? ~(0xFFFFFFFF >>> cidr) : 0xFFFFFFFF, + ipv6Mask = genIpv6Mask(cidr), + ips = input.split(delim), + ipv4Networks = {}, + ipv6Networks = {}; + let match = null, + output = "", + ip = null, + network = null, + networkStr = "", + i; + + if (cidr < 0 || cidr > 127) { + throw new OperationError("CIDR必须小于32(IPv4)或者128(IPv6)"); + } + + // Parse all IPs and add to network dictionary + for (i = 0; i < ips.length; i++) { + if ((match = IPV4_REGEX.exec(ips[i]))) { + ip = strToIpv4(match[1]) >>> 0; + network = ip & ipv4Mask; + + if (network in ipv4Networks) { + ipv4Networks[network].push(ip); + } else { + ipv4Networks[network] = [ip]; + } + } else if ((match = IPV6_REGEX.exec(ips[i]))) { + ip = strToIpv6(match[1]); + network = []; + networkStr = ""; + + for (let j = 0; j < 8; j++) { + network.push(ip[j] & ipv6Mask[j]); + } + + networkStr = ipv6ToStr(network, true); + + if (networkStr in ipv6Networks) { + ipv6Networks[networkStr].push(ip); + } else { + ipv6Networks[networkStr] = [ip]; + } + } + } + + // Sort IPv4 network dictionaries and print + for (network in ipv4Networks) { + ipv4Networks[network] = ipv4Networks[network].sort(); + + output += ipv4ToStr(network) + "/" + cidr + "\n"; + + if (!onlySubnets) { + for (i = 0; i < ipv4Networks[network].length; i++) { + output += " " + ipv4ToStr(ipv4Networks[network][i]) + "\n"; + } + output += "\n"; + } + } + + // Sort IPv6 network dictionaries and print + for (networkStr in ipv6Networks) { + // ipv6Networks[networkStr] = ipv6Networks[networkStr].sort(); TODO + + output += networkStr + "/" + cidr + "\n"; + + if (!onlySubnets) { + for (i = 0; i < ipv6Networks[networkStr].length; i++) { + output += " " + ipv6ToStr(ipv6Networks[networkStr][i], true) + "\n"; + } + output += "\n"; + } + } + + return output; + } + +} + +export default GroupIPAddresses; diff --git a/plugins/srktoolbox/src/core/operations/Gunzip.mjs b/plugins/srktoolbox/src/core/operations/Gunzip.mjs new file mode 100644 index 00000000..1777ee61 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Gunzip.mjs @@ -0,0 +1,53 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import gunzip from "zlibjs/bin/gunzip.min.js"; + +const Zlib = gunzip.Zlib; + +/** + * Gunzip operation + */ +class Gunzip extends Operation { + + /** + * Gunzip constructor + */ + constructor() { + super(); + + this.name = "Gunzip"; + this.module = "Compression"; + this.description = "解压使用带有Gzip标头的deflate算法压缩的数据。"; + this.infoURL = "https://wikipedia.org/wiki/Gzip"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = []; + this.checks = [ + { + pattern: "^\\x1f\\x8b\\x08", + flags: "", + args: [] + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {File} + */ + run(input, args) { + const gzipObj = new Zlib.Gunzip(new Uint8Array(input)); + return new Uint8Array(gzipObj.decompress()).buffer; + } + +} + +export default Gunzip; diff --git a/plugins/srktoolbox/src/core/operations/Gzip.mjs b/plugins/srktoolbox/src/core/operations/Gzip.mjs new file mode 100644 index 00000000..a1121cbb --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Gzip.mjs @@ -0,0 +1,91 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {COMPRESSION_TYPE, ZLIB_COMPRESSION_TYPE_LOOKUP} from "../lib/Zlib.mjs"; +import gzip from "zlibjs/bin/gzip.min.js"; + +const Zlib = gzip.Zlib; + +/** + * Gzip operation + */ +class Gzip extends Operation { + + /** + * Gzip constructor + */ + constructor() { + super(); + + this.name = "Gzip"; + this.module = "Compression"; + this.description = "使用带有Gzip标头的deflate算法压缩数据。"; + this.infoURL = "https://wikipedia.org/wiki/Gzip"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + name: "压缩类型", + type: "option", + value: COMPRESSION_TYPE + }, + { + name: "文件名 (可选)", + type: "string", + value: "" + }, + { + name: "注释 (可选)", + type: "string", + value: "" + }, + { + name: "包括文件校验和", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const filename = args[1], + comment = args[2], + options = { + deflateOptions: { + compressionType: ZLIB_COMPRESSION_TYPE_LOOKUP[args[0]] + }, + flags: { + fhcrc: args[3] + } + }; + + if (filename.length) { + options.flags.fname = true; + options.filename = filename; + } + if (comment.length) { + options.flags.comment = true; + options.comment = comment; + } + const gzipObj = new Zlib.Gzip(new Uint8Array(input), options); + const compressed = new Uint8Array(gzipObj.compress()); + if (options.flags.comment && !(compressed[3] & 0x10)) { + compressed[3] |= 0x10; + } + return compressed.buffer; + } + +} + +export default Gzip; diff --git a/plugins/srktoolbox/src/core/operations/HAS160.mjs b/plugins/srktoolbox/src/core/operations/HAS160.mjs new file mode 100644 index 00000000..29499b3c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/HAS160.mjs @@ -0,0 +1,51 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * HAS-160 operation + */ +class HAS160 extends Operation { + + /** + * HAS-160 constructor + */ + constructor() { + super(); + + this.name = "HAS-160"; + this.module = "Crypto"; + this.description = "HAS-160是设计用于韩国KCDSA数据签名的哈希算法。它是SHA-1的变种,并进行了提高安全性的修改。此算法产生160位长度的输出。

HAS-160和SHA-1计算方法相同。首先把输入分割成512位长度的块,并补齐最后一块。摘要函数按顺序处理块并不断更新哈希值。

此算法默认进行80轮运算。"; + this.infoURL = "https://wikipedia.org/wiki/HAS-160"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "轮数", + type: "number", + value: 80, + min: 1, + max: 80 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return runHash("has160", input, {rounds: args[0]}); + } + +} + +export default HAS160; diff --git a/plugins/srktoolbox/src/core/operations/HASSHClientFingerprint.mjs b/plugins/srktoolbox/src/core/operations/HASSHClientFingerprint.mjs new file mode 100644 index 00000000..a3240b47 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/HASSHClientFingerprint.mjs @@ -0,0 +1,168 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * HASSH created by Salesforce + * Ben Reardon (@benreardon) + * Adel Karimi (@0x4d31) + * and the JA3 crew: + * John B. Althouse + * Jeff Atkinson + * Josh Atkins + * + * Algorithm released under the BSD-3-clause licence + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import Stream from "../lib/Stream.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * HASSH Client Fingerprint operation + */ +class HASSHClientFingerprint extends Operation { + + /** + * HASSHClientFingerprint constructor + */ + constructor() { + super(); + + this.name = "HASSH客户端指纹"; + this.module = "Crypto"; + this.description = "使用SSH的Client Key Exchange Init消息内容进行哈希生成HASSH指纹,用于辨识SSH客户端。

输入:由客户端发送至服务器端的应用层SSH_MSG_KEXINIT包十六进制流。"; + this.infoURL = "https://engineering.salesforce.com/open-sourcing-hassh-abed3ae5044c"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "输入格式", + type: "option", + value: ["十六进制", "Base64", "原始"] + }, + { + name: "输出格式", + type: "option", + value: ["哈希摘要", "HASSH算法字符串", "详细信息"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [inputFormat, outputFormat] = args; + + input = Utils.convertToByteArray(input, inputFormat); + const s = new Stream(new Uint8Array(input)); + + // Length + const length = s.readInt(4); + if (s.length !== length + 4) + throw new OperationError("错误的包长度。"); + + // Padding length + const paddingLength = s.readInt(1); + + // Message code + const messageCode = s.readInt(1); + if (messageCode !== 20) + throw new OperationError("不是Key Exchange Init。"); + + // Cookie + s.moveForwardsBy(16); + + // KEX Algorithms + const kexAlgosLength = s.readInt(4); + const kexAlgos = s.readString(kexAlgosLength); + + // Server Host Key Algorithms + const serverHostKeyAlgosLength = s.readInt(4); + s.moveForwardsBy(serverHostKeyAlgosLength); + + // Encryption Algorithms Client to Server + const encAlgosC2SLength = s.readInt(4); + const encAlgosC2S = s.readString(encAlgosC2SLength); + + // Encryption Algorithms Server to Client + const encAlgosS2CLength = s.readInt(4); + s.moveForwardsBy(encAlgosS2CLength); + + // MAC Algorithms Client to Server + const macAlgosC2SLength = s.readInt(4); + const macAlgosC2S = s.readString(macAlgosC2SLength); + + // MAC Algorithms Server to Client + const macAlgosS2CLength = s.readInt(4); + s.moveForwardsBy(macAlgosS2CLength); + + // Compression Algorithms Client to Server + const compAlgosC2SLength = s.readInt(4); + const compAlgosC2S = s.readString(compAlgosC2SLength); + + // Compression Algorithms Server to Client + const compAlgosS2CLength = s.readInt(4); + s.moveForwardsBy(compAlgosS2CLength); + + // Languages Client to Server + const langsC2SLength = s.readInt(4); + s.moveForwardsBy(langsC2SLength); + + // Languages Server to Client + const langsS2CLength = s.readInt(4); + s.moveForwardsBy(langsS2CLength); + + // First KEX packet follows + s.moveForwardsBy(1); + + // Reserved + s.moveForwardsBy(4); + + // Padding string + s.moveForwardsBy(paddingLength); + + // Output + const hassh = [ + kexAlgos, + encAlgosC2S, + macAlgosC2S, + compAlgosC2S + ]; + const hasshStr = hassh.join(";"); + const hasshHash = runHash("md5", Utils.strToArrayBuffer(hasshStr)); + + switch (outputFormat) { + case "HASSH算法字符串": + return hasshStr; + case "详细信息": + return `哈希摘要: +${hasshHash} + +完整HASSH算法字符串: +${hasshStr} + +密钥交换算法: +${kexAlgos} +客户端到服务器端加密算法: +${encAlgosC2S} +客户端到服务器端MAC算法: +${macAlgosC2S} +客户端到服务器端压缩算法: +${compAlgosC2S}`; + case "哈希摘要": + default: + return hasshHash; + } + } + +} + +export default HASSHClientFingerprint; diff --git a/plugins/srktoolbox/src/core/operations/HASSHServerFingerprint.mjs b/plugins/srktoolbox/src/core/operations/HASSHServerFingerprint.mjs new file mode 100644 index 00000000..9e4d3552 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/HASSHServerFingerprint.mjs @@ -0,0 +1,168 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * HASSH created by Salesforce + * Ben Reardon (@benreardon) + * Adel Karimi (@0x4d31) + * and the JA3 crew: + * John B. Althouse + * Jeff Atkinson + * Josh Atkins + * + * Algorithm released under the BSD-3-clause licence + * + * Modified by Raka-loah@github for zh-CN i18n +*/ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import Stream from "../lib/Stream.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * HASSH Server Fingerprint operation + */ +class HASSHServerFingerprint extends Operation { + + /** + * HASSHServerFingerprint constructor + */ + constructor() { + super(); + + this.name = "HASSH服务器指纹"; + this.module = "Crypto"; + this.description = "使用SSH的Server Key Exchange Init消息内容进行哈希生成HASSH指纹,用于辨识SSH服务器端。

输入:由服务器端发送至客户端的应用层SSH_MSG_KEXINIT包十六进制流。"; + this.infoURL = "https://engineering.salesforce.com/open-sourcing-hassh-abed3ae5044c"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "输入格式", + type: "option", + value: ["十六进制", "Base64", "原始"] + }, + { + name: "输出格式", + type: "option", + value: ["哈希摘要", "HASSH算法字符串", "详细信息"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [inputFormat, outputFormat] = args; + + input = Utils.convertToByteArray(input, inputFormat); + const s = new Stream(new Uint8Array(input)); + + // Length + const length = s.readInt(4); + if (s.length !== length + 4) + throw new OperationError("错误的包长度。"); + + // Padding length + const paddingLength = s.readInt(1); + + // Message code + const messageCode = s.readInt(1); + if (messageCode !== 20) + throw new OperationError("不是Key Exchange Init。"); + + // Cookie + s.moveForwardsBy(16); + + // KEX Algorithms + const kexAlgosLength = s.readInt(4); + const kexAlgos = s.readString(kexAlgosLength); + + // Server Host Key Algorithms + const serverHostKeyAlgosLength = s.readInt(4); + s.moveForwardsBy(serverHostKeyAlgosLength); + + // Encryption Algorithms Client to Server + const encAlgosC2SLength = s.readInt(4); + s.moveForwardsBy(encAlgosC2SLength); + + // Encryption Algorithms Server to Client + const encAlgosS2CLength = s.readInt(4); + const encAlgosS2C = s.readString(encAlgosS2CLength); + + // MAC Algorithms Client to Server + const macAlgosC2SLength = s.readInt(4); + s.moveForwardsBy(macAlgosC2SLength); + + // MAC Algorithms Server to Client + const macAlgosS2CLength = s.readInt(4); + const macAlgosS2C = s.readString(macAlgosS2CLength); + + // Compression Algorithms Client to Server + const compAlgosC2SLength = s.readInt(4); + s.moveForwardsBy(compAlgosC2SLength); + + // Compression Algorithms Server to Client + const compAlgosS2CLength = s.readInt(4); + const compAlgosS2C = s.readString(compAlgosS2CLength); + + // Languages Client to Server + const langsC2SLength = s.readInt(4); + s.moveForwardsBy(langsC2SLength); + + // Languages Server to Client + const langsS2CLength = s.readInt(4); + s.moveForwardsBy(langsS2CLength); + + // First KEX packet follows + s.moveForwardsBy(1); + + // Reserved + s.moveForwardsBy(4); + + // Padding string + s.moveForwardsBy(paddingLength); + + // Output + const hassh = [ + kexAlgos, + encAlgosS2C, + macAlgosS2C, + compAlgosS2C + ]; + const hasshStr = hassh.join(";"); + const hasshHash = runHash("md5", Utils.strToArrayBuffer(hasshStr)); + + switch (outputFormat) { + case "HASSH算法字符串": + return hasshStr; + case "详细信息": + return `哈希摘要: +${hasshHash} + +完整HASSH算法字符串: +${hasshStr} + +密钥交换算法: +${kexAlgos} +服务器端到客户端加密算法: +${encAlgosS2C} +服务器端到客户端MAC算法: +${macAlgosS2C} +服务器端到客户端压缩算法: +${compAlgosS2C}`; + case "哈希摘要": + default: + return hasshHash; + } + } + +} + +export default HASSHServerFingerprint; diff --git a/plugins/srktoolbox/src/core/operations/HMAC.mjs b/plugins/srktoolbox/src/core/operations/HMAC.mjs new file mode 100644 index 00000000..2b43049c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/HMAC.mjs @@ -0,0 +1,84 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import CryptoApi from "crypto-api/src/crypto-api.mjs"; + +/** + * HMAC operation + */ +class HMAC extends Operation { + + /** + * HMAC constructor + */ + constructor() { + super(); + + this.name = "HMAC"; + this.module = "Crypto"; + this.description = "HMAC (有时扩展为 英语:keyed-hash message authentication code, 密钥散列消息认证码, 或 英语:hash-based message authentication code,散列消息认证码),是一种通过特别计算方式之后产生的消息认证码(MAC),使用密码散列函数,同时结合一个加密密钥。它可以用来保证资料的完整性,同时可以用来作某个消息的身份验证。"; + this.infoURL = "https://wikipedia.org/wiki/HMAC"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "Key", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "十进制", "Base64", "UTF8", "Latin1"] + }, + { + "name": "哈希算法", + "type": "option", + "value": [ + "MD2", + "MD4", + "MD5", + "SHA0", + "SHA1", + "SHA224", + "SHA256", + "SHA384", + "SHA512", + "SHA512/224", + "SHA512/256", + "RIPEMD128", + "RIPEMD160", + "RIPEMD256", + "RIPEMD320", + "HAS160", + "Whirlpool", + "Whirlpool-0", + "Whirlpool-T", + "Snefru" + ] + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const key = Utils.convertToByteString(args[0].string || "", args[0].option), + hashFunc = args[1].toLowerCase(), + msg = Utils.arrayBufferToStr(input, false), + hasher = CryptoApi.getHasher(hashFunc); + + const mac = CryptoApi.getHmac(key, hasher); + mac.update(msg); + return CryptoApi.encoder.toHex(mac.finalize()); + } + +} + +export default HMAC; diff --git a/plugins/srktoolbox/src/core/operations/HTMLToText.mjs b/plugins/srktoolbox/src/core/operations/HTMLToText.mjs new file mode 100644 index 00000000..7becab4f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/HTMLToText.mjs @@ -0,0 +1,43 @@ +/** + * @author tlwr [toby@toby.codes] + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * HTML To Text operation + */ +class HTMLToText extends Operation { + + /** + * HTMLToText constructor + */ + constructor() { + super(); + + this.name = "HTML转文本"; + this.module = "Default"; + this.description = "将某个操作输出的HTML转换为纯文本形式,不在输出框进行渲染。"; + this.infoURL = ""; + this.inputType = "html"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {html} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return input; + } + +} + +export default HTMLToText; diff --git a/plugins/srktoolbox/src/core/operations/HTTPRequest.mjs b/plugins/srktoolbox/src/core/operations/HTTPRequest.mjs new file mode 100644 index 00000000..e3b9ac1e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/HTTPRequest.mjs @@ -0,0 +1,149 @@ +/** + * @author tlwr [toby@toby.codes] + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * HTTP request operation + */ +class HTTPRequest extends Operation { + + /** + * HTTPRequest constructor + */ + constructor() { + super(); + + this.name = "HTTP请求"; + this.module = "Default"; + this.description = [ + "发起HTTP请求并接收响应内容。", + "

", + "此操作支持不同的HTTP方法,例如GET、POST、PUT等等。", + "

", + "你可以用 Key: Value 的格式按行添加请求头(Header)。", + "

", + "响应的状态码和一部分响应头可通过勾选“显示响应元数据”查看。由于浏览器安全设置,只能显示一部分响应头。", + ].join("\n"); + this.infoURL = "https://wikipedia.org/wiki/List_of_HTTP_header_fields#Request_fields"; + this.inputType = "string"; + this.outputType = "string"; + this.manualBake = true; + this.args = [ + { + "name": "方法", + "type": "option", + "value": [ + "GET", "POST", "HEAD", + "PUT", "PATCH", "DELETE", + "CONNECT", "TRACE", "OPTIONS" + ] + }, + { + "name": "URL", + "type": "string", + "value": "" + }, + { + "name": "请求头(Header)", + "type": "text", + "value": "" + }, + { + "name": "模式", + "type": "option", + "value": [ + "Cross-Origin Resource Sharing", + "No CORS (limited to HEAD, GET or POST)", + ] + }, + { + "name": "显示响应元数据", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [method, url, headersText, mode, showResponseMetadata] = args; + + if (url.length === 0) return ""; + + const headers = new Headers(); + headersText.split(/\r?\n/).forEach(line => { + line = line.trim(); + + if (line.length === 0) return; + + const split = line.split(":"); + if (split.length !== 2) throw `无法解析请求头,位于行: ${line}`; + + headers.set(split[0].trim(), split[1].trim()); + }); + + const config = { + method: method, + headers: headers, + mode: modeLookup[mode], + cache: "no-cache", + }; + + if (method !== "GET" && method !== "HEAD") { + config.body = input; + } + + return fetch(url, config) + .then(r => { + if (r.status === 0 && r.type === "opaque") { + throw new OperationError("错误:响应为空。尝试把连接模式设置为CORS。"); + } + + if (showResponseMetadata) { + let headers = ""; + for (const pair of r.headers.entries()) { + headers += " " + pair[0] + ": " + pair[1] + "\n"; + } + return r.text().then(b => { + return "####\n 状态: " + r.status + " " + r.statusText + + "\n 响应头:\n" + headers + "####\n\n" + b; + }); + } + return r.text(); + }) + .catch(e => { + throw new OperationError(e.toString() + + "\n\n此错误可能由以下原因产生:\n" + + " - 无效的URL\n" + + " - 从安全来源(HTTPS)发起到不安全来源(HTTP)的请求。\n" + + " - 对不支持CORS的服务器发起了跨域请求。\n"); + }); + } + +} + + +/** + * Lookup table for HTTP modes + * + * @private + */ +const modeLookup = { + "Cross-Origin Resource Sharing": "cors", + "No CORS (limited to HEAD, GET or POST)": "no-cors", +}; + + +export default HTTPRequest; diff --git a/plugins/srktoolbox/src/core/operations/HammingDistance.mjs b/plugins/srktoolbox/src/core/operations/HammingDistance.mjs new file mode 100644 index 00000000..86c5ba38 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/HammingDistance.mjs @@ -0,0 +1,100 @@ +/** + * @author GCHQ Contributor [2] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {fromHex} from "../lib/Hex.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Hamming Distance operation + */ +class HammingDistance extends Operation { + + /** + * HammingDistance constructor + */ + constructor() { + super(); + + this.name = "汉明距离"; + this.module = "Default"; + this.description = "在信息论中,两个等长字符串之间的汉明距离(英语:Hamming distance)是两个字符串对应位置的不同字符的个数。换句话说,它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。"; + this.infoURL = "https://wikipedia.org/wiki/Hamming_distance"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "分隔符", + "type": "binaryShortString", + "value": "\\n\\n" + }, + { + "name": "单位", + "type": "option", + "value": ["字节", "位"] + }, + { + "name": "输入格式", + "type": "option", + "value": ["原始字符串", "十六进制"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = args[0], + byByte = args[1] === "字节", + inputType = args[2], + samples = input.split(delim); + + if (samples.length !== 2) { + throw new OperationError("错误:计算汉明距离需要两个字符串,请确保输入按照给定分隔符的两个字符串。"); + } + + if (samples[0].length !== samples[1].length) { + throw new OperationError("错误:两个字符串需要等长。"); + } + + if (inputType === "十六进制") { + samples[0] = fromHex(samples[0]); + samples[1] = fromHex(samples[1]); + } else { + samples[0] = new Uint8Array(Utils.strToArrayBuffer(samples[0])); + samples[1] = new Uint8Array(Utils.strToArrayBuffer(samples[1])); + } + + let dist = 0; + + for (let i = 0; i < samples[0].length; i++) { + const lhs = samples[0][i], + rhs = samples[1][i]; + + if (byByte && lhs !== rhs) { + dist++; + } else if (!byByte) { + let xord = lhs ^ rhs; + + while (xord) { + dist++; + xord &= xord - 1; + } + } + } + + return dist.toString(); + } + +} + +export default HammingDistance; diff --git a/plugins/srktoolbox/src/core/operations/HaversineDistance.mjs b/plugins/srktoolbox/src/core/operations/HaversineDistance.mjs new file mode 100644 index 00000000..3ecb1475 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/HaversineDistance.mjs @@ -0,0 +1,61 @@ +/** + * @author Dachande663 [dachande663@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * HaversineDistance operation + */ +class HaversineDistance extends Operation { + + /** + * HaversineDistance constructor + */ + constructor() { + super(); + + this.name = "半正矢距离"; + this.module = "Default"; + this.description = "计算两对GPS经纬度坐标之间的距离,单位米。

例如:51.487263,-0.124323, 38.9517,-77.1467"; + this.infoURL = "https://wikipedia.org/wiki/Haversine_formula"; + this.inputType = "string"; + this.outputType = "number"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {number} + */ + run(input, args) { + + const values = input.match(/^(-?\d+(\.\d+)?), ?(-?\d+(\.\d+)?), ?(-?\d+(\.\d+)?), ?(-?\d+(\.\d+)?)$/); + if (!values) { + throw new OperationError("输入格式必须是:纬度1, 经度1, 纬度2, 经度2"); + } + + const lat1 = parseFloat(values[1]); + const lng1 = parseFloat(values[3]); + const lat2 = parseFloat(values[5]); + const lng2 = parseFloat(values[7]); + + const TO_RAD = Math.PI / 180; + const dLat = (lat2-lat1) * TO_RAD; + const dLng = (lng2-lng1) * TO_RAD; + const a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(lat1 * TO_RAD) * Math.cos(lat2 * TO_RAD) * Math.sin(dLng/2) * Math.sin(dLng/2); + const metres = 6371000 * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); + + return metres; + + } + +} + +export default HaversineDistance; diff --git a/plugins/srktoolbox/src/core/operations/Head.mjs b/plugins/srktoolbox/src/core/operations/Head.mjs new file mode 100644 index 00000000..5bae32e6 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Head.mjs @@ -0,0 +1,70 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs"; + +/** + * Head operation + */ +class Head extends Operation { + + /** + * Head constructor + */ + constructor() { + super(); + + this.name = "Head"; + this.module = "Default"; + this.description = "和UNIX的head工具类似。
输出前n行。
输入负数可以选取除最后n行之外的内容。
可以选择不同的分隔符来实现选取前n个数据。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": INPUT_DELIM_OPTIONS + }, + { + "name": "选取数量", + "type": "number", + "value": 10 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let delimiter = args[0]; + const number = args[1]; + + delimiter = Utils.charRep(delimiter); + const splitInput = input.split(delimiter); + + return splitInput + .filter((line, lineIndex) => { + lineIndex += 1; + + if (number < 0) { + return lineIndex <= splitInput.length + number; + } else { + return lineIndex <= number; + } + }) + .join(delimiter); + } + +} + +export default Head; diff --git a/plugins/srktoolbox/src/core/operations/HeatmapChart.mjs b/plugins/srktoolbox/src/core/operations/HeatmapChart.mjs new file mode 100644 index 00000000..240962c0 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/HeatmapChart.mjs @@ -0,0 +1,268 @@ +/** + * @author tlwr [toby@toby.codes] + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import * as d3temp from "d3"; +import * as nodomtemp from "nodom"; +import { getScatterValues, RECORD_DELIMITER_OPTIONS, COLOURS, FIELD_DELIMITER_OPTIONS } from "../lib/Charts.mjs"; + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; + +const d3 = d3temp.default ? d3temp.default : d3temp; +const nodom = nodomtemp.default ? nodomtemp.default: nodomtemp; + +/** + * Heatmap chart operation + */ +class HeatmapChart extends Operation { + + /** + * HeatmapChart constructor + */ + constructor() { + super(); + + this.name = "热图"; + this.module = "Charts"; + this.description = "热图(英语:heat map)是在二维空间中以颜色的形式显示一个现象的绝对量一种数据可视化技术。"; + this.infoURL = "https://wikipedia.org/wiki/Heat_map"; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + name: "记录分隔符", + type: "option", + value: RECORD_DELIMITER_OPTIONS, + }, + { + name: "字段分隔符", + type: "option", + value: FIELD_DELIMITER_OPTIONS, + }, + { + name: "垂直色块数", + type: "number", + value: 25, + }, + { + name: "水平色块数", + type: "number", + value: 25, + }, + { + name: "使用表头作为标签", + type: "boolean", + value: true, + }, + { + name: "X轴标签", + type: "string", + value: "", + }, + { + name: "Y轴标签", + type: "string", + value: "", + }, + { + name: "绘制色块边缘", + type: "boolean", + value: false, + }, + { + name: "最小值色彩", + type: "string", + value: COLOURS.min, + }, + { + name: "最大值色彩", + type: "string", + value: COLOURS.max, + }, + ]; + } + + /** + * Heatmap chart operation. + * + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const recordDelimiter = Utils.charRep(args[0]), + fieldDelimiter = Utils.charRep(args[1]), + vBins = args[2], + hBins = args[3], + columnHeadingsAreIncluded = args[4], + drawEdges = args[7], + minColour = args[8], + maxColour = args[9], + dimension = 500; + if (vBins <= 0) throw new OperationError("水平色块数必须大于0"); + if (hBins <= 0) throw new OperationError("垂直色块数必须大于0"); + + let xLabel = args[5], + yLabel = args[6]; + const { headings, values } = getScatterValues( + input, + recordDelimiter, + fieldDelimiter, + columnHeadingsAreIncluded + ); + + if (headings) { + xLabel = headings.x; + yLabel = headings.y; + } + + const document = new nodom.Document(); + let svg = document.createElement("svg"); + svg = d3.select(svg) + .attr("width", "100%") + .attr("height", "100%") + .attr("viewBox", `0 0 ${dimension} ${dimension}`); + + const margin = { + top: 10, + right: 0, + bottom: 40, + left: 30, + }, + width = dimension - margin.left - margin.right, + height = dimension - margin.top - margin.bottom, + binWidth = width / hBins, + binHeight = height/ vBins, + marginedSpace = svg.append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + + const bins = this.getHeatmapPacking(values, vBins, hBins), + maxCount = Math.max(...bins.map(row => { + const lengths = row.map(cell => cell.length); + return Math.max(...lengths); + })); + + const xExtent = d3.extent(values, d => d[0]), + yExtent = d3.extent(values, d => d[1]); + + const xAxis = d3.scaleLinear() + .domain(xExtent) + .range([0, width]); + const yAxis = d3.scaleLinear() + .domain(yExtent) + .range([height, 0]); + + const colour = d3.scaleSequential(d3.interpolateLab(minColour, maxColour)) + .domain([0, maxCount]); + + marginedSpace.append("clipPath") + .attr("id", "clip") + .append("rect") + .attr("width", width) + .attr("height", height); + + marginedSpace.append("g") + .attr("class", "bins") + .attr("clip-path", "url(#clip)") + .selectAll("g") + .data(bins) + .enter() + .append("g") + .selectAll("rect") + .data(d => d) + .enter() + .append("rect") + .attr("x", (d) => binWidth * d.x) + .attr("y", (d) => (height - binHeight * (d.y + 1))) + .attr("width", binWidth) + .attr("height", binHeight) + .attr("fill", (d) => colour(d.length)) + .attr("stroke", drawEdges ? "rgba(0, 0, 0, 0.5)" : "none") + .attr("stroke-width", drawEdges ? "0.5" : "none") + .append("title") + .text(d => { + const count = d.length, + perc = 100.0 * d.length / values.length, + tooltip = `计数: ${count}\n + 占比: ${perc.toFixed(2)}%\n + `.replace(/\s{2,}/g, "\n"); + return tooltip; + }); + + marginedSpace.append("g") + .attr("class", "axis axis--y") + .call(d3.axisLeft(yAxis).tickSizeOuter(-width)); + + svg.append("text") + .attr("transform", "rotate(-90)") + .attr("y", -margin.left) + .attr("x", -(height / 2)) + .attr("dy", "1em") + .style("text-anchor", "middle") + .text(yLabel); + + marginedSpace.append("g") + .attr("class", "axis axis--x") + .attr("transform", "translate(0," + height + ")") + .call(d3.axisBottom(xAxis).tickSizeOuter(-height)); + + svg.append("text") + .attr("x", width / 2) + .attr("y", dimension) + .style("text-anchor", "middle") + .text(xLabel); + + return svg._groups[0][0].outerHTML; + } + + /** + * Packs a list of x, y coordinates into a number of bins for use in a heatmap. + * + * @param {Object[]} points + * @param {number} number of vertical bins + * @param {number} number of horizontal bins + * @returns {Object[]} a list of bins (each bin is an Array) with x y coordinates, filled with the points + */ + getHeatmapPacking(values, vBins, hBins) { + const xBounds = d3.extent(values, d => d[0]), + yBounds = d3.extent(values, d => d[1]), + bins = []; + + if (xBounds[0] === xBounds[1]) throw "无法对数据点分组。X坐标最大值和最小值之间没有差异。"; + if (yBounds[0] === yBounds[1]) throw "无法对数据点分组。Y坐标最大值和最小值之间没有差异。"; + + for (let y = 0; y < vBins; y++) { + bins.push([]); + for (let x = 0; x < hBins; x++) { + const item = []; + item.y = y; + item.x = x; + + bins[y].push(item); + } // x + } // y + + const epsilon = 0.000000001; // This is to clamp values that are exactly the maximum; + + values.forEach(v => { + const fractionOfY = (v[1] - yBounds[0]) / ((yBounds[1] + epsilon) - yBounds[0]), + fractionOfX = (v[0] - xBounds[0]) / ((xBounds[1] + epsilon) - xBounds[0]), + y = Math.floor(vBins * fractionOfY), + x = Math.floor(hBins * fractionOfX); + + bins[y][x].push({x: v[0], y: v[1]}); + }); + + return bins; + } + +} + +export default HeatmapChart; diff --git a/plugins/srktoolbox/src/core/operations/HexDensityChart.mjs b/plugins/srktoolbox/src/core/operations/HexDensityChart.mjs new file mode 100644 index 00000000..175a6e27 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/HexDensityChart.mjs @@ -0,0 +1,298 @@ +/** + * @author tlwr [toby@toby.codes] + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import * as d3temp from "d3"; +import * as d3hexbintemp from "d3-hexbin"; +import * as nodomtemp from "nodom"; +import { getScatterValues, RECORD_DELIMITER_OPTIONS, COLOURS, FIELD_DELIMITER_OPTIONS } from "../lib/Charts.mjs"; + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +const d3 = d3temp.default ? d3temp.default : d3temp; +const d3hexbin = d3hexbintemp.default ? d3hexbintemp.default : d3hexbintemp; +const nodom = nodomtemp.default ? nodomtemp.default: nodomtemp; + + +/** + * Hex Density chart operation + */ +class HexDensityChart extends Operation { + + /** + * HexDensityChart constructor + */ + constructor() { + super(); + + this.name = "六边形密度图"; + this.module = "Charts"; + this.description = "六边形密度图(Hex density chart)和散点图的使用方法类似,但与其显示上万散点,六边形密度图将相近位置的数据合并,用较少的六边形和色彩来展示密度。"; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + name: "记录分隔符", + type: "option", + value: RECORD_DELIMITER_OPTIONS, + }, + { + name: "字段分隔符", + type: "option", + value: FIELD_DELIMITER_OPTIONS, + }, + { + name: "分组半径", + type: "number", + value: 25, + }, + { + name: "绘制半径", + type: "number", + value: 15, + }, + { + name: "使用表头作为标签", + type: "boolean", + value: true, + }, + { + name: "X轴标签", + type: "string", + value: "", + }, + { + name: "Y轴标签", + type: "string", + value: "", + }, + { + name: "绘制六边形边缘", + type: "boolean", + value: false, + }, + { + name: "最小值色彩", + type: "string", + value: COLOURS.min, + }, + { + name: "最大值色彩", + type: "string", + value: COLOURS.max, + }, + { + name: "绘制数据范围内的空六边形", + type: "boolean", + value: false, + } + ]; + } + + + /** + * Hex Bin chart operation. + * + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const recordDelimiter = Utils.charRep(args[0]), + fieldDelimiter = Utils.charRep(args[1]), + packRadius = args[2], + drawRadius = args[3], + columnHeadingsAreIncluded = args[4], + drawEdges = args[7], + minColour = args[8], + maxColour = args[9], + drawEmptyHexagons = args[10], + dimension = 500; + + let xLabel = args[5], + yLabel = args[6]; + const { headings, values } = getScatterValues( + input, + recordDelimiter, + fieldDelimiter, + columnHeadingsAreIncluded + ); + + if (headings) { + xLabel = headings.x; + yLabel = headings.y; + } + + const document = new nodom.Document(); + let svg = document.createElement("svg"); + svg = d3.select(svg) + .attr("width", "100%") + .attr("height", "100%") + .attr("viewBox", `0 0 ${dimension} ${dimension}`); + + const margin = { + top: 10, + right: 0, + bottom: 40, + left: 30, + }, + width = dimension - margin.left - margin.right, + height = dimension - margin.top - margin.bottom, + marginedSpace = svg.append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + + const hexbin = d3hexbin.hexbin() + .radius(packRadius) + .extent([0, 0], [width, height]); + + const hexPoints = hexbin(values), + maxCount = Math.max(...hexPoints.map(b => b.length)); + + const xExtent = d3.extent(hexPoints, d => d.x), + yExtent = d3.extent(hexPoints, d => d.y); + xExtent[0] -= 2 * packRadius; + xExtent[1] += 3 * packRadius; + yExtent[0] -= 2 * packRadius; + yExtent[1] += 2 * packRadius; + + const xAxis = d3.scaleLinear() + .domain(xExtent) + .range([0, width]); + const yAxis = d3.scaleLinear() + .domain(yExtent) + .range([height, 0]); + + const colour = d3.scaleSequential(d3.interpolateLab(minColour, maxColour)) + .domain([0, maxCount]); + + marginedSpace.append("clipPath") + .attr("id", "clip") + .append("rect") + .attr("width", width) + .attr("height", height); + + if (drawEmptyHexagons) { + marginedSpace.append("g") + .attr("class", "empty-hexagon") + .selectAll("path") + .data(this.getEmptyHexagons(hexPoints, packRadius)) + .enter() + .append("path") + .attr("d", d => { + return `M${xAxis(d.x)},${yAxis(d.y)} ${hexbin.hexagon(drawRadius)}`; + }) + .attr("fill", (d) => colour(0)) + .attr("stroke", drawEdges ? "black" : "none") + .attr("stroke-width", drawEdges ? "0.5" : "none") + .append("title") + .text(d => { + const count = 0, + perc = 0, + tooltip = `计数: ${count}\n + 占比: ${perc.toFixed(2)}%\n + 中心: ${d.x.toFixed(2)}, ${d.y.toFixed(2)}\n + `.replace(/\s{2,}/g, "\n"); + return tooltip; + }); + } + + marginedSpace.append("g") + .attr("class", "hexagon") + .attr("clip-path", "url(#clip)") + .selectAll("path") + .data(hexPoints) + .enter() + .append("path") + .attr("d", d => { + return `M${xAxis(d.x)},${yAxis(d.y)} ${hexbin.hexagon(drawRadius)}`; + }) + .attr("fill", (d) => colour(d.length)) + .attr("stroke", drawEdges ? "black" : "none") + .attr("stroke-width", drawEdges ? "0.5" : "none") + .append("title") + .text(d => { + const count = d.length, + perc = 100.0 * d.length / values.length, + CX = d.x, + CY = d.y, + xMin = Math.min(...d.map(d => d[0])), + xMax = Math.max(...d.map(d => d[0])), + yMin = Math.min(...d.map(d => d[1])), + yMax = Math.max(...d.map(d => d[1])), + tooltip = `计数: ${count}\n + 占比: ${perc.toFixed(2)}%\n + 中心: ${CX.toFixed(2)}, ${CY.toFixed(2)}\n + X最小: ${xMin.toFixed(2)}\n + X最大: ${xMax.toFixed(2)}\n + Y最小: ${yMin.toFixed(2)}\n + Y最大: ${yMax.toFixed(2)} + `.replace(/\s{2,}/g, "\n"); + return tooltip; + }); + + marginedSpace.append("g") + .attr("class", "axis axis--y") + .call(d3.axisLeft(yAxis).tickSizeOuter(-width)); + + svg.append("text") + .attr("transform", "rotate(-90)") + .attr("y", -margin.left) + .attr("x", -(height / 2)) + .attr("dy", "1em") + .style("text-anchor", "middle") + .text(yLabel); + + marginedSpace.append("g") + .attr("class", "axis axis--x") + .attr("transform", "translate(0," + height + ")") + .call(d3.axisBottom(xAxis).tickSizeOuter(-height)); + + svg.append("text") + .attr("x", width / 2) + .attr("y", dimension) + .style("text-anchor", "middle") + .text(xLabel); + + return svg._groups[0][0].outerHTML; + } + + + /** + * Hex Bin chart operation. + * + * @param {Object[]} - centres + * @param {number} - radius + * @returns {Object[]} + */ + getEmptyHexagons(centres, radius) { + const emptyCentres = [], + boundingRect = [d3.extent(centres, d => d.x), d3.extent(centres, d => d.y)], + hexagonCenterToEdge = Math.cos(2 * Math.PI / 12) * radius, + hexagonEdgeLength = Math.sin(2 * Math.PI / 12) * radius; + let indent = false; + + for (let y = boundingRect[1][0]; y <= boundingRect[1][1] + radius; y += hexagonEdgeLength + radius) { + for (let x = boundingRect[0][0]; x <= boundingRect[0][1] + radius; x += 2 * hexagonCenterToEdge) { + let cx = x; + const cy = y; + + if (indent && x >= boundingRect[0][1]) break; + if (indent) cx += hexagonCenterToEdge; + + emptyCentres.push({x: cx, y: cy}); + } + indent = !indent; + } + + return emptyCentres; + } + +} + +export default HexDensityChart; diff --git a/plugins/srktoolbox/src/core/operations/HexToObjectIdentifier.mjs b/plugins/srktoolbox/src/core/operations/HexToObjectIdentifier.mjs new file mode 100644 index 00000000..4727369e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/HexToObjectIdentifier.mjs @@ -0,0 +1,43 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import r from "jsrsasign"; +import Operation from "../Operation.mjs"; + +/** + * Hex to Object Identifier operation + */ +class HexToObjectIdentifier extends Operation { + + /** + * HexToObjectIdentifier constructor + */ + constructor() { + super(); + + this.name = "十六进制转OID"; + this.module = "PublicKey"; + this.description = "把十六进制字符串转换成对应的对象标识符(object identifier,OID)。"; + this.infoURL = "https://wikipedia.org/wiki/Object_identifier"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return r.KJUR.asn1.ASN1Util.oidHexToInt(input.replace(/\s/g, "")); + } + +} + +export default HexToObjectIdentifier; diff --git a/plugins/srktoolbox/src/core/operations/HexToPEM.mjs b/plugins/srktoolbox/src/core/operations/HexToPEM.mjs new file mode 100644 index 00000000..258a230b --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/HexToPEM.mjs @@ -0,0 +1,49 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import r from "jsrsasign"; +import Operation from "../Operation.mjs"; + +/** + * Hex to PEM operation + */ +class HexToPEM extends Operation { + + /** + * HexToPEM constructor + */ + constructor() { + super(); + + this.name = "十六进制转PEM"; + this.module = "PublicKey"; + this.description = "把十六进制DER(Distinguished Encoding Rules)字符串转换成PEM(Privacy Enhanced Mail)格式。"; + this.infoURL = "https://wikipedia.org/wiki/Privacy-Enhanced_Mail"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Header字符串", + "type": "string", + "value": "CERTIFICATE" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return r.KJUR.asn1.ASN1Util.getPEMStringFromHex(input.replace(/\s/g, ""), args[0]); + } + +} + +export default HexToPEM; diff --git a/plugins/srktoolbox/src/core/operations/IPv6TransitionAddresses.mjs b/plugins/srktoolbox/src/core/operations/IPv6TransitionAddresses.mjs new file mode 100644 index 00000000..1a2fc0ed --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/IPv6TransitionAddresses.mjs @@ -0,0 +1,211 @@ +/** + * @author jb30795 [jb30795@proton.me] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * IPv6 Transition Addresses operation + */ +class IPv6TransitionAddresses extends Operation { + + /** + * IPv6TransitionAddresses constructor + */ + constructor() { + super(); + + this.name = "IPv6过渡地址"; + this.module = "Default"; + this.description = "将IPv4地址转换为其IPv6过渡地址,亦可反向将IPv6过渡地址还原为原始IPv4地址。同时支持将MAC地址转换为EUI-64格式,该格式可直接附加至您的IPv6 /64地址段,从而生成完整的/128地址。过渡技术通过实现IPv4与IPv6地址间的转换或建立隧道,使流量能在不兼容的网络间传输,从而实现两种标准的共存。当前仅支持处理/24地址范围。提供“移除标头”功能,便于直接复制输出结果。"; + this.infoURL = "https://wikipedia.org/wiki/IPv6_transition_mechanism"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "忽略地址范围", + "type": "boolean", + "value": true + }, + { + "name": "移除标头", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const XOR = {"0": "2", "1": "3", "2": "0", "3": "1", "4": "6", "5": "7", "6": "4", "7": "5", "8": "a", "9": "b", "a": "8", "b": "9", "c": "e", "d": "f", "e": "c", "f": "d"}; + + /** + * Function to convert to hex + */ + function hexify(octet) { + return Number(octet).toString(16).padStart(2, "0"); + } + + /** + * Function to convert Hex to Int + */ + function intify(hex) { + return parseInt(hex, 16); + } + + /** + * Function converts IPv4 to IPv6 Transtion address + */ + function ipTransition(input, range) { + let output = ""; + const HEXIP = input.split("."); + + /** + * 6to4 + */ + if (!args[1]) { + output += "6to4:"; + } + output += "2002:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]); + if (range) { + output += "00::/40\n"; + } else { + output += hexify(HEXIP[3]) + "::/48\n"; + } + + /** + * Mapped + */ + if (!args[1]) { + output += "IPv4映射:"; + } + output += "::ffff:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]); + if (range) { + output += "00/120\n"; + } else { + output += hexify(HEXIP[3]) + "\n"; + } + + /** + * Translated + */ + if (!args[1]) { + output += "IPv4转译:"; + } + output += "::ffff:0:" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]); + if (range) { + output += "00/120\n"; + } else { + output += hexify(HEXIP[3]) + "\n"; + } + + /** + * Nat64 + */ + if (!args[1]) { + output += "NAT64:"; + } + output += "64:ff9b::" + hexify(HEXIP[0]) + hexify(HEXIP[1]) + ":" + hexify(HEXIP[2]); + if (range) { + output += "00/120\n"; + } else { + output += hexify(HEXIP[3]) + "\n"; + } + + return output; + } + + /** + * Convert MAC to EUI-64 + */ + function macTransition(input) { + let output = ""; + const MACPARTS = input.split(":"); + if (!args[1]) { + output += "EUI-64接口标识符:"; + } + const MAC = MACPARTS[0] + MACPARTS[1] + ":" + MACPARTS[2] + "ff:fe" + MACPARTS[3] + ":" + MACPARTS[4] + MACPARTS[5]; + output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2)] + MAC.slice(2); + + return output; + } + + + /** + * Convert IPv6 address to its original IPv4 or MAC address + */ + function unTransition(input) { + let output = ""; + let hextets = ""; + + /** + * 6to4 + */ + if (input.startsWith("2002:")) { + if (!args[1]) { + output += "IPv4:"; + } + output += String(intify(input.slice(5, 7))) + "." + String(intify(input.slice(7, 9)))+ "." + String(intify(input.slice(10, 12)))+ "." + String(intify(input.slice(12, 14))) + "\n"; + } else if (input.startsWith("::ffff:") || input.startsWith("0000:0000:0000:0000:0000:ffff:") || input.startsWith("::ffff:0000:") || input.startsWith("0000:0000:0000:0000:ffff:0000:") || input.startsWith("64:ff9b::") || input.startsWith("0064:ff9b:0000:0000:0000:0000:")) { + /** + * Mapped/Translated/Nat64 + */ + hextets = /:([0-9a-z]{1,4}):[0-9a-z]{1,4}$/.exec(input)[1].padStart(4, "0") + /:([0-9a-z]{1,4})$/.exec(input)[1].padStart(4, "0"); + if (!args[1]) { + output += "IPv4:"; + } + output += intify(hextets.slice(-8, -7) + hextets.slice(-7, -6)) + "." +intify(hextets.slice(-6, -5) + hextets.slice(-5, -4)) + "." +intify(hextets.slice(-4, -3) + hextets.slice(-3, -2)) + "." +intify(hextets.slice(-2, -1) + hextets.slice(-1,)) + "\n"; + } else if (input.slice(-12, -7).toUpperCase() === "FF:FE") { + /** + * EUI-64 + */ + if (!args[1]) { + output += "MAC地址:"; + } + const MAC = (input.slice(-19, -17) + ":" + input.slice(-17, -15) + ":" + input.slice(-14, -12) + ":" + input.slice(-7, -5) + ":" + input.slice(-4, -2) + ":" + input.slice(-2,)).toUpperCase(); + output += MAC.slice(0, 1) + XOR[MAC.slice(1, 2)] + MAC.slice(2) + "\n"; + } + + return output; + } + + + /** + * Main + */ + let output = ""; + let inputs = input.split("\n"); + // Remove blank rows + inputs = inputs.filter(Boolean); + + for (let i = 0; i < inputs.length; i++) { + // if ignore ranges is checked and input is a range, skip + if ((args[0] && !inputs[i].includes("/")) || (!args[0])) { + if (/^[0-9]{1,3}(?:\.[0-9]{1,3}){3}$/.test(inputs[i])) { + output += ipTransition(inputs[i], false); + } else if (/\/24$/.test(inputs[i])) { + output += ipTransition(inputs[i], true); + } else if (/^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$/.test(inputs[i])) { + output += macTransition(inputs[i]); + } else if (/^((?:[0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?:(?::[0-9a-fA-F]{1,4}){1,6})|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(?::[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(?:ffff(?::0{1,4}){0,1}:){0,1}(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])|(?:[0-9a-fA-F]{1,4}:){1,4}:(?:(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/.test(inputs[i])) { + output += unTransition(inputs[i]); + } else { + output = "请输入压缩或原始格式的IPv6、IPv4或MAC地址。"; + } + } + } + + return output; + } + +} + +export default IPv6TransitionAddresses; diff --git a/plugins/srktoolbox/src/core/operations/ImageBrightnessContrast.mjs b/plugins/srktoolbox/src/core/operations/ImageBrightnessContrast.mjs new file mode 100644 index 00000000..d286c793 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ImageBrightnessContrast.mjs @@ -0,0 +1,112 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; +import { Jimp, JimpMime } from "jimp"; + +/** + * Image Brightness / Contrast operation + */ +class ImageBrightnessContrast extends Operation { + /** + * ImageBrightnessContrast constructor + */ + constructor() { + super(); + + this.name = "图像亮度/对比度"; + this.module = "Image"; + this.description = "调整图像的亮度或对比度。"; + this.infoURL = ""; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = [ + { + name: "亮度", + type: "number", + value: 0, + min: -100, + max: 100, + }, + { + name: "对比度", + type: "number", + value: 0, + min: -100, + max: 100, + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + async run(input, args) { + const [brightness, contrast] = args; + if (!isImage(input)) { + throw new OperationError("无效的文件类型。"); + } + + let image; + try { + image = await Jimp.read(input); + } catch (err) { + throw new OperationError(`图像加载出错:(${err})`); + } + try { + if (brightness !== 0) { + if (isWorkerEnvironment()) + self.sendStatusMessage("图像亮度调整……"); + image.brightness(brightness / 100); + } + if (contrast !== 0) { + if (isWorkerEnvironment()) + self.sendStatusMessage("图像对比度调整……"); + image.contrast(contrast / 100); + } + + let imageBuffer; + if (image.mime === "image/gif") { + imageBuffer = await image.getBuffer(JimpMime.png); + } else { + imageBuffer = await image.getBuffer(image.mime); + } + return imageBuffer.buffer; + } catch (err) { + throw new OperationError( + `调整图像亮度/对比度出错:(${err})`, + ); + } + } + + /** + * Displays the image using HTML for web apps + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const dataArray = new Uint8Array(data); + + const type = isImage(dataArray); + if (!type) { + throw new OperationError("无效的文件类型。"); + } + + return ``; + } +} + +export default ImageBrightnessContrast; diff --git a/plugins/srktoolbox/src/core/operations/ImageFilter.mjs b/plugins/srktoolbox/src/core/operations/ImageFilter.mjs new file mode 100644 index 00000000..5136fdd6 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ImageFilter.mjs @@ -0,0 +1,104 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; +import { Jimp, JimpMime } from "jimp"; + +/** + * Image Filter operation + */ +class ImageFilter extends Operation { + /** + * ImageFilter constructor + */ + constructor() { + super(); + + this.name = "图像滤镜"; + this.module = "Image"; + this.description = "为图像添加灰度或深褐(Sepia)滤镜。"; + this.infoURL = ""; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = [ + { + name: "滤镜类型", + type: "option", + value: ["灰度", "深褐(Sepia)"], + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + async run(input, args) { + const [filterType] = args; + if (!isImage(input)) { + throw new OperationError("无效的文件类型。"); + } + + let image; + try { + image = await Jimp.read(input); + } catch (err) { + throw new OperationError(`载入图像出错:(${err})`); + } + try { + if (isWorkerEnvironment()) + self.sendStatusMessage( + "应用 " + + filterType.toLowerCase() + + " 滤镜……", + ); + if (filterType === "灰度") { + image.greyscale(); + } else { + image.sepia(); + } + + let imageBuffer; + if (image.mime === "image/gif") { + imageBuffer = await image.getBuffer(JimpMime.png); + } else { + imageBuffer = await image.getBuffer(image.mime); + } + return imageBuffer.buffer; + } catch (err) { + throw new OperationError( + `应用滤镜出错:(${err})`, + ); + } + } + + /** + * Displays the blurred image using HTML for web apps + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const dataArray = new Uint8Array(data); + + const type = isImage(dataArray); + if (!type) { + throw new OperationError("无效的文件类型。"); + } + + return ``; + } +} + +export default ImageFilter; diff --git a/plugins/srktoolbox/src/core/operations/ImageHueSaturationLightness.mjs b/plugins/srktoolbox/src/core/operations/ImageHueSaturationLightness.mjs new file mode 100644 index 00000000..a3b73342 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ImageHueSaturationLightness.mjs @@ -0,0 +1,141 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; +import { Jimp, JimpMime } from "jimp"; + +/** + * Image Hue/Saturation/Lightness operation + */ +class ImageHueSaturationLightness extends Operation { + /** + * ImageHueSaturationLightness constructor + */ + constructor() { + super(); + + this.name = "图像色调/饱和度/明度"; + this.module = "Image"; + this.description = + "调整图像的色调/饱和度/明度值(HSL)。"; + this.infoURL = ""; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = [ + { + name: "色调", + type: "number", + value: 0, + min: -360, + max: 360, + }, + { + name: "饱和度", + type: "number", + value: 0, + min: -100, + max: 100, + }, + { + name: "明度", + type: "number", + value: 0, + min: -100, + max: 100, + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + async run(input, args) { + const [hue, saturation, lightness] = args; + + if (!isImage(input)) { + throw new OperationError("无效的文件类型。"); + } + + let image; + try { + image = await Jimp.read(input); + } catch (err) { + throw new OperationError(`载入图像出错:(${err})`); + } + try { + if (hue !== 0) { + if (isWorkerEnvironment()) + self.sendStatusMessage("调整图像色调……"); + image.color([ + { + apply: "hue", + params: [hue], + }, + ]); + } + if (saturation !== 0) { + if (isWorkerEnvironment()) + self.sendStatusMessage("调整图像饱和度……"); + image.color([ + { + apply: "saturate", + params: [saturation], + }, + ]); + } + if (lightness !== 0) { + if (isWorkerEnvironment()) + self.sendStatusMessage("调整图像明度……"); + image.color([ + { + apply: "lighten", + params: [lightness], + }, + ]); + } + + let imageBuffer; + if (image.mime === "image/gif") { + imageBuffer = await image.getBuffer(JimpMime.png); + } else { + imageBuffer = await image.getBuffer(image.mime); + } + return imageBuffer.buffer; + } catch (err) { + throw new OperationError( + `调整图像色调/饱和度/明度报错:(${err})`, + ); + } + } + + /** + * Displays the image using HTML for web apps + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const dataArray = new Uint8Array(data); + + const type = isImage(dataArray); + if (!type) { + throw new OperationError("无效的文件类型。"); + } + + return ``; + } +} + +export default ImageHueSaturationLightness; diff --git a/plugins/srktoolbox/src/core/operations/ImageOpacity.mjs b/plugins/srktoolbox/src/core/operations/ImageOpacity.mjs new file mode 100644 index 00000000..4f2716ab --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ImageOpacity.mjs @@ -0,0 +1,96 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; +import { Jimp, JimpMime } from "jimp"; + +/** + * Image Opacity operation + */ +class ImageOpacity extends Operation { + /** + * ImageOpacity constructor + */ + constructor() { + super(); + + this.name = "图像透明度"; + this.module = "Image"; + this.description = "调整图像透明度。"; + this.infoURL = ""; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = [ + { + name: "透明度 (%)", + type: "number", + value: 100, + min: 0, + max: 100, + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + async run(input, args) { + const [opacity] = args; + if (!isImage(input)) { + throw new OperationError("无效的文件类型。"); + } + + let image; + try { + image = await Jimp.read(input); + } catch (err) { + throw new OperationError(`载入图像出错:(${err})`); + } + try { + if (isWorkerEnvironment()) + self.sendStatusMessage("调整图像透明度……"); + image.opacity(opacity / 100); + + let imageBuffer; + if (image.mime === "image/gif") { + imageBuffer = await image.getBuffer(JimpMime.png); + } else { + imageBuffer = await image.getBuffer(image.mime); + } + return imageBuffer.buffer; + } catch (err) { + throw new OperationError(`调整图像透明度出错:(${err})`); + } + } + + /** + * Displays the image using HTML for web apps + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const dataArray = new Uint8Array(data); + + const type = isImage(dataArray); + if (!type) { + throw new OperationError("无效的文件类型。"); + } + + return ``; + } +} + +export default ImageOpacity; diff --git a/plugins/srktoolbox/src/core/operations/IndexOfCoincidence.mjs b/plugins/srktoolbox/src/core/operations/IndexOfCoincidence.mjs new file mode 100644 index 00000000..988b40bf --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/IndexOfCoincidence.mjs @@ -0,0 +1,109 @@ +/** + * @author George O [georgeomnet+cyberchef@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Index of Coincidence operation + */ +class IndexOfCoincidence extends Operation { + + /** + * IndexOfCoincidence constructor + */ + constructor() { + super(); + + this.name = "重合因子"; + this.module = "Default"; + this.description = "重合因子(Index of Coincidence, IC)指任意拿出两个字母,两个字母相同的概率。由于英语文本的IC通常大约为0.066,所以IC可以用来推测文本是否为可读文本。IC作为良好的判定条件被用来进行自动化文本频率分析。"; + this.infoURL = "https://wikipedia.org/wiki/Index_of_coincidence"; + this.inputType = "string"; + this.outputType = "number"; + this.presentType = "html"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {number} + */ + run(input, args) { + const text = input.toLowerCase().replace(/[^a-z]/g, ""), + frequencies = new Array(26).fill(0), + alphabet = Utils.expandAlphRange("a-z"); + let coincidence = 0.00, + density = 0.00, + result = 0.00, + i; + + for (i=0; i < alphabet.length; i++) { + frequencies[i] = text.count(alphabet[i]); + } + + for (i=0; i < frequencies.length; i++) { + coincidence += frequencies[i] * (frequencies[i] - 1); + } + + density = frequencies.sum(); + + // Ensure that we don't divide by 0 + if (density < 2) density = 2; + + result = coincidence / (density * (density - 1)); + + return result; + } + + /** + * Displays the IC as a scale bar for web apps. + * + * @param {number} ic + * @returns {html} + */ + present(ic) { + return `重合因子: ${ic} +标准化: ${ic * 26} +

+- 0表示完全随机(所有字符不重复),1代表完全不随机(所有字符相同)。 +- 英语文本的IC通常位于0.067至0.078。 +- 文本的随机度由每个字母和其它字母出现次数相同的概率决定。 + +以下图标显示输入数据的IC。较低的IC值通常表示文本是随机生成的,或被压缩/加密过。 + + + `; + } + +} + +export default IndexOfCoincidence; diff --git a/plugins/srktoolbox/src/core/operations/InvertImage.mjs b/plugins/srktoolbox/src/core/operations/InvertImage.mjs new file mode 100644 index 00000000..a6cffcbc --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/InvertImage.mjs @@ -0,0 +1,87 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; +import { Jimp, JimpMime } from "jimp"; + +/** + * Invert Image operation + */ +class InvertImage extends Operation { + /** + * InvertImage constructor + */ + constructor() { + super(); + + this.name = "图像反色"; + this.module = "Image"; + this.description = "对图像进行反色处理。"; + this.infoURL = ""; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + async run(input, args) { + if (!isImage(input)) { + throw new OperationError("无效的文件类型。"); + } + + let image; + try { + image = await Jimp.read(input); + } catch (err) { + throw new OperationError(`载入图片错误:(${err})`); + } + try { + if (isWorkerEnvironment()) + self.sendStatusMessage("图像反色……"); + image.invert(); + + let imageBuffer; + if (image.mime === "image/gif") { + imageBuffer = await image.getBuffer(JimpMime.png); + } else { + imageBuffer = await image.getBuffer(image.mime); + } + return imageBuffer.buffer; + } catch (err) { + throw new OperationError(`应用反色效果错误:(${err})`); + } + } + + /** + * Displays the inverted image using HTML for web apps + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const dataArray = new Uint8Array(data); + + const type = isImage(dataArray); + if (!type) { + throw new OperationError("无效的文件类型。"); + } + + return ``; + } +} + +export default InvertImage; diff --git a/plugins/srktoolbox/src/core/operations/JA3Fingerprint.mjs b/plugins/srktoolbox/src/core/operations/JA3Fingerprint.mjs new file mode 100644 index 00000000..ec0b47c1 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/JA3Fingerprint.mjs @@ -0,0 +1,207 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * JA3 created by Salesforce + * John B. Althouse + * Jeff Atkinson + * Josh Atkins + * + * Algorithm released under the BSD-3-clause licence + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import Stream from "../lib/Stream.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * JA3 Fingerprint operation + */ +class JA3Fingerprint extends Operation { + + /** + * JA3Fingerprint constructor + */ + constructor() { + super(); + + this.name = "JA3指纹"; + this.module = "Crypto"; + this.description = "使用客户端发起的Client Hello值进行哈希后生成JA3指纹,用于辨识TLS客户端。

输入:TLS Client Hello应用层数据包十六进制流。"; + this.infoURL = "https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "输入格式", + type: "option", + value: ["十六进制", "Base64", "原始"] + }, + { + name: "输出格式", + type: "option", + value: ["哈希摘要", "JA3字符串", "详细信息"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [inputFormat, outputFormat] = args; + + input = Utils.convertToByteArray(input, inputFormat); + const s = new Stream(new Uint8Array(input)); + + const handshake = s.readInt(1); + if (handshake !== 0x16) + throw new OperationError("没有握手数据。"); + + // Version + s.moveForwardsBy(2); + + // Length + const length = s.readInt(2); + if (s.length !== length + 5) + throw new OperationError("错误的握手长度。"); + + // Handshake type + const handshakeType = s.readInt(1); + if (handshakeType !== 1) + throw new OperationError("不是Client Hello。"); + + // Handshake length + const handshakeLength = s.readInt(3); + if (s.length !== handshakeLength + 9) + throw new OperationError("Client Hello包含的数据太少。"); + + // Hello version + const helloVersion = s.readInt(2); + + // Random + s.moveForwardsBy(32); + + // Session ID + const sessionIDLength = s.readInt(1); + s.moveForwardsBy(sessionIDLength); + + // Cipher suites + const cipherSuitesLength = s.readInt(2); + const cipherSuites = s.getBytes(cipherSuitesLength); + const cs = new Stream(cipherSuites); + const cipherSegment = parseJA3Segment(cs, 2); + + // Compression Methods + const compressionMethodsLength = s.readInt(1); + s.moveForwardsBy(compressionMethodsLength); + + // Extensions + const extensionsLength = s.readInt(2); + const extensions = s.getBytes(extensionsLength); + const es = new Stream(extensions); + let ecsLen, ecs, ellipticCurves = "", ellipticCurvePointFormats = ""; + const exts = []; + while (es.hasMore()) { + const type = es.readInt(2); + const length = es.readInt(2); + switch (type) { + case 0x0a: // Elliptic curves + ecsLen = es.readInt(2); + ecs = new Stream(es.getBytes(ecsLen)); + ellipticCurves = parseJA3Segment(ecs, 2); + break; + case 0x0b: // Elliptic curve point formats + ecsLen = es.readInt(1); + ecs = new Stream(es.getBytes(ecsLen)); + ellipticCurvePointFormats = parseJA3Segment(ecs, 1); + break; + default: + es.moveForwardsBy(length); + } + if (!GREASE_CIPHERSUITES.includes(type)) + exts.push(type); + } + + // Output + const ja3 = [ + helloVersion.toString(), + cipherSegment, + exts.join("-"), + ellipticCurves, + ellipticCurvePointFormats + ]; + const ja3Str = ja3.join(","); + const ja3Hash = runHash("md5", Utils.strToArrayBuffer(ja3Str)); + + switch (outputFormat) { + case "JA3字符串": + return ja3Str; + case "详细信息": + return `哈希摘要: +${ja3Hash} + +完整JA3字符串: +${ja3Str} + +TLS版本: +${helloVersion.toString()} +加密套件: +${cipherSegment} +扩展: +${exts.join("-")} +椭圆曲线: +${ellipticCurves} +椭圆曲线点格式: +${ellipticCurvePointFormats}`; + case "哈希摘要": + default: + return ja3Hash; + } + } + +} + +/** + * Parses a JA3 segment, returning a "-" separated list + * + * @param {Stream} stream + * @returns {string} + */ +function parseJA3Segment(stream, size=2) { + const segment = []; + while (stream.hasMore()) { + const element = stream.readInt(size); + if (!GREASE_CIPHERSUITES.includes(element)) + segment.push(element); + } + return segment.join("-"); +} + +const GREASE_CIPHERSUITES = [ + 0x0a0a, + 0x1a1a, + 0x2a2a, + 0x3a3a, + 0x4a4a, + 0x5a5a, + 0x6a6a, + 0x7a7a, + 0x8a8a, + 0x9a9a, + 0xaaaa, + 0xbaba, + 0xcaca, + 0xdada, + 0xeaea, + 0xfafa +]; + +export default JA3Fingerprint; diff --git a/plugins/srktoolbox/src/core/operations/JA3SFingerprint.mjs b/plugins/srktoolbox/src/core/operations/JA3SFingerprint.mjs new file mode 100644 index 00000000..f16b5cca --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/JA3SFingerprint.mjs @@ -0,0 +1,147 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * JA3S created by Salesforce + * John B. Althouse + * Jeff Atkinson + * Josh Atkins + * + * Algorithm released under the BSD-3-clause licence + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import Stream from "../lib/Stream.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * JA3S Fingerprint operation + */ +class JA3SFingerprint extends Operation { + + /** + * JA3SFingerprint constructor + */ + constructor() { + super(); + + this.name = "JA3S指纹"; + this.module = "Crypto"; + this.description = "使用服务器端发起的Server Hello值进行哈希后生成JA3S指纹,用于辨识TLS服务器端。

输入:TLS Server Hello应用层数据包十六进制流。"; + this.infoURL = "https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "输入格式", + type: "option", + value: ["十六进制", "Base64", "原始"] + }, + { + name: "输出格式", + type: "option", + value: ["哈希摘要", "JA3S字符串", "详细信息"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [inputFormat, outputFormat] = args; + + input = Utils.convertToByteArray(input, inputFormat); + const s = new Stream(new Uint8Array(input)); + + const handshake = s.readInt(1); + if (handshake !== 0x16) + throw new OperationError("没有握手数据。"); + + // Version + s.moveForwardsBy(2); + + // Length + const length = s.readInt(2); + if (s.length !== length + 5) + throw new OperationError("错误的握手长度。"); + + // Handshake type + const handshakeType = s.readInt(1); + if (handshakeType !== 2) + throw new OperationError("不是Server Hello。"); + + // Handshake length + const handshakeLength = s.readInt(3); + if (s.length !== handshakeLength + 9) + throw new OperationError("Server Hello包含的数据太少。"); + + // Hello version + const helloVersion = s.readInt(2); + + // Random + s.moveForwardsBy(32); + + // Session ID + const sessionIDLength = s.readInt(1); + s.moveForwardsBy(sessionIDLength); + + // Cipher suite + const cipherSuite = s.readInt(2); + + // Compression Method + s.moveForwardsBy(1); + + // Extensions + const extensionsLength = s.readInt(2); + const extensions = s.getBytes(extensionsLength); + const es = new Stream(extensions); + const exts = []; + while (es.hasMore()) { + const type = es.readInt(2); + const length = es.readInt(2); + es.moveForwardsBy(length); + exts.push(type); + } + + // Output + const ja3s = [ + helloVersion.toString(), + cipherSuite, + exts.join("-") + ]; + const ja3sStr = ja3s.join(","); + const ja3sHash = runHash("md5", Utils.strToArrayBuffer(ja3sStr)); + + switch (outputFormat) { + case "JA3S字符串": + return ja3sStr; + case "详细信息": + return `哈希摘要: +${ja3sHash} + +完整JA3S字符串: +${ja3sStr} + +TLS版本: +${helloVersion.toString()} +加密套件: +${cipherSuite} +扩展: +${exts.join("-")}`; + case "哈希摘要": + default: + return ja3sHash; + } + } + +} + +export default JA3SFingerprint; diff --git a/plugins/srktoolbox/src/core/operations/JA4Fingerprint.mjs b/plugins/srktoolbox/src/core/operations/JA4Fingerprint.mjs new file mode 100644 index 00000000..05219ea3 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/JA4Fingerprint.mjs @@ -0,0 +1,75 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {toJA4} from "../lib/JA4.mjs"; + +/** + * JA4 Fingerprint operation + */ +class JA4Fingerprint extends Operation { + + /** + * JA4Fingerprint constructor + */ + constructor() { + super(); + + this.name = "JA4指纹"; + this.module = "Crypto"; + this.description = "通过将Client Hello中的值进行哈希,生成用于辨识TLS客户端的JA4指纹。

输入:TLS或QUIC客户端应用层Client Hello包的十六进制流。"; + this.infoURL = "https://medium.com/foxio/ja4-network-fingerprinting-9376fe9ca637"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "输入格式", + type: "option", + value: ["十六进制", "Base64", "原始"] + }, + { + name: "输出格式", + type: "option", + value: ["JA4", "JA4 Original Rendering", "JA4 Raw", "JA4 Raw Original Rendering", "所有"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [inputFormat, outputFormat] = args; + input = Utils.convertToByteArray(input, inputFormat); + const ja4 = toJA4(new Uint8Array(input)); + + // Output + switch (outputFormat) { + case "JA4": + return ja4.JA4; + case "JA4 Original Rendering": + return ja4.JA4_o; + case "JA4 Raw": + return ja4.JA4_r; + case "JA4 Raw Original Rendering": + return ja4.JA4_ro; + case "所有": + default: + return `JA4: ${ja4.JA4} +JA4_o: ${ja4.JA4_o} +JA4_r: ${ja4.JA4_r} +JA4_ro: ${ja4.JA4_ro}`; + } + } + +} + +export default JA4Fingerprint; diff --git a/plugins/srktoolbox/src/core/operations/JA4ServerFingerprint.mjs b/plugins/srktoolbox/src/core/operations/JA4ServerFingerprint.mjs new file mode 100644 index 00000000..4196176e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/JA4ServerFingerprint.mjs @@ -0,0 +1,68 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {toJA4S} from "../lib/JA4.mjs"; + +/** + * JA4Server Fingerprint operation + */ +class JA4ServerFingerprint extends Operation { + + /** + * JA4ServerFingerprint constructor + */ + constructor() { + super(); + + this.name = "JA4S指纹"; + this.module = "Crypto"; + this.description = "生成用于辨识TLS服务器或会话的JA4服务器指纹(JA4S),通过将Server Hello中的值合并后进行哈希计算得出。

输入:TLS或QUIC Server Hello数据包十六进制流。"; + this.infoURL = "https://medium.com/foxio/ja4-network-fingerprinting-9376fe9ca637"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "输入格式", + type: "option", + value: ["十六进制", "Base64", "原始"] + }, + { + name: "输出格式", + type: "option", + value: ["JA4S", "JA4S原始", "全部"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [inputFormat, outputFormat] = args; + input = Utils.convertToByteArray(input, inputFormat); + const ja4s = toJA4S(new Uint8Array(input)); + + // Output + switch (outputFormat) { + case "JA4S": + return ja4s.JA4S; + case "JA4S原始": + return ja4s.JA4S_r; + case "全部": + default: + return `JA4S: ${ja4s.JA4S}\nJA4S_r: ${ja4s.JA4S_r}`; + } + } + +} + +export default JA4ServerFingerprint; diff --git a/plugins/srktoolbox/src/core/operations/JPathExpression.mjs b/plugins/srktoolbox/src/core/operations/JPathExpression.mjs new file mode 100644 index 00000000..5765f762 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/JPathExpression.mjs @@ -0,0 +1,73 @@ +/** + * @author Matt C (matt@artemisbot.uk) + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import {JSONPath} from "jsonpath-plus"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * JPath expression operation + */ +class JPathExpression extends Operation { + + /** + * JPathExpression constructor + */ + constructor() { + super(); + + this.name = "JPath表达式"; + this.module = "Code"; + this.description = "从JSON object中使用给定的JPath表达式进行查询并提取内容。"; + this.infoURL = "http://goessner.net/articles/JsonPath/"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "JPath", + type: "string", + value: "" + }, + { + name: "查询结果分隔符", + type: "binaryShortString", + value: "\\n" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [query, delimiter] = args; + let results, jsonObj; + + try { + jsonObj = JSON.parse(input); + } catch (err) { + throw new OperationError(`无效的JSON: ${err.message}`); + } + + try { + results = JSONPath({ + path: query, + json: jsonObj + }); + } catch (err) { + throw new OperationError(`无效的JPath表达式: ${err.message}`); + } + + return results.map(result => JSON.stringify(result)).join(delimiter); + } + +} + +export default JPathExpression; diff --git a/plugins/srktoolbox/src/core/operations/JSONBeautify.mjs b/plugins/srktoolbox/src/core/operations/JSONBeautify.mjs new file mode 100644 index 00000000..357274c3 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/JSONBeautify.mjs @@ -0,0 +1,246 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @author Phillip Nordwall [phillip.nordwall@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import JSON5 from "json5"; +import OperationError from "../errors/OperationError.mjs"; +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * JSON Beautify operation + */ +class JSONBeautify extends Operation { + + /** + * JSONBeautify constructor + */ + constructor() { + super(); + + this.name = "JSON美化"; + this.module = "Code"; + this.description = "为JavaScript Object Notation (JSON)代码添加缩进与美化。

标签: json viewer, prettify, syntax highlighting"; + this.inputType = "string"; + this.outputType = "string"; + this.presentType = "html"; + this.args = [ + { + name: "缩进", + type: "binaryShortString", + value: " " + }, + { + name: "按键值排序", + type: "boolean", + value: false + }, + { + name: "格式化", + type: "boolean", + value: true + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (!input) return ""; + + const [indentStr, sortBool] = args; + let json = null; + + try { + json = JSON5.parse(input); + } catch (err) { + throw new OperationError("无法解析JSON。\n" + err); + } + + if (sortBool) json = sortKeys(json); + + return JSON.stringify(json, null, indentStr); + } + + /** + * Adds various dynamic features to the JSON blob + * + * @param {string} data + * @param {Object[]} args + * @returns {html} + */ + present(data, args) { + const formatted = args[2]; + if (!formatted) return Utils.escapeHtml(data); + + const json = JSON5.parse(data); + const options = { + withLinks: true, + bigNumbers: true + }; + let html = '
'; + + if (isCollapsable(json)) { + const isArr = json instanceof Array; + html += '
' + + `` + + json2html(json, options) + + "
"; + } else { + html += json2html(json, options); + } + + html += "
"; + return html; + } +} + +/** + * Sort keys in a JSON object + * + * @author Phillip Nordwall [phillip.nordwall@gmail.com] + * @param {object} o + * @returns {object} + */ +function sortKeys(o) { + if (Array.isArray(o)) { + return o.map(sortKeys); + } else if ("[object Object]" === Object.prototype.toString.call(o)) { + return Object.keys(o).sort().reduce(function(a, k) { + a[k] = sortKeys(o[k]); + return a; + }, {}); + } + return o; +} + + +/** + * Check if arg is either an array with at least 1 element, or a dict with at least 1 key + * @returns {boolean} + */ +function isCollapsable(arg) { + return arg instanceof Object && Object.keys(arg).length > 0; +} + +/** + * Check if a string looks like a URL, based on protocol + * @returns {boolean} + */ +function isUrl(string) { + const protocols = ["http", "https", "ftp", "ftps"]; + for (let i = 0; i < protocols.length; i++) { + if (string.startsWith(protocols[i] + "://")) { + return true; + } + } + return false; +} + +/** + * Transform a json object into html representation + * + * Adapted for CyberChef by @n1474335 from jQuery json-viewer + * @author Alexandre Bodelot + * @link https://github.com/abodelot/jquery.json-viewer + * @license MIT + * + * @returns {string} + */ +function json2html(json, options) { + let html = ""; + if (typeof json === "string") { + // Escape tags and quotes + json = Utils.escapeHtml(json); + + if (options.withLinks && isUrl(json)) { + html += `
${json}`; + } else { + // Escape double quotes in the rendered non-URL string. + json = json.replace(/"/g, "\\""); + html += `"${json}"`; + } + } else if (typeof json === "number" || typeof json === "bigint") { + html += `${json}`; + } else if (typeof json === "boolean") { + html += `${json}`; + } else if (json === null) { + html += 'null'; + } else if (json instanceof Array) { + if (json.length > 0) { + html += '[
    '; + for (let i = 0; i < json.length; i++) { + html += "
  1. "; + + // Add toggle button if item is collapsable + if (isCollapsable(json[i])) { + const isArr = json[i] instanceof Array; + html += '
    ' + + `` + + json2html(json[i], options) + + "
    "; + } else { + html += json2html(json[i], options); + } + + // Add comma if item is not last + if (i < json.length - 1) { + html += ','; + } + html += "
  2. "; + } + html += '
]'; + } else { + html += '[]'; + } + } else if (typeof json === "object") { + // Optional support different libraries for big numbers + // json.isLosslessNumber: package lossless-json + // json.toExponential(): packages bignumber.js, big.js, decimal.js, decimal.js-light, others? + if (options.bigNumbers && (typeof json.toExponential === "function" || json.isLosslessNumber)) { + html += `${json.toString()}`; + } else { + let keyCount = Object.keys(json).length; + if (keyCount > 0) { + html += '{
    '; + for (const key in json) { + if (Object.prototype.hasOwnProperty.call(json, key)) { + const safeKey = Utils.escapeHtml(key); + html += "
  • "; + + // Add toggle button if item is collapsable + if (isCollapsable(json[key])) { + const isArr = json[key] instanceof Array; + html += '
    ' + + `${safeKey}: ` + + json2html(json[key], options) + + "
    "; + } else { + html += safeKey + ': ' + json2html(json[key], options); + } + + // Add comma if item is not last + if (--keyCount > 0) { + html += ','; + } + html += "
  • "; + } + } + html += '
}'; + } else { + html += '{}'; + } + } + } + return html; +} + +export default JSONBeautify; diff --git a/plugins/srktoolbox/src/core/operations/JSONMinify.mjs b/plugins/srktoolbox/src/core/operations/JSONMinify.mjs new file mode 100644 index 00000000..23dc2acc --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/JSONMinify.mjs @@ -0,0 +1,43 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import vkbeautify from "vkbeautify"; +import Operation from "../Operation.mjs"; + +/** + * JSON Minify operation + */ +class JSONMinify extends Operation { + + /** + * JSONMinify constructor + */ + constructor() { + super(); + + this.name = "JSON压缩"; + this.module = "Code"; + this.description = "压缩JavaScript Object Notation (JSON)代码(Minify/Uglify)。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (!input) return ""; + return vkbeautify.jsonmin(input); + } + +} + +export default JSONMinify; diff --git a/plugins/srktoolbox/src/core/operations/JSONToCSV.mjs b/plugins/srktoolbox/src/core/operations/JSONToCSV.mjs new file mode 100644 index 00000000..54a5d3fd --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/JSONToCSV.mjs @@ -0,0 +1,144 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import * as flat from "flat"; +const flatten = flat.default ? flat.default.flatten : flat.flatten; + +/** + * JSON to CSV operation + */ +class JSONToCSV extends Operation { + + /** + * JSONToCSV constructor + */ + constructor() { + super(); + + this.name = "JSON转CSV"; + this.module = "Default"; + this.description = "把JSON转换为CSV格式(RFC 4180)。"; + this.infoURL = "https://wikipedia.org/wiki/Comma-separated_values"; + this.inputType = "JSON"; + this.outputType = "string"; + this.args = [ + { + name: "单元格分隔符", + type: "binaryShortString", + value: "," + }, + { + name: "行分隔符", + type: "binaryShortString", + value: "\\r\\n" + } + ]; + } + + /** + * Converts JSON to a CSV equivalent. + * + * @param {boolean} force - Whether to force conversion of data to fit in a cell + * @returns {string} + */ + toCSV(force=false) { + const self = this; + // If the JSON is an array of arrays, this is easy + if (this.flattened[0] instanceof Array) { + return this.flattened + .map(row => row + .map(d => self.escapeCellContents(d, force)) + .join(this.cellDelim) + ) + .join(this.rowDelim) + + this.rowDelim; + } + + // If it's an array of dictionaries... + const header = Object.keys(this.flattened[0]); + return header + .map(d => self.escapeCellContents(d, force)) + .join(this.cellDelim) + + this.rowDelim + + this.flattened + .map(row => header + .map(h => row[h]) + .map(d => self.escapeCellContents(d, force)) + .join(this.cellDelim) + ) + .join(this.rowDelim) + + this.rowDelim; + } + + /** + * @param {JSON} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [cellDelim, rowDelim] = args; + + // Record values so they don't have to be passed to other functions explicitly + this.cellDelim = cellDelim; + this.rowDelim = rowDelim; + this.flattened = input; + if (!(this.flattened instanceof Array)) { + this.flattened = [input]; + } + + try { + return this.toCSV(); + } catch (err) { + try { + this.flattened = flatten(input); + if (!(this.flattened instanceof Array)) { + this.flattened = [this.flattened]; + } + return this.toCSV(true); + } catch (err) { + throw new OperationError("无法转换JSON到CSV:" + err.toString()); + } + } + } + + /** + * Correctly escapes a cell's contents based on the cell and row delimiters. + * + * @param {string} data + * @param {boolean} force - Whether to force conversion of data to fit in a cell + * @returns {string} + */ + escapeCellContents(data, force=false) { + if (data !== "string") { + const isPrimitive = data == null || typeof data !== "object"; + if (isPrimitive) data = `${data}`; + else if (force) data = JSON.stringify(data); + } + + // Double quotes should be doubled up + data = data.replace(/"/g, '""'); + + // If the cell contains a cell or row delimiter or a double quote, it must be enclosed in double quotes + if ( + data.indexOf(this.cellDelim) >= 0 || + data.indexOf(this.rowDelim) >= 0 || + data.indexOf("\n") >= 0 || + data.indexOf("\r") >= 0 || + data.indexOf('"') >= 0 + ) { + data = `"${data}"`; + } + + return data; + } + +} + +export default JSONToCSV; diff --git a/plugins/srktoolbox/src/core/operations/JSONtoYAML.mjs b/plugins/srktoolbox/src/core/operations/JSONtoYAML.mjs new file mode 100644 index 00000000..e573a3a8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/JSONtoYAML.mjs @@ -0,0 +1,48 @@ +/** + * @author ccarpo [ccarpo@gmx.net] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import YAML from "yaml"; + +/** + * JSON to YAML operation + */ +class JSONtoYAML extends Operation { + + /** + * JSONtoYAML constructor + */ + constructor() { + super(); + + this.name = "JSON转YAML"; + this.module = "Default"; + this.description = "将JSON对象转换为YAML"; + this.infoURL = "https://en.wikipedia.org/wiki/YAML"; + this.inputType = "JSON"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {JSON} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + try { + return YAML.stringify(input); + } catch (err) { + throw new OperationError("转换失败"); + } + } + +} + +export default JSONtoYAML; diff --git a/plugins/srktoolbox/src/core/operations/JWKToPem.mjs b/plugins/srktoolbox/src/core/operations/JWKToPem.mjs new file mode 100644 index 00000000..ec971a74 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/JWKToPem.mjs @@ -0,0 +1,82 @@ +/** + * @author cplussharp + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import r from "jsrsasign"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * PEM to JWK operation + */ +class PEMToJWK extends Operation { + + /** + * PEMToJWK constructor + */ + constructor() { + super(); + + this.name = "JWK转PEM"; + this.module = "PublicKey"; + this.description = "将JSON Web Key格式转换为PEM格式(PKCS#8)。"; + this.infoURL = "https://datatracker.ietf.org/doc/html/rfc7517"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + this.checks = [ + { + "pattern": "\"kty\":\\s*\"(EC|RSA)\"", + "flags": "gm", + "args": [] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const inputJson = JSON.parse(input); + + let keys = []; + if (Array.isArray(inputJson)) { + // list of keys => transform all keys + keys = inputJson; + } else if (Array.isArray(inputJson.keys)) { + // JSON Web Key Set => transform all keys + keys = inputJson.keys; + } else if (typeof inputJson === "object") { + // single key + keys.push(inputJson); + } else { + throw new OperationError("输入内容不是有效的JSON Web Key"); + } + + let output = ""; + for (let i=0; i" + e.message); + } + return result; + } + +} + +export default JavaScriptBeautify; diff --git a/plugins/srktoolbox/src/core/operations/JavaScriptMinify.mjs b/plugins/srktoolbox/src/core/operations/JavaScriptMinify.mjs new file mode 100644 index 00000000..161026b6 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/JavaScriptMinify.mjs @@ -0,0 +1,47 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import OperationError from "../errors/OperationError.mjs"; +import Operation from "../Operation.mjs"; +import * as terser from "terser"; + +/** + * JavaScript Minify operation + */ +class JavaScriptMinify extends Operation { + + /** + * JavaScriptMinify constructor + */ + constructor() { + super(); + + this.name = "JavaScript压缩"; + this.module = "Code"; + this.description = "压缩JavaScript代码(Minify/Uglify)。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const result = await terser.minify(input); + if (result.error) { + throw new OperationError(`压缩JavaScript时出错。 (${result.error})`); + } + return result.code; + } + +} + +export default JavaScriptMinify; diff --git a/plugins/srktoolbox/src/core/operations/JavaScriptParser.mjs b/plugins/srktoolbox/src/core/operations/JavaScriptParser.mjs new file mode 100644 index 00000000..141170ca --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/JavaScriptParser.mjs @@ -0,0 +1,80 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import * as esprima from "esprima"; + +/** + * JavaScript Parser operation + */ +class JavaScriptParser extends Operation { + + /** + * JavaScriptParser constructor + */ + constructor() { + super(); + + this.name = "JavaScript解析"; + this.module = "Code"; + this.description = "返回合法Javascript代码的抽象语法树(Abstract Syntax Tree, AST)。"; + this.infoURL = "https://wikipedia.org/wiki/Abstract_syntax_tree"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "位置信息", + "type": "boolean", + "value": false + }, + { + "name": "范围信息", + "type": "boolean", + "value": false + }, + { + "name": "包括token数组", + "type": "boolean", + "value": false + }, + { + "name": "包括注释数组", + "type": "boolean", + "value": false + }, + { + "name": "报告错误并尝试继续", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [parseLoc, parseRange, parseTokens, parseComment, parseTolerant] = args, + options = { + loc: parseLoc, + range: parseRange, + tokens: parseTokens, + comment: parseComment, + tolerant: parseTolerant + }; + let result = {}; + + result = esprima.parseScript(input, options); + return JSON.stringify(result, null, 2); + } + +} + +export default JavaScriptParser; diff --git a/plugins/srktoolbox/src/core/operations/Jq.mjs b/plugins/srktoolbox/src/core/operations/Jq.mjs new file mode 100644 index 00000000..1bca07af --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Jq.mjs @@ -0,0 +1,59 @@ +/** + * @author zhzy0077 [zhzy0077@hotmail.com] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import jq from "jq-web"; + +/** + * jq operation + */ +class Jq extends Operation { + + /** + * Jq constructor + */ + constructor() { + super(); + + this.name = "Jq"; + this.module = "Jq"; + this.description = "jq是一款轻量且灵活的命令行JSON处理工具。"; + this.infoURL = "https://github.com/jqlang/jq"; + this.inputType = "JSON"; + this.outputType = "string"; + this.args = [ + { + name: "查询", + type: "string", + value: "" + } + ]; + } + + /** + * @param {JSON} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [query] = args; + let result; + + try { + result = jq.json(input, query); + } catch (err) { + throw new OperationError(`无效的jq表达式:${err.message}`); + } + + return JSON.stringify(result); + } + +} + +export default Jq; diff --git a/plugins/srktoolbox/src/core/operations/Jsonata.mjs b/plugins/srktoolbox/src/core/operations/Jsonata.mjs new file mode 100644 index 00000000..4ab0fe9c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Jsonata.mjs @@ -0,0 +1,67 @@ +/** + * @author Jon K (jon@ajarsoftware.com) + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import jsonata from "jsonata"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Jsonata Query operation + */ +class JsonataQuery extends Operation { + /** + * JsonataQuery constructor + */ + constructor() { + super(); + + this.name = "Jsonata查询"; + this.module = "Code"; + this.description = + "使用Jsonata表达式查询与转换JSON数据。"; + this.infoURL = "https://docs.jsonata.org/overview.html"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "查询", + type: "text", + value: "string", + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const [query] = args; + let result, jsonObj; + + try { + jsonObj = JSON.parse(input); + } catch (err) { + throw new OperationError(`输入的JSON无效:${err.message}`); + } + + try { + const expression = jsonata(query); + result = await expression.evaluate(jsonObj); + } catch (err) { + throw new OperationError( + `无效的Jsonata表达式:${err.message}` + ); + } + + return JSON.stringify(result === undefined ? "" : result); + } +} + +export default JsonataQuery; diff --git a/plugins/srktoolbox/src/core/operations/Jump.mjs b/plugins/srktoolbox/src/core/operations/Jump.mjs new file mode 100644 index 00000000..7ed3ec57 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Jump.mjs @@ -0,0 +1,68 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { getLabelIndex } from "../lib/FlowControl.mjs"; + +/** + * Jump operation + */ +class Jump extends Operation { + + /** + * Jump constructor + */ + constructor() { + super(); + + this.name = "Jump"; + this.flowControl = true; + this.module = "Default"; + this.description = "跳转到特定的Label位置。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Label名称", + "type": "string", + "value": "" + }, + { + "name": "最大跳转次数(用于向后跳转)", + "type": "number", + "value": 10 + } + ]; + } + + /** + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on. + * @param {Operation[]} state.opList - The list of operations in the recipe. + * @param {number} state.numJumps - The number of jumps taken so far. + * @returns {Object} The updated state of the recipe. + */ + run(state) { + const ings = state.opList[state.progress].ingValues; + const [label, maxJumps] = ings; + const jmpIndex = getLabelIndex(label, state); + + if (state.numJumps >= maxJumps || jmpIndex === -1) { + state.numJumps = 0; + return state; + } + + state.progress = jmpIndex; + state.numJumps++; + return state; + } + +} + +export default Jump; diff --git a/plugins/srktoolbox/src/core/operations/Keccak.mjs b/plugins/srktoolbox/src/core/operations/Keccak.mjs new file mode 100644 index 00000000..860cab53 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Keccak.mjs @@ -0,0 +1,70 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import JSSHA3 from "js-sha3"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Keccak operation + */ +class Keccak extends Operation { + + /** + * Keccak constructor + */ + constructor() { + super(); + + this.name = "Keccak"; + this.module = "Crypto"; + this.description = "Keccak是一个加密散列算法,由 Guido Bertoni,Joan Daemen,Michaël Peeters,以及Gilles Van Assche在RadioGatún上设计。2012年10月2日,Keccak被选为NIST散列函数竞赛的胜利者。

此版本算法为Keccak[c=2d],和SHA-3略有不同。"; + this.infoURL = "https://wikipedia.org/wiki/SHA-3"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "长度", + "type": "option", + "value": ["512", "384", "256", "224"] + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const size = parseInt(args[0], 10); + let algo; + + switch (size) { + case 224: + algo = JSSHA3.keccak224; + break; + case 384: + algo = JSSHA3.keccak384; + break; + case 256: + algo = JSSHA3.keccak256; + break; + case 512: + algo = JSSHA3.keccak512; + break; + default: + throw new OperationError("无效长度"); + } + + return algo(input); + } + +} + +export default Keccak; diff --git a/plugins/srktoolbox/src/core/operations/LMHash.mjs b/plugins/srktoolbox/src/core/operations/LMHash.mjs new file mode 100644 index 00000000..cd215993 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/LMHash.mjs @@ -0,0 +1,43 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {smbhash} from "ntlm"; + +/** + * LM Hash operation + */ +class LMHash extends Operation { + + /** + * LMHash constructor + */ + constructor() { + super(); + + this.name = "LM哈希"; + this.module = "Crypto"; + this.description = "LM哈希,又叫LAN Manager哈希,是较旧的微软操作系统使用的存储密码方式,目前已被废弃。其安全性非常弱,使用现代硬件设备并利用彩虹表能在几秒之内完成破解。"; + this.infoURL = "https://wikipedia.org/wiki/LAN_Manager#Password_hashing_algorithm"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return smbhash.lmhash(input); + } + +} + +export default LMHash; diff --git a/plugins/srktoolbox/src/core/operations/LS47Decrypt.mjs b/plugins/srktoolbox/src/core/operations/LS47Decrypt.mjs new file mode 100644 index 00000000..25949ab3 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/LS47Decrypt.mjs @@ -0,0 +1,59 @@ +/** + * @author n1073645 [n1073645@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import * as LS47 from "../lib/LS47.mjs"; + +/** + * LS47 Decrypt operation + */ +class LS47Decrypt extends Operation { + + /** + * LS47Decrypt constructor + */ + constructor() { + super(); + + this.name = "LS47解密"; + this.module = "Crypto"; + this.description = "LS47是对Alan Kaminsky的ElsieFour加密进行少量优化后的版本。为了编码更为详尽的信息,把原版的6x6网格(几乎不够用)扩充到了7x7。同时提供了一种简单的key扩充算法,因为没人喜欢记密码。和ElsieFour有着类似的安全性考虑。
LS47字母表包括以下字符: _abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()
LS47 key是字母表49个字符的排列,同时用于加解密。"; + this.infoURL = "https://github.com/exaexa/ls47"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "密码", + type: "string", + value: "" + }, + { + name: "填充", + type: "number", + value: 10 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + this.paddingSize = parseInt(args[1], 10); + + LS47.initTiles(); + + const key = LS47.deriveKey(args[0]); + return LS47.decryptPad(key, input, this.paddingSize); + } + +} + +export default LS47Decrypt; diff --git a/plugins/srktoolbox/src/core/operations/LS47Encrypt.mjs b/plugins/srktoolbox/src/core/operations/LS47Encrypt.mjs new file mode 100644 index 00000000..3d79dd06 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/LS47Encrypt.mjs @@ -0,0 +1,64 @@ +/** + * @author n1073645 [n1073645@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import * as LS47 from "../lib/LS47.mjs"; + +/** + * LS47 Encrypt operation + */ +class LS47Encrypt extends Operation { + + /** + * LS47Encrypt constructor + */ + constructor() { + super(); + + this.name = "LS47加密"; + this.module = "Crypto"; + this.description = "LS47是对Alan Kaminsky的ElsieFour加密进行少量优化后的版本。为了编码更为详尽的信息,把原版的6x6网格(几乎不够用)扩充到了7x7。同时提供了一种简单的key扩充算法,因为没人喜欢记密码。和ElsieFour有着类似的安全性考虑。
LS47字母表包括以下字符: _abcdefghijklmnopqrstuvwxyz.0123456789,-+*/:?!'()
LS47 key是字母表49个字符的排列,同时用于加解密。"; + this.infoURL = "https://github.com/exaexa/ls47"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "密码", + type: "string", + value: "" + }, + { + name: "填充", + type: "number", + value: 10 + }, + { + name: "签名", + type: "string", + value: "" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + this.paddingSize = parseInt(args[1], 10); + + LS47.initTiles(); + + const key = LS47.deriveKey(args[0]); + return LS47.encryptPad(key, input, args[2], this.paddingSize); + } + +} + +export default LS47Encrypt; diff --git a/plugins/srktoolbox/src/core/operations/LZ4Compress.mjs b/plugins/srktoolbox/src/core/operations/LZ4Compress.mjs new file mode 100644 index 00000000..eb53bfcf --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/LZ4Compress.mjs @@ -0,0 +1,45 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import lz4 from "lz4js"; + +/** + * LZ4 Compress operation + */ +class LZ4Compress extends Operation { + + /** + * LZ4Compress constructor + */ + constructor() { + super(); + + this.name = "LZ4压缩"; + this.module = "Compression"; + this.description = "LZ4是一种无损数据压缩算法,着重于压缩和解压缩速度。它属于面向字节的LZ77压缩方案家族。"; + this.infoURL = "https://wikipedia.org/wiki/LZ4_(compression_algorithm)"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const inBuf = new Uint8Array(input); + const compressed = lz4.compress(inBuf); + return compressed.buffer; + } + +} + +export default LZ4Compress; diff --git a/plugins/srktoolbox/src/core/operations/LZ4Decompress.mjs b/plugins/srktoolbox/src/core/operations/LZ4Decompress.mjs new file mode 100644 index 00000000..95598fb9 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/LZ4Decompress.mjs @@ -0,0 +1,45 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import lz4 from "lz4js"; + +/** + * LZ4 Decompress operation + */ +class LZ4Decompress extends Operation { + + /** + * LZ4Decompress constructor + */ + constructor() { + super(); + + this.name = "LZ4解压"; + this.module = "Compression"; + this.description = "LZ4是一种无损数据压缩算法,着重于压缩和解压缩速度。它属于面向字节的LZ77压缩方案家族。"; + this.infoURL = "https://wikipedia.org/wiki/LZ4_(compression_algorithm)"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const inBuf = new Uint8Array(input); + const decompressed = lz4.decompress(inBuf); + return decompressed.buffer; + } + +} + +export default LZ4Decompress; diff --git a/plugins/srktoolbox/src/core/operations/LZMACompress.mjs b/plugins/srktoolbox/src/core/operations/LZMACompress.mjs new file mode 100644 index 00000000..2c5a7eb4 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/LZMACompress.mjs @@ -0,0 +1,66 @@ +/** + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +import { compress } from "@blu3r4y/lzma"; +import {isWorkerEnvironment} from "../Utils.mjs"; + +/** + * LZMA Compress operation + */ +class LZMACompress extends Operation { + + /** + * LZMACompress constructor + */ + constructor() { + super(); + + this.name = "LZMA压缩"; + this.module = "Compression"; + this.description = "使用Lempel\u2013Ziv\u2013Markov chain算法压缩数据。压缩模式指定压缩的速度与效率:1为最快但压缩率最低,9最慢但压缩率最高。"; + this.infoURL = "https://wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Markov_chain_algorithm"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + name: "压缩模式", + type: "option", + value: [ + "1", "2", "3", "4", "5", "6", "7", "8", "9" + ], + "defaultIndex": 6 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + async run(input, args) { + const mode = Number(args[0]); + return new Promise((resolve, reject) => { + compress(new Uint8Array(input), mode, (result, error) => { + if (error) { + reject(new OperationError(`压缩失败: ${error.message}`)); + } + // The compression returns as an Int8Array, but we can just get the unsigned data from the buffer + resolve(new Int8Array(result).buffer); + }, (percent) => { + if (isWorkerEnvironment()) self.sendStatusMessage(`压缩输入数据: ${(percent*100).toFixed(2)}%`); + }); + }); + } + +} + +export default LZMACompress; diff --git a/plugins/srktoolbox/src/core/operations/LZMADecompress.mjs b/plugins/srktoolbox/src/core/operations/LZMADecompress.mjs new file mode 100644 index 00000000..5cfc0ab6 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/LZMADecompress.mjs @@ -0,0 +1,59 @@ +/** + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {decompress} from "@blu3r4y/lzma"; +import Utils, {isWorkerEnvironment} from "../Utils.mjs"; + +/** + * LZMA Decompress operation + */ +class LZMADecompress extends Operation { + + /** + * LZMADecompress constructor + */ + constructor() { + super(); + + this.name = "LZMA解压"; + this.module = "Compression"; + this.description = "解压使用LZMA算法压缩的数据。"; + this.infoURL = "https://wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Markov_chain_algorithm"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + async run(input, args) { + return new Promise((resolve, reject) => { + decompress(new Uint8Array(input), (result, error) => { + if (error) { + reject(new OperationError(`解压失败: ${error.message}`)); + } + // The decompression returns either a String or an untyped unsigned int8 array, but we can just get the unsigned data from the buffer + + if (typeof result == "string") { + resolve(Utils.strToArrayBuffer(result)); + } else { + resolve(new Int8Array(result).buffer); + } + }, (percent) => { + if (isWorkerEnvironment()) self.sendStatusMessage(`解压: ${(percent*100).toFixed(2)}%`); + }); + }); + } + +} + +export default LZMADecompress; diff --git a/plugins/srktoolbox/src/core/operations/LZNT1Decompress.mjs b/plugins/srktoolbox/src/core/operations/LZNT1Decompress.mjs new file mode 100644 index 00000000..c7273b93 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/LZNT1Decompress.mjs @@ -0,0 +1,43 @@ +/** + * @author 0xThiebaut [thiebaut.dev] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {decompress} from "../lib/LZNT1.mjs"; + +/** + * LZNT1 Decompress operation + */ +class LZNT1Decompress extends Operation { + + /** + * LZNT1 Decompress constructor + */ + constructor() { + super(); + + this.name = "LZNT1解压"; + this.module = "Compression"; + this.description = "使用LZNT1算法解压数据。

功能和Windows API RtlDecompressBuffer类似。"; + this.infoURL = "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-xca/5655f4a3-6ba4-489b-959f-e1f407c52f15"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = []; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + return decompress(input); + } + +} + +export default LZNT1Decompress; diff --git a/plugins/srktoolbox/src/core/operations/LZStringCompress.mjs b/plugins/srktoolbox/src/core/operations/LZStringCompress.mjs new file mode 100644 index 00000000..7ef8e646 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/LZStringCompress.mjs @@ -0,0 +1,57 @@ +/** + * @author crespyl [peter@crespyl.net] + * @copyright Peter Jacobs 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +import {COMPRESSION_OUTPUT_FORMATS, COMPRESSION_FUNCTIONS} from "../lib/LZString.mjs"; + +/** + * LZString Compress operation + */ +class LZStringCompress extends Operation { + + /** + * LZStringCompress constructor + */ + constructor() { + super(); + + this.name = "LZString压缩"; + this.module = "Compression"; + this.description = "使用 lz-string 算法压缩输入内容。"; + this.infoURL = "https://pieroxy.net/blog/pages/lz-string/index.html"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "压缩格式", + type: "option", + defaultIndex: 0, + value: COMPRESSION_OUTPUT_FORMATS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const compress = COMPRESSION_FUNCTIONS[args[0]]; + if (compress) { + return compress(input); + } else { + throw new OperationError("压缩功能不可用"); + } + } + +} + +export default LZStringCompress; diff --git a/plugins/srktoolbox/src/core/operations/LZStringDecompress.mjs b/plugins/srktoolbox/src/core/operations/LZStringDecompress.mjs new file mode 100644 index 00000000..8b5159b1 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/LZStringDecompress.mjs @@ -0,0 +1,58 @@ +/** + * @author crespyl [peter@crespyl.net] + * @copyright Peter Jacobs 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +import {COMPRESSION_OUTPUT_FORMATS, DECOMPRESSION_FUNCTIONS} from "../lib/LZString.mjs"; + +/** + * LZString Decompress operation + */ +class LZStringDecompress extends Operation { + + /** + * LZStringDecompress constructor + */ + constructor() { + super(); + + this.name = "LZString解压"; + this.module = "Compression"; + this.description = "解压使用 lz-string 算法压缩的数据。"; + this.infoURL = "https://pieroxy.net/blog/pages/lz-string/index.html"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "压缩格式", + type: "option", + defaultIndex: 0, + value: COMPRESSION_OUTPUT_FORMATS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const decompress = DECOMPRESSION_FUNCTIONS[args[0]]; + if (decompress) { + return decompress(input); + } else { + throw new OperationError("压缩功能不可用"); + } + } + + +} + +export default LZStringDecompress; diff --git a/plugins/srktoolbox/src/core/operations/Label.mjs b/plugins/srktoolbox/src/core/operations/Label.mjs new file mode 100644 index 00000000..3e5721af --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Label.mjs @@ -0,0 +1,50 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Label operation. For use with Jump and Conditional Jump. + */ +class Label extends Operation { + + /** + * Label constructor + */ + constructor() { + super(); + + this.name = "Label"; + this.flowControl = true; + this.module = "Default"; + this.description = "给Conditional和Fixed Jump(跳转操作)提供一个跳转位置。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "名称", + "type": "shortString", + "value": "" + } + ]; + } + + /** + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on. + * @param {Operation[]} state.opList - The list of operations in the recipe. + * @returns {Object} The updated state of the recipe. + */ + run(state) { + return state; + } + +} + +export default Label; diff --git a/plugins/srktoolbox/src/core/operations/LevenshteinDistance.mjs b/plugins/srktoolbox/src/core/operations/LevenshteinDistance.mjs new file mode 100644 index 00000000..3b45c86e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/LevenshteinDistance.mjs @@ -0,0 +1,100 @@ +/** + * @author mikecat + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Levenshtein Distance operation + */ +class LevenshteinDistance extends Operation { + + /** + * LevenshteinDistance constructor + */ + constructor() { + super(); + + this.name = "莱文斯坦距离"; + this.module = "Default"; + this.description = "莱文斯坦距离,又称Levenshtein距离,是编辑距离的一种。指两个字串之间,由一个转成另一个所需的最少编辑操作次数。"; + this.infoURL = "https://wikipedia.org/wiki/Levenshtein_distance"; + this.inputType = "string"; + this.outputType = "number"; + this.args = [ + { + name: "分隔符", + type: "binaryString", + value: "\\n" + }, + { + name: "插入操作消耗步数", + type: "number", + value: 1 + }, + { + name: "删除操作消耗步数", + type: "number", + value: 1 + }, + { + name: "替换操作消耗步数", + type: "number", + value: 1 + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {number} + */ + run(input, args) { + const [delim, insCost, delCost, subCost] = args; + const samples = input.split(delim); + if (samples.length !== 2) { + throw new OperationError("错误:计算莱文斯坦距离需要两个字符串,请确保输入按照给定分隔符的两个字符串。"); + } + if (insCost < 0 || delCost < 0 || subCost < 0) { + throw new OperationError("消耗量不能为负数。"); + } + const src = samples[0], dest = samples[1]; + let currentCost = new Array(src.length + 1); + let nextCost = new Array(src.length + 1); + for (let i = 0; i < currentCost.length; i++) { + currentCost[i] = delCost * i; + } + for (let i = 0; i < dest.length; i++) { + const destc = dest.charAt(i); + nextCost[0] = currentCost[0] + insCost; + for (let j = 0; j < src.length; j++) { + let candidate; + // insertion + let optCost = currentCost[j + 1] + insCost; + // deletion + candidate = nextCost[j] + delCost; + if (candidate < optCost) optCost = candidate; + // substitution or matched character + candidate = currentCost[j]; + if (src.charAt(j) !== destc) candidate += subCost; + if (candidate < optCost) optCost = candidate; + // store calculated cost + nextCost[j + 1] = optCost; + } + const tempCost = nextCost; + nextCost = currentCost; + currentCost = tempCost; + } + + return currentCost[currentCost.length - 1]; + } + +} + +export default LevenshteinDistance; diff --git a/plugins/srktoolbox/src/core/operations/Lorenz.mjs b/plugins/srktoolbox/src/core/operations/Lorenz.mjs new file mode 100644 index 00000000..28ac3bf7 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Lorenz.mjs @@ -0,0 +1,763 @@ +/** + * Emulation of the Lorenz SZ40/42a/42b cipher attachment. + * + * Tested against the Colossus Rebuild at Bletchley Park's TNMOC + * using a variety of inputs and settings to confirm correctness. + * + * @author VirtualColossus [martin@virtualcolossus.co.uk] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Lorenz operation + */ +class Lorenz extends Operation { + + /** + * Lorenz constructor + */ + constructor() { + super(); + + this.name = "Lorenz"; + this.module = "Bletchley"; + this.description = "The Lorenz SZ40/42 cipher attachment was a WW2 German rotor cipher machine with twelve rotors which attached in-line between remote teleprinters.

It used the Vernam cipher with two groups of five rotors (named the psi(ψ) wheels and chi(χ) wheels at Bletchley Park) to create two pseudorandom streams of five bits, encoded in ITA2, which were XOR added to the plaintext. Two other rotors, dubbed the mu(μ) or motor wheels, could hold up the stepping of the psi wheels meaning they stepped intermittently.

Each rotor has a different number of cams/lugs around their circumference which could be set active or inactive changing the key stream.

Three models of the Lorenz are emulated, SZ40, SZ42a and SZ42b and three example wheel patterns (the lug settings) are included (KH, ZMUG & BREAM) with the option to set a custom set using the letter 'x' for active or '.' for an inactive lug.

The input can either be plaintext or ITA2 when sending and ITA2 when receiving.

To learn more, Virtual Lorenz, an online, browser based simulation of the Lorenz SZ40/42 is available at lorenz.virtualcolossus.co.uk.

A more detailed description of this operation can be found here."; + this.infoURL = "https://wikipedia.org/wiki/Lorenz_cipher"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "Model", + type: "option", + value: ["SZ40", "SZ42a", "SZ42b"] + }, + { + name: "Wheel Pattern", + type: "argSelector", + value: [ + { + name: "KH Pattern", + off: [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30] + }, + { + name: "ZMUG Pattern", + off: [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30] + }, + { + name: "BREAM Pattern", + off: [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30] + }, + { + name: "No Pattern", + off: [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30] + }, + { + name: "Custom", + on: [19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30] + } + ] + }, + { + name: "KT-Schalter", + type: "boolean", + value: false + }, + { + name: "Mode", + type: "argSelector", + value: [ + { + name: "Send", + on: [4], + off: [5] + }, + { + name: "Receive", + off: [4], + on: [5] + } + ] + }, + { + name: "Input Type", + type: "option", + value: ["Plaintext", "ITA2"] + }, + { + name: "Output Type", + type: "option", + value: ["Plaintext", "ITA2"] + }, + { + name: "ITA2 Format", + type: "option", + value: ["5/8/9", "+/-/."] + }, + { + name: "Ψ1 start (1-43)", + type: "number", + value: 1 + }, + { + name: "Ψ2 start (1-47)", + type: "number", + value: 1 + }, + { + name: "Ψ3 start (1-51)", + type: "number", + value: 1 + }, + { + name: "Ψ4 start (1-53)", + type: "number", + value: 1 + }, + { + name: "Ψ5 start (1-59)", + type: "number", + value: 1 + }, + { + name: "Μ37 start (1-37)", + type: "number", + value: 1 + }, + { + name: "Μ61 start (1-61)", + type: "number", + value: 1 + }, + { + name: "Χ1 start (1-41)", + type: "number", + value: 1 + }, + { + name: "Χ2 start (1-31)", + type: "number", + value: 1 + }, + { + name: "Χ3 start (1-29)", + type: "number", + value: 1 + }, + { + name: "Χ4 start (1-26)", + type: "number", + value: 1 + }, + { + name: "Χ5 start (1-23)", + type: "number", + value: 1 + }, + { + name: "Ψ1 lugs (43)", + type: "string", + value: ".x...xx.x.x..xxx.x.x.xxxx.x.x.x.x.x..x.xx.x" + }, + { + name: "Ψ2 lugs (47)", + type: "string", + value: ".xx.x.xxx..x.x.x..x.xx.x.xxx.x....x.xx.x.x.x..x" + }, + { + name: "Ψ3 lugs (51)", + type: "string", + value: ".x.x.x..xxx....x.x.xx.x.x.x..xxx.x.x..x.x.xx..x.x.x" + }, + { + name: "Ψ4 lugs (53)", + type: "string", + value: ".xx...xxxxx.x.x.xx...x.xx.x.x..x.x.xx.x..x.x.x.x.x.x." + }, + { + name: "Ψ5 lugs (59)", + type: "string", + value: "xx...xx.x..x.xx.x...x.x.x.x.x.x.x.x.xx..xxxx.x.x...xx.x..x." + }, + { + name: "Μ37 lugs (37)", + type: "string", + value: "x.x.x.x.x.x...x.x.x...x.x.x...x.x...." + }, + { + name: "Μ61 lugs (61)", + type: "string", + value: ".xxxx.xxxx.xxx.xxxx.xx....xxx.xxxx.xxxx.xxxx.xxxx.xxx.xxxx..." + }, + { + name: "Χ1 lugs (41)", + type: "string", + value: ".x...xxx.x.xxxx.x...x.x..xxx....xx.xxxx.." + }, + { + name: "Χ2 lugs (31)", + type: "string", + value: "x..xxx...x.xxxx..xx..x..xx.xx.." + }, + { + name: "Χ3 lugs (29)", + type: "string", + value: "..xx..x.xxx...xx...xx..xx.xx." + }, + { + name: "Χ4 lugs (26)", + type: "string", + value: "xx..x..xxxx..xx.xxx....x.." + }, + { + name: "Χ5 lugs (23)", + type: "string", + value: "xx..xx....xxxx.x..x.x.." + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + + const model = args[0], + pattern = args[1], + kt = args[2], + mode = args[3], + intype = args[4], + outtype = args[5], + format = args[6], + lugs1 = args[19], + lugs2 = args[20], + lugs3 = args[21], + lugs4 = args[22], + lugs5 = args[23], + lugm37 = args[24], + lugm61 = args[25], + lugx1 = args[26], + lugx2 = args[27], + lugx3 = args[28], + lugx4 = args[29], + lugx5 = args[30]; + + let s1 = args[7], + s2 = args[8], + s3 = args[9], + s4 = args[10], + s5 = args[11], + m37 = args[12], + m61 = args[13], + x1 = args[14], + x2 = args[15], + x3 = args[16], + x4 = args[17], + x5 = args[18]; + + this.reverseTable(); + + if (s1<1 || s1>43) throw new OperationError("Ψ1 start must be between 1 and 43"); + if (s2<1 || s2>47) throw new OperationError("Ψ2 start must be between 1 and 47"); + if (s3<1 || s3>51) throw new OperationError("Ψ3 start must be between 1 and 51"); + if (s4<1 || s4>53) throw new OperationError("Ψ4 start must be between 1 and 53"); + if (s5<1 || s5>59) throw new OperationError("Ψ5 start must be between 1 and 59"); + if (m37<1 || m37>37) throw new OperationError("Μ37 start must be between 1 and 37"); + if (m61<1 || m61>61) throw new OperationError("Μ61 start must be between 1 and 61"); + if (x1<1 || x1>41) throw new OperationError("Χ1 start must be between 1 and 41"); + if (x2<1 || x2>31) throw new OperationError("Χ2 start must be between 1 and 31"); + if (x3<1 || x3>29) throw new OperationError("Χ3 start must be between 1 and 29"); + if (x4<1 || x4>26) throw new OperationError("Χ4 start must be between 1 and 26"); + if (x5<1 || x5>23) throw new OperationError("Χ5 start must be between 1 and 23"); + + // Initialise chosen wheel pattern + let chosenSetting = ""; + if (pattern === "Custom") { + const re = new RegExp("^[.xX]*$"); + if (lugs1.length !== 43 || !re.test(lugs1)) throw new OperationError("Ψ1 custom lugs must be 43 long and can only include . or x "); + if (lugs2.length !== 47 || !re.test(lugs2)) throw new OperationError("Ψ2 custom lugs must be 47 long and can only include . or x"); + if (lugs3.length !== 51 || !re.test(lugs3)) throw new OperationError("Ψ3 custom lugs must be 51 long and can only include . or x"); + if (lugs4.length !== 53 || !re.test(lugs4)) throw new OperationError("Ψ4 custom lugs must be 53 long and can only include . or x"); + if (lugs5.length !== 59 || !re.test(lugs5)) throw new OperationError("Ψ5 custom lugs must be 59 long and can only include . or x"); + if (lugm37.length !== 37 || !re.test(lugm37)) throw new OperationError("M37 custom lugs must be 37 long and can only include . or x"); + if (lugm61.length !== 61 || !re.test(lugm61)) throw new OperationError("M61 custom lugs must be 61 long and can only include . or x"); + if (lugx1.length !== 41 || !re.test(lugx1)) throw new OperationError("Χ1 custom lugs must be 41 long and can only include . or x"); + if (lugx2.length !== 31 || !re.test(lugx2)) throw new OperationError("Χ2 custom lugs must be 31 long and can only include . or x"); + if (lugx3.length !== 29 || !re.test(lugx3)) throw new OperationError("Χ3 custom lugs must be 29 long and can only include . or x"); + if (lugx4.length !== 26 || !re.test(lugx4)) throw new OperationError("Χ4 custom lugs must be 26 long and can only include . or x"); + if (lugx5.length !== 23 || !re.test(lugx5)) throw new OperationError("Χ5 custom lugs must be 23 long and can only include . or x"); + chosenSetting = INIT_PATTERNS["No Pattern"]; + chosenSetting.S[1] = this.readLugs(lugs1); + chosenSetting.S[2] = this.readLugs(lugs2); + chosenSetting.S[3] = this.readLugs(lugs3); + chosenSetting.S[4] = this.readLugs(lugs4); + chosenSetting.S[5] = this.readLugs(lugs5); + chosenSetting.M[1] = this.readLugs(lugm61); + chosenSetting.M[2] = this.readLugs(lugm37); + chosenSetting.X[1] = this.readLugs(lugx1); + chosenSetting.X[2] = this.readLugs(lugx2); + chosenSetting.X[3] = this.readLugs(lugx3); + chosenSetting.X[4] = this.readLugs(lugx4); + chosenSetting.X[5] = this.readLugs(lugx5); + } else { + chosenSetting = INIT_PATTERNS[pattern]; + } + const chiSettings = chosenSetting.X; // Pin settings for Chi links (X) + const psiSettings = chosenSetting.S; // Pin settings for Psi links (S) + const muSettings = chosenSetting.M; // Pin settings for Motor links (M) + + // Convert input text to ITA2 (including figure/letter shifts) + const ita2Input = this.convertToITA2(input, intype, mode); + + let thisPsi = []; + let thisChi = []; + let m61lug = muSettings[1][m61-1]; + let m37lug = muSettings[2][m37-1]; + const p5 = [0, 0, 0]; + + const self = this; + const letters = Array.prototype.map.call(ita2Input, function(character) { + const letter = character.toUpperCase(); + + // Store lugs used in limitations, need these later + let x2bptr = x2+1; + if (x2bptr===32) x2bptr=1; + let s1bptr = s1+1; + if (s1bptr===44) s1bptr=1; + + thisChi = [ + chiSettings[1][x1-1], + chiSettings[2][x2-1], + chiSettings[3][x3-1], + chiSettings[4][x4-1], + chiSettings[5][x5-1] + ]; + + thisPsi = [ + psiSettings[1][s1-1], + psiSettings[2][s2-1], + psiSettings[3][s3-1], + psiSettings[4][s4-1], + psiSettings[5][s5-1] + ]; + + if (typeof ITA2_TABLE[letter] == "undefined") { + return ""; + } + + // The encipher calculation + + // We calculate Bitwise XOR for each of the 5 bits across our input ( K XOR Psi XOR Chi ) + const xorSum = []; + for (let i=0;i<=4;i++) { + xorSum[i] = ITA2_TABLE[letter][i] ^ thisPsi[i] ^ thisChi[i]; + } + const resultStr = xorSum.join(""); + + // Wheel movement + + // Chi wheels always move one back after each letter + if (--x1 < 1) x1 = 41; + if (--x2 < 1) x2 = 31; + if (--x3 < 1) x3 = 29; + if (--x4 < 1) x4 = 26; + if (--x5 < 1) x5 = 23; + + // Motor wheel (61 pin) also moves one each letter + if (--m61 < 1) m61 = 61; + + // If M61 is set, we also move M37 + if (m61lug === 1) { + if (--m37 < 1) m37 = 37; + } + + // Psi wheels only move sometimes, dependent on M37 current setting and limitations + + const basicmotor = m37lug; + let totalmotor; + let lim = 0; + + p5[2] = p5[1]; + p5[1] = p5[0]; + if (mode==="Send") { + p5[0] = parseInt(ITA2_TABLE[letter][4], 10); + } else { + p5[0] = parseInt(xorSum[4], 10); + } + + // Limitations here + if (model==="SZ42a") { + // Chi 2 one back lim - The active character of Chi 2 (2nd Chi wheel) in the previous position + lim = parseInt(chiSettings[2][x2bptr-1], 10); + if (kt) { + // p5 back 2 + if (lim===p5[2]) { + lim = 0; + } else { + lim=1; + } + } + + // If basic motor = 0 and limitation = 1, Total motor = 0 [no move], otherwise, total motor = 1 [move] + if (basicmotor===0 && lim===1) { + totalmotor = 0; + } else { + totalmotor = 1; + } + + } else if (model==="SZ42b") { + // Chi 2 one back + Psi 1 one back. + const x2b1lug = parseInt(chiSettings[2][x2bptr-1], 10); + const s1b1lug = parseInt(psiSettings[1][s1bptr-1], 10); + lim = 1; + if (x2b1lug===s1b1lug) lim=0; + if (kt) { + // p5 back 2 + if (lim===p5[2]) { + lim=0; + } else { + lim=1; + } + } + // If basic motor = 0 and limitation = 1, Total motor = 0 [no move], otherwise, total motor = 1 [move] + if (basicmotor===0 && lim===1) { + totalmotor = 0; + } else { + totalmotor = 1; + } + + } else if (model==="SZ40") { + // SZ40 - just move based on the M37 motor wheel + totalmotor = basicmotor; + } else { + throw new OperationError("Lorenz model type not recognised"); + } + + // Move the Psi wheels when current totalmotor active + if (totalmotor === 1) { + if (--s1 < 1) s1 = 43; + if (--s2 < 1) s2 = 47; + if (--s3 < 1) s3 = 51; + if (--s4 < 1) s4 = 53; + if (--s5 < 1) s5 = 59; + } + + m61lug = muSettings[1][m61-1]; + m37lug = muSettings[2][m37-1]; + + let rtnstr = self.REVERSE_ITA2_TABLE[resultStr]; + if (format==="5/8/9") { + if (rtnstr==="+") rtnstr="5"; // + or 5 used to represent figure shift + if (rtnstr==="-") rtnstr="8"; // - or 8 used to represent letter shift + if (rtnstr===".") rtnstr="9"; // . or 9 used to represent space + } + return rtnstr; + }); + + const ita2output = letters.join(""); + + return this.convertFromITA2(ita2output, outtype, mode); + + } + + /** + * Reverses the ITA2 Code lookup table + */ + reverseTable() { + this.REVERSE_ITA2_TABLE = {}; + this.REVERSE_FIGSHIFT_TABLE = {}; + + for (const letter in ITA2_TABLE) { + const code = ITA2_TABLE[letter]; + this.REVERSE_ITA2_TABLE[code] = letter; + } + for (const letter in figShiftArr) { + const ltr = figShiftArr[letter]; + this.REVERSE_FIGSHIFT_TABLE[ltr] = letter; + } + } + + /** + * Read lugs settings - convert to 0|1 + */ + readLugs(lugstr) { + const arr = Array.prototype.map.call(lugstr, function(lug) { + if (lug===".") { + return 0; + } else { + return 1; + } + }); + return arr; + } + + /** + * Convert input plaintext to ITA2 + */ + convertToITA2(input, intype, mode) { + let result = ""; + let figShifted = false; + + for (const character of input) { + const letter = character.toUpperCase(); + + // Convert input text to ITA2 (including figure/letter shifts) + if (intype === "ITA2" || mode === "Receive") { + if (validITA2.indexOf(letter) === -1) { + let errltr = letter; + if (errltr==="\n") errltr = "Carriage Return"; + if (errltr===" ") errltr = "Space"; + throw new OperationError("Invalid ITA2 character : "+errltr); + } + result += letter; + } else { + if (validChars.indexOf(letter) === -1) throw new OperationError("Invalid Plaintext character : "+letter); + + if (!figShifted && figShiftedChars.indexOf(letter) !== -1) { + // in letters mode and next char needs to be figure shifted + figShifted = true; + result += "55" + figShiftArr[letter]; + } else if (figShifted) { + // in figures mode and next char needs to be letter shifted + if (letter==="\n") { + result += "34"; + } else if (letter==="\r") { + result += "4"; + } else if (figShiftedChars.indexOf(letter) === -1) { + figShifted = false; + result += "88" + letter; + } else { + result += figShiftArr[letter]; + } + + } else { + if (letter==="\n") { + result += "34"; + } else if (letter==="\r") { + result += "4"; + } else { + result += letter; + } + } + + } + + } + + return result; + } + + /** + * Convert final result ITA2 to plaintext + */ + convertFromITA2(input, outtype, mode) { + let result = ""; + let figShifted = false; + for (const letter of input) { + if (mode === "Receive") { + + // Convert output ITA2 to plaintext (including figure/letter shifts) + if (outtype === "Plaintext") { + + if (letter === "5" || letter === "+") { + figShifted = true; + } else if (letter === "8" || letter === "-") { + figShifted = false; + } else if (letter === "9") { + result += " "; + } else if (letter === "3") { + result += "\n"; + } else if (letter === "4") { + result += ""; + } else if (letter === "/") { + result += "/"; + } else { + + if (figShifted) { + result += this.REVERSE_FIGSHIFT_TABLE[letter]; + } else { + result += letter; + } + + } + + } else { + result += letter; + } + + } else { + result += letter; + } + } + + return result; + + } + +} + +const ITA2_TABLE = { + "A": "11000", + "B": "10011", + "C": "01110", + "D": "10010", + "E": "10000", + "F": "10110", + "G": "01011", + "H": "00101", + "I": "01100", + "J": "11010", + "K": "11110", + "L": "01001", + "M": "00111", + "N": "00110", + "O": "00011", + "P": "01101", + "Q": "11101", + "R": "01010", + "S": "10100", + "T": "00001", + "U": "11100", + "V": "01111", + "W": "11001", + "X": "10111", + "Y": "10101", + "Z": "10001", + "3": "00010", + "4": "01000", + "9": "00100", + "/": "00000", + " ": "00100", + ".": "00100", + "8": "11111", + "5": "11011", + "-": "11111", + "+": "11011" +}; + +const validChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890+-'()/:=?,. \n\r"; +const validITA2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ34589+-./"; +const figShiftedChars = "1234567890+-'()/:=?,."; + +const figShiftArr = { + "1": "Q", + "2": "W", + "3": "E", + "4": "R", + "5": "T", + "6": "Y", + "7": "U", + "8": "I", + "9": "O", + "0": "P", + " ": "9", + "-": "A", + "?": "B", + ":": "C", + "#": "D", + "%": "F", + "@": "G", + "£": "H", + "": "J", + "(": "K", + ")": "L", + ".": "M", + ",": "N", + "'": "S", + "=": "V", + "/": "X", + "+": "Z", + "\n": "3", + "\r": "4" +}; + +const INIT_PATTERNS = { + "No Pattern": { + "X": { + 1: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + 2: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + 3: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + 4: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + 5: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + "S": { + 1: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + 2: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + 3: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + 4: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + 5: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + }, + "M": { + 1: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + 2: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + } + + }, + "KH Pattern": { + "X": { + 1: [0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0], + 2: [1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0], + 3: [0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0], + 4: [1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0], + 5: [1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0] + }, + "S": { + 1: [0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1], + 2: [0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1], + 3: [0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1], + 4: [0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0], + 5: [1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0] + }, + "M": { + 1: [0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0], + 2: [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0] + } + }, + "ZMUG Pattern": { + "X": { + 1: [0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0], + 2: [1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0], + 3: [0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0], + 4: [1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1], + 5: [0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1] + }, + "S": { + 1: [1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0], + 2: [0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1], + 3: [0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1], + 4: [0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1], + 5: [1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0] + }, + "M": { + 1: [1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1], + 2: [0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1] + } + }, + "BREAM Pattern": { + "X": { + 1: [0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0], + 2: [0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1], + 3: [1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0], + 4: [1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0], + 5: [0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0] + }, + "S": { + 1: [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0], + 2: [1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0], + 3: [1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], + 4: [0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1], + 5: [1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0] + }, + "M": { + 1: [1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1], + 2: [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1] + } + } +}; + +export default Lorenz; diff --git a/plugins/srktoolbox/src/core/operations/LuhnChecksum.mjs b/plugins/srktoolbox/src/core/operations/LuhnChecksum.mjs new file mode 100644 index 00000000..53bb838e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/LuhnChecksum.mjs @@ -0,0 +1,98 @@ +/** + * @author n1073645 [n1073645@gmail.com] + * @author k3ach [k3ach@proton.me] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Luhn Checksum operation + */ +class LuhnChecksum extends Operation { + + /** + * LuhnChecksum constructor + */ + constructor() { + super(); + + this.name = "Luhn校验和"; + this.module = "Default"; + this.description = "The Luhn mod N algorithm using the english alphabet. The Luhn mod N algorithm is an extension to the Luhn algorithm (also known as mod 10 algorithm) that allows it to work with sequences of values in any even-numbered base. This can be useful when a check digit is required to validate an identification string composed of letters, a combination of letters and digits or any arbitrary set of N characters where N is divisible by 2."; + this.infoURL = "https://en.wikipedia.org/wiki/Luhn_mod_N_algorithm"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Radix", + "type": "number", + "value": 10 + } + ]; + } + + /** + * Generates the Luhn checksum from the input. + * + * @param {string} inputStr + * @returns {number} + */ + checksum(inputStr, radix = 10) { + let even = false; + return inputStr.split("").reverse().reduce((acc, elem) => { + // Convert element to an integer based on the provided radix. + let temp = parseInt(elem, radix); + + // If element is not a valid number in the given radix. + if (isNaN(temp)) { + throw new Error("Character: " + elem + " is not valid in radix " + radix + "."); + } + + // If element is in an even position + if (even) { + // Double the element and sum the quotient and remainder. + temp = 2 * temp; + temp = Math.floor(temp / radix) + (temp % radix); + } + + even = !even; + return acc + temp; + }, 0) % radix; // Use radix as the modulus base + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (!input) return ""; + + const radix = args[0]; + + if (radix < 2 || radix > 36) { + throw new OperationError("Error: Radix argument must be between 2 and 36"); + } + + if (radix % 2 !== 0) { + throw new OperationError("Error: Radix argument must be divisible by 2"); + } + + const checkSum = this.checksum(input, radix).toString(radix); + let checkDigit = this.checksum(input + "0", radix); + checkDigit = checkDigit === 0 ? 0 : (radix - checkDigit); + checkDigit = checkDigit.toString(radix); + + return `校验和: ${checkSum} +检验位: ${checkDigit} +Luhn校验字符串: ${input + "" + checkDigit}`; + } + +} + +export default LuhnChecksum; diff --git a/plugins/srktoolbox/src/core/operations/MD2.mjs b/plugins/srktoolbox/src/core/operations/MD2.mjs new file mode 100644 index 00000000..08511420 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/MD2.mjs @@ -0,0 +1,50 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * MD2 operation + */ +class MD2 extends Operation { + + /** + * MD2 constructor + */ + constructor() { + super(); + + this.name = "MD2"; + this.module = "Crypto"; + this.description = "MD2讯息摘要算法(英语:MD2 Message-Digest Algorithm)是由Ronald Rivest在1989年设计的密码杂凑函数,该算法针对8位计算机进行了优化。

尽管早就被认为不够安全,但直到2014年,MD2依然配合RSA算法用于生成证书公钥。此算法默认进行18轮计算。"; + this.infoURL = "https://wikipedia.org/wiki/MD2_(cryptography)"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "轮数", + type: "number", + value: 18, + min: 0 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return runHash("md2", input, {rounds: args[0]}); + } + +} + +export default MD2; diff --git a/plugins/srktoolbox/src/core/operations/MD4.mjs b/plugins/srktoolbox/src/core/operations/MD4.mjs new file mode 100644 index 00000000..3d628c89 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/MD4.mjs @@ -0,0 +1,43 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * MD4 operation + */ +class MD4 extends Operation { + + /** + * MD4 constructor + */ + constructor() { + super(); + + this.name = "MD4"; + this.module = "Crypto"; + this.description = "MD4是麻省理工学院教授Ronald Rivest于1990年设计的一种信息摘要算法。它是一种用来测试信息完整性的密码散列函数的实行。其摘要长度为128位。这个算法影响了后来的算法如MD5、SHA家族和RIPEMD等。

MD4算法具有严重的安全漏洞,目前已被淘汰。"; + this.infoURL = "https://wikipedia.org/wiki/MD4"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return runHash("md4", input); + } + +} + +export default MD4; diff --git a/plugins/srktoolbox/src/core/operations/MD5.mjs b/plugins/srktoolbox/src/core/operations/MD5.mjs new file mode 100644 index 00000000..c93e0b54 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/MD5.mjs @@ -0,0 +1,43 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * MD5 operation + */ +class MD5 extends Operation { + + /** + * MD5 constructor + */ + constructor() { + super(); + + this.name = "MD5"; + this.module = "Crypto"; + this.description = "MD5消息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16个字符(BYTES))的散列值(hash value),用于确保信息传输完整一致。

2004年,证实MD5算法无法防止碰撞攻击,因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。"; + this.infoURL = "https://wikipedia.org/wiki/MD5"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return runHash("md5", input); + } + +} + +export default MD5; diff --git a/plugins/srktoolbox/src/core/operations/MD6.mjs b/plugins/srktoolbox/src/core/operations/MD6.mjs new file mode 100644 index 00000000..7ce1be0e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/MD6.mjs @@ -0,0 +1,67 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import NodeMD6 from "node-md6"; + +/** + * MD6 operation + */ +class MD6 extends Operation { + + /** + * MD6 constructor + */ + constructor() { + super(); + + this.name = "MD6"; + this.module = "Crypto"; + this.description = "MD6消息摘要算法是一个密码散列函数。它使用默克尔树形式的结构,允许对很长的输入并行进行大量散列计算。"; + this.infoURL = "https://wikipedia.org/wiki/MD6"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "长度", + "type": "number", + "value": 256 + }, + { + "name": "层次(Level)", + "type": "number", + "value": 64 + }, + { + "name": "Key", + "type": "string", + "value": "" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [size, levels, key] = args; + + if (size < 0 || size > 512) + throw new OperationError("长度必须位于 0 和 512 之间"); + if (levels < 0) + throw new OperationError("层次必须大于 0"); + + return NodeMD6.getHashOfText(input, size, key, levels); + } + +} + +export default MD6; diff --git a/plugins/srktoolbox/src/core/operations/MIMEDecoding.mjs b/plugins/srktoolbox/src/core/operations/MIMEDecoding.mjs new file mode 100644 index 00000000..80dd6766 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/MIMEDecoding.mjs @@ -0,0 +1,173 @@ +/** + * @author mshwed [m@ttshwed.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { fromHex } from "../lib/Hex.mjs"; +import { fromBase64 } from "../lib/Base64.mjs"; +import cptable from "codepage"; + +/** + * MIME Decoding operation + */ +class MIMEDecoding extends Operation { + + /** + * MIMEDecoding constructor + */ + constructor() { + super(); + + this.name = "MIME解码"; + this.module = "Default"; + this.description = "解码RFC2047使用“非ASCII文本扩展”的MIME标头。"; + this.infoURL = "https://tools.ietf.org/html/rfc2047"; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const mimeEncodedText = Utils.byteArrayToUtf8(input); + const encodedHeaders = mimeEncodedText.replace(/\r\n/g, "\n"); + + const decodedHeader = this.decodeHeaders(encodedHeaders); + + return decodedHeader; + } + + /** + * Decode MIME header strings + * + * @param headerString + */ + decodeHeaders(headerString) { + // No encoded words detected + let i = headerString.indexOf("=?"); + if (i === -1) return headerString; + + let decodedHeaders = headerString.slice(0, i); + let header = headerString.slice(i); + + let isBetweenWords = false; + let start, cur, charset, encoding, j, end, text; + while (header.length > -1) { + start = header.indexOf("=?"); + if (start === -1) break; + cur = start + "=?".length; + + i = header.slice(cur).indexOf("?"); + if (i === -1) break; + + charset = header.slice(cur, cur + i); + cur += i + "?".length; + + if (header.length < cur + "Q??=".length) break; + + encoding = header[cur]; + cur += 1; + + if (header[cur] !== "?") break; + + cur += 1; + + j = header.slice(cur).indexOf("?="); + if (j === -1) break; + + text = header.slice(cur, cur + j); + end = cur + j + "?=".length; + + if (encoding.toLowerCase() === "b") { + text = fromBase64(text); + } else if (encoding.toLowerCase() === "q") { + text = this.parseQEncodedWord(text); + } else { + isBetweenWords = false; + decodedHeaders += header.slice(0, start + 2); + header = header.slice(start + 2); + } + + if (start > 0 && (!isBetweenWords || header.slice(0, start).search(/\S/g) > -1)) { + decodedHeaders += header.slice(0, start); + } + + decodedHeaders += this.convertFromCharset(charset, text); + + header = header.slice(end); + isBetweenWords = true; + } + + if (header.length > 0) { + decodedHeaders += header; + } + + return decodedHeaders; + } + + /** + * Converts decoded text for supported charsets. + * Supports UTF-8, US-ASCII, ISO-8859-* + * + * @param encodedWord + */ + convertFromCharset(charset, encodedText) { + charset = charset.toLowerCase(); + const parsedCharset = charset.split("-"); + + if (parsedCharset.length === 2 && parsedCharset[0] === "utf" && charset === "utf-8") { + return cptable.utils.decode(65001, encodedText); + } else if (parsedCharset.length === 2 && charset === "us-ascii") { + return cptable.utils.decode(20127, encodedText); + } else if (parsedCharset.length === 3 && parsedCharset[0] === "iso" && parsedCharset[1] === "8859") { + const isoCharset = parseInt(parsedCharset[2], 10); + if (isoCharset >= 1 && isoCharset <= 16) { + return cptable.utils.decode(28590 + isoCharset, encodedText); + } + } + + throw new OperationError("不支持的字符集"); + } + + /** + * Parses a Q encoded word + * + * @param encodedWord + */ + parseQEncodedWord(encodedWord) { + let decodedWord = ""; + for (let i = 0; i < encodedWord.length; i++) { + if (encodedWord[i] === "_") { + decodedWord += " "; + // Parse hex encoding + } else if (encodedWord[i] === "=") { + if ((i + 2) >= encodedWord.length) throw new OperationError("Q编码错误"); + const decodedHex = Utils.byteArrayToChars(fromHex(encodedWord.substring(i + 1, i + 3))); + decodedWord += decodedHex; + i += 2; + } else if ( + (encodedWord[i].charCodeAt(0) >= " ".charCodeAt(0) && encodedWord[i].charCodeAt(0) <= "~".charCodeAt(0)) || + encodedWord[i] === "\n" || + encodedWord[i] === "\r" || + encodedWord[i] === "\t") { + decodedWord += encodedWord[i]; + } else { + throw new OperationError("Q编码错误"); + } + } + + return decodedWord; + } +} + +export default MIMEDecoding; diff --git a/plugins/srktoolbox/src/core/operations/Magic.mjs b/plugins/srktoolbox/src/core/operations/Magic.mjs new file mode 100644 index 00000000..80681cee --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Magic.mjs @@ -0,0 +1,170 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import Dish from "../Dish.mjs"; +import MagicLib from "../lib/Magic.mjs"; + +/** + * Magic operation + */ +class Magic extends Operation { + + /** + * Magic constructor + */ + constructor() { + super(); + + this.name = "Magic"; + this.flowControl = true; + this.module = "Default"; + this.description = "Magic操作尝试检测输入数据的多种属性来建议对应的操作。

设定
深度:如果某个操作和数据相符,此操作会被运行一次,运行结果会被再次分析。此参数设置递归的最大次数。

加强模式:当此模式开启时,多种操作如XOR、位运算和字符编码会进行暴力破解来检测可能的数据处理方式。为提高性能,仅有前100个字节会被暴力破解。

扩展语言支持:在每个阶段,数据的相对字节频率数据会和各种现实语言的平均频率进行对照。默认情况下仅检测约40种互联网常见语言。扩展语言功能将语言数据提高到284种,这使得数据可以匹配更多语言种类,如果它们的频率数据相近的话。

支持输入一个正则表达式来过滤输出结果(crib)。"; + this.infoURL = "https://github.com/gchq/CyberChef/wiki/Automatic-detection-of-encoded-data-using-CyberChef-Magic"; + this.inputType = "ArrayBuffer"; + this.outputType = "JSON"; + this.presentType = "html"; + this.args = [ + { + "name": "深度", + "type": "number", + "value": 3 + }, + { + "name": "加强模式", + "type": "boolean", + "value": false + }, + { + "name": "扩展语言支持", + "type": "boolean", + "value": false + }, + { + "name": "Crib(已知明文字符串或正则)", + "type": "string", + "value": "" + } + ]; + } + + /** + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on. + * @param {Operation[]} state.opList - The list of operations in the recipe. + * @returns {Object} The updated state of the recipe. + */ + async run(state) { + const ings = state.opList[state.progress].ingValues, + [depth, intensive, extLang, crib] = ings, + dish = state.dish, + magic = new MagicLib(await dish.get(Dish.ARRAY_BUFFER)), + cribRegex = (crib && crib.length) ? new RegExp(crib, "i") : null; + let options = await magic.speculativeExecution(depth, extLang, intensive, [], false, cribRegex); + + // Filter down to results which matched the crib + if (cribRegex) { + options = options.filter(option => option.matchesCrib); + } + + // Record the current state for use when presenting + this.state = state; + + dish.set(options, Dish.JSON); + return state; + } + + /** + * Displays Magic results in HTML for web apps. + * + * @param {JSON} options + * @returns {html} + */ + present(options) { + const currentRecipeConfig = this.state.opList.map(op => op.config); + + let output = ` + + + + + `; + + /** + * Returns a CSS colour value based on an integer input. + * + * @param {number} val + * @returns {string} + */ + function chooseColour(val) { + if (val < 3) return "green"; + if (val < 5) return "goldenrod"; + return "red"; + } + + options.forEach(option => { + // Construct recipe URL + // Replace this Magic op with the generated recipe + const recipeConfig = currentRecipeConfig.slice(0, this.state.progress) + .concat(option.recipe) + .concat(currentRecipeConfig.slice(this.state.progress + 1)), + recipeURL = "recipe=" + Utils.encodeURIFragment(Utils.generatePrettyRecipe(recipeConfig)); + + let language = "", + fileType = "", + matchingOps = "", + useful = ""; + const entropy = `信息熵: ${option.entropy.toFixed(2)}`, + validUTF8 = option.isUTF8 ? "有效UTF8\n" : ""; + + if (option.languageScores[0].probability > 0) { + let likelyLangs = option.languageScores.filter(l => l.probability > 0); + if (likelyLangs.length < 1) likelyLangs = [option.languageScores[0]]; + language = "" + + "可能为以下语言:\n " + + likelyLangs.map(lang => { + return MagicLib.codeToLanguage(lang.lang); + }).join("\n ") + + "\n"; + } + + if (option.fileType) { + fileType = `文件类型:${option.fileType.mime} (${option.fileType.ext})\n`; + } + + if (option.matchingOps.length) { + matchingOps = `对应操作:${[...new Set(option.matchingOps.map(op => op.op))].join(", ")}\n`; + } + + if (option.useful) { + useful = "检测到建议操作\n"; + } + + output += ` + + + + `; + }); + + output += "
操作(点击加载)结果摘要属性
${Utils.generatePrettyRecipe(option.recipe, true)}${Utils.escapeHtml(Utils.escapeWhitespace(Utils.truncate(option.data, 99)))}${language}${fileType}${matchingOps}${useful}${validUTF8}${entropy}
"; + + if (!options.length) { + output = "针对输入数据未检测到任何可用操作。\n请尝试调整操作参数。"; + } + + return output; + } + +} + +export default Magic; diff --git a/plugins/srktoolbox/src/core/operations/Mean.mjs b/plugins/srktoolbox/src/core/operations/Mean.mjs new file mode 100644 index 00000000..05bb1fa8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Mean.mjs @@ -0,0 +1,53 @@ +/** + * @author bwhitn [brian.m.whitney@outlook.com] + * @author d98762625 [d98762625@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { mean, createNumArray } from "../lib/Arithmetic.mjs"; +import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs"; +import BigNumber from "bignumber.js"; + +/** + * Mean operation + */ +class Mean extends Operation { + + /** + * Mean constructor + */ + constructor() { + super(); + + this.name = "求平均"; + this.module = "Default"; + this.description = "对一组数字求平均值。非数字的值会被忽略。

例: 0x0a 8 .5 .5 计算为 4.75"; + this.infoURL = "https://wikipedia.org/wiki/Arithmetic_mean"; + this.inputType = "string"; + this.outputType = "BigNumber"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": ARITHMETIC_DELIM_OPTIONS, + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {BigNumber} + */ + run(input, args) { + const val = mean(createNumArray(input, args[0])); + return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN); + } + +} + +export default Mean; diff --git a/plugins/srktoolbox/src/core/operations/Median.mjs b/plugins/srktoolbox/src/core/operations/Median.mjs new file mode 100644 index 00000000..b03e6074 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Median.mjs @@ -0,0 +1,53 @@ +/** + * @author bwhitn [brian.m.whitney@outlook.com] + * @author d98762625 [d98762625@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import BigNumber from "bignumber.js"; +import Operation from "../Operation.mjs"; +import { median, createNumArray } from "../lib/Arithmetic.mjs"; +import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs"; + +/** + * Median operation + */ +class Median extends Operation { + + /** + * Median constructor + */ + constructor() { + super(); + + this.name = "求中位数"; + this.module = "Default"; + this.description = "对一组数字求中位数。非数字的值会被忽略。

例: 0x0a 8 1 .5 计算为 4.5"; + this.infoURL = "https://wikipedia.org/wiki/Median"; + this.inputType = "string"; + this.outputType = "BigNumber"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": ARITHMETIC_DELIM_OPTIONS, + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {BigNumber} + */ + run(input, args) { + const val = median(createNumArray(input, args[0])); + return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN); + } + +} + +export default Median; diff --git a/plugins/srktoolbox/src/core/operations/Merge.mjs b/plugins/srktoolbox/src/core/operations/Merge.mjs new file mode 100644 index 00000000..6dc42b76 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Merge.mjs @@ -0,0 +1,52 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Merge operation + */ +class Merge extends Operation { + + /** + * Merge constructor + */ + constructor() { + super(); + + this.name = "Merge"; + this.flowControl = true; + this.module = "Default"; + this.description = "将所有分支合并回一个单独进程。Fork的反操作。不勾选“合并全部”则只会抵消最近的Fork/Subsection。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "合并全部", + type: "boolean", + value: true, + } + ]; + } + + /** + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on. + * @param {Operation[]} state.opList - The list of operations in the recipe. + * @returns {Object} The updated state of the recipe. + */ + run(state) { + // No need to actually do anything here. The fork operation will + // merge when it sees this operation. + return state; + } + +} + +export default Merge; diff --git a/plugins/srktoolbox/src/core/operations/MicrosoftScriptDecoder.mjs b/plugins/srktoolbox/src/core/operations/MicrosoftScriptDecoder.mjs new file mode 100644 index 00000000..00dc6cbf --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/MicrosoftScriptDecoder.mjs @@ -0,0 +1,227 @@ +/** + * @author bmwhitn [brian.m.whitney@outlook.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Microsoft Script Decoder operation + */ +class MicrosoftScriptDecoder extends Operation { + + /** + * MicrosoftScriptDecoder constructor + */ + constructor() { + super(); + + this.name = "Microsoft Script解码"; + this.module = "Default"; + this.description = "解码Microsoft Encoded Script文件。这些文件通常是VBS (Visual Basic Script)或JS (JScript)文件经过微软的特殊方式编码,带有“.vbe”或“.jse”扩展名。

例如:

编码后:
#@~^RQAAAA==-mD~sX|:/TP{~J:+dYbxL~@!F@*@!+@*@!&@*eEI@#@&@#@&.jm.raY 214Wv:zms/obI0xEAAA==^#~@

解码为:
var my_msg = "Testing <1><2><3>!";\n\nVScript.Echo(my_msg);"; + this.infoURL = "https://wikipedia.org/wiki/JScript.Encode"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + this.checks = [ + { + pattern: "#@~\\^.{6}==(.+).{6}==\\^#~@", + flags: "i", + args: [] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const matcher = /#@~\^.{6}==(.+).{6}==\^#~@/; + const encodedData = matcher.exec(input); + if (encodedData) { + return MicrosoftScriptDecoder._decode(encodedData[1]); + } else { + return ""; + } + } + + /** + * Decodes Microsoft Encoded Script files that can be read and executed by cscript.exe/wscript.exe. + * This is a conversion of a Python script that was originally created by Didier Stevens + * (https://DidierStevens.com). + * + * @private + * @param {string} data + * @returns {string} + */ + static _decode(data) { + const result = []; + let index = -1; + data = data.replace(/@&/g, String.fromCharCode(10)) + .replace(/@#/g, String.fromCharCode(13)) + .replace(/@\*/g, ">") + .replace(/@!/g, "<") + .replace(/@\$/g, "@"); + + for (let i = 0; i < data.length; i++) { + const byte = data.charCodeAt(i); + let char = data.charAt(i); + if (byte < 128) { + index++; + } + + if ((byte === 9 || byte > 31 && byte < 128) && + byte !== 60 && + byte !== 62 && + byte !== 64) { + char = D_DECODE[byte].charAt(D_COMBINATION[index % 64]); + } + result.push(char); + } + return result.join(""); + } + +} + +const D_DECODE = [ + "", + "", + "", + "", + "", + "", + "", + "", + "", + "\x57\x6E\x7B", + "\x4A\x4C\x41", + "\x0B\x0B\x0B", + "\x0C\x0C\x0C", + "\x4A\x4C\x41", + "\x0E\x0E\x0E", + "\x0F\x0F\x0F", + "\x10\x10\x10", + "\x11\x11\x11", + "\x12\x12\x12", + "\x13\x13\x13", + "\x14\x14\x14", + "\x15\x15\x15", + "\x16\x16\x16", + "\x17\x17\x17", + "\x18\x18\x18", + "\x19\x19\x19", + "\x1A\x1A\x1A", + "\x1B\x1B\x1B", + "\x1C\x1C\x1C", + "\x1D\x1D\x1D", + "\x1E\x1E\x1E", + "\x1F\x1F\x1F", + "\x2E\x2D\x32", + "\x47\x75\x30", + "\x7A\x52\x21", + "\x56\x60\x29", + "\x42\x71\x5B", + "\x6A\x5E\x38", + "\x2F\x49\x33", + "\x26\x5C\x3D", + "\x49\x62\x58", + "\x41\x7D\x3A", + "\x34\x29\x35", + "\x32\x36\x65", + "\x5B\x20\x39", + "\x76\x7C\x5C", + "\x72\x7A\x56", + "\x43\x7F\x73", + "\x38\x6B\x66", + "\x39\x63\x4E", + "\x70\x33\x45", + "\x45\x2B\x6B", + "\x68\x68\x62", + "\x71\x51\x59", + "\x4F\x66\x78", + "\x09\x76\x5E", + "\x62\x31\x7D", + "\x44\x64\x4A", + "\x23\x54\x6D", + "\x75\x43\x71", + "\x4A\x4C\x41", + "\x7E\x3A\x60", + "\x4A\x4C\x41", + "\x5E\x7E\x53", + "\x40\x4C\x40", + "\x77\x45\x42", + "\x4A\x2C\x27", + "\x61\x2A\x48", + "\x5D\x74\x72", + "\x22\x27\x75", + "\x4B\x37\x31", + "\x6F\x44\x37", + "\x4E\x79\x4D", + "\x3B\x59\x52", + "\x4C\x2F\x22", + "\x50\x6F\x54", + "\x67\x26\x6A", + "\x2A\x72\x47", + "\x7D\x6A\x64", + "\x74\x39\x2D", + "\x54\x7B\x20", + "\x2B\x3F\x7F", + "\x2D\x38\x2E", + "\x2C\x77\x4C", + "\x30\x67\x5D", + "\x6E\x53\x7E", + "\x6B\x47\x6C", + "\x66\x34\x6F", + "\x35\x78\x79", + "\x25\x5D\x74", + "\x21\x30\x43", + "\x64\x23\x26", + "\x4D\x5A\x76", + "\x52\x5B\x25", + "\x63\x6C\x24", + "\x3F\x48\x2B", + "\x7B\x55\x28", + "\x78\x70\x23", + "\x29\x69\x41", + "\x28\x2E\x34", + "\x73\x4C\x09", + "\x59\x21\x2A", + "\x33\x24\x44", + "\x7F\x4E\x3F", + "\x6D\x50\x77", + "\x55\x09\x3B", + "\x53\x56\x55", + "\x7C\x73\x69", + "\x3A\x35\x61", + "\x5F\x61\x63", + "\x65\x4B\x50", + "\x46\x58\x67", + "\x58\x3B\x51", + "\x31\x57\x49", + "\x69\x22\x4F", + "\x6C\x6D\x46", + "\x5A\x4D\x68", + "\x48\x25\x7C", + "\x27\x28\x36", + "\x5C\x46\x70", + "\x3D\x4A\x6E", + "\x24\x32\x7A", + "\x79\x41\x2F", + "\x37\x3D\x5F", + "\x60\x5F\x4B", + "\x51\x4F\x5A", + "\x20\x42\x2C", + "\x36\x65\x57" +]; + +const D_COMBINATION = [ + 0, 1, 2, 0, 1, 2, 1, 2, 2, 1, 2, 1, 0, 2, 1, 2, 0, 2, 1, 2, 0, 0, 1, 2, 2, 1, 0, 2, 1, 2, 2, 1, + 0, 0, 2, 1, 2, 1, 2, 0, 2, 0, 0, 1, 2, 0, 2, 1, 0, 2, 1, 2, 0, 0, 1, 2, 2, 0, 0, 1, 2, 0, 2, 1 +]; + +export default MicrosoftScriptDecoder; diff --git a/plugins/srktoolbox/src/core/operations/MultipleBombe.mjs b/plugins/srktoolbox/src/core/operations/MultipleBombe.mjs new file mode 100644 index 00000000..1af471c2 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/MultipleBombe.mjs @@ -0,0 +1,307 @@ +/** + * Emulation of the Bombe machine. + * This version carries out multiple Bombe runs to handle unknown rotor configurations. + * + * @author s2224834 + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { BombeMachine } from "../lib/Bombe.mjs"; +import { ROTORS, ROTORS_FOURTH, REFLECTORS, Reflector } from "../lib/Enigma.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; + + +/** + * Convenience method for flattening the preset ROTORS object into a newline-separated string. + * @param {Object[]} - Preset rotors object + * @param {number} s - Start index + * @param {number} n - End index + * @returns {string} + */ +function rotorsFormat(rotors, s, n) { + const res = []; + for (const i of rotors.slice(s, n)) { + res.push(i.value); + } + return res.join("\n"); +} + +/** + * Combinatorics choose function + * @param {number} n + * @param {number} k + * @returns number + */ +function choose(n, k) { + let res = 1; + for (let i=1; i<=k; i++) { + res *= (n + 1 - i) / i; + } + return res; +} + +/** + * Bombe operation + */ +class MultipleBombe extends Operation { + /** + * Bombe constructor + */ + constructor() { + super(); + + this.name = "Multiple Bombe"; + this.module = "Bletchley"; + this.description = "Emulation of the Bombe machine used to attack Enigma. This version carries out multiple Bombe runs to handle unknown rotor configurations.

You should test your menu on the single Bombe operation before running it here. See the description of the Bombe operation for instructions on choosing a crib.

More detailed descriptions of the Enigma, Typex and Bombe operations can be found here."; + this.infoURL = "https://wikipedia.org/wiki/Bombe"; + this.inputType = "string"; + this.outputType = "JSON"; + this.presentType = "html"; + this.args = [ + { + "name": "Standard Enigmas", + "type": "populateMultiOption", + "value": [ + { + name: "German Service Enigma (First - 3 rotor)", + value: [ + rotorsFormat(ROTORS, 0, 5), + "", + rotorsFormat(REFLECTORS, 0, 1) + ] + }, + { + name: "German Service Enigma (Second - 3 rotor)", + value: [ + rotorsFormat(ROTORS, 0, 8), + "", + rotorsFormat(REFLECTORS, 0, 2) + ] + }, + { + name: "German Service Enigma (Third - 4 rotor)", + value: [ + rotorsFormat(ROTORS, 0, 8), + rotorsFormat(ROTORS_FOURTH, 1, 2), + rotorsFormat(REFLECTORS, 2, 3) + ] + }, + { + name: "German Service Enigma (Fourth - 4 rotor)", + value: [ + rotorsFormat(ROTORS, 0, 8), + rotorsFormat(ROTORS_FOURTH, 1, 3), + rotorsFormat(REFLECTORS, 2, 4) + ] + }, + { + name: "User defined", + value: ["", "", ""] + }, + ], + "target": [1, 2, 3] + }, + { + name: "Main rotors", + type: "text", + value: "" + }, + { + name: "4th rotor", + type: "text", + value: "" + }, + { + name: "Reflectors", + type: "text", + value: "" + }, + { + name: "Crib", + type: "string", + value: "" + }, + { + name: "Crib offset", + type: "number", + value: 0 + }, + { + name: "Use checking machine", + type: "boolean", + value: true + } + ]; + } + + /** + * Format and send a status update message. + * @param {number} nLoops - Number of loops in the menu + * @param {number} nStops - How many stops so far + * @param {number} progress - Progress (as a float in the range 0..1) + */ + updateStatus(nLoops, nStops, progress, start) { + const elapsed = Date.now() - start; + const remaining = (elapsed / progress) * (1 - progress) / 1000; + const hours = Math.floor(remaining / 3600); + const minutes = `0${Math.floor((remaining % 3600) / 60)}`.slice(-2); + const seconds = `0${Math.floor(remaining % 60)}`.slice(-2); + const msg = `Bombe run with ${nLoops} loop${nLoops === 1 ? "" : "s"} in menu (2+ desirable): ${nStops} stops, ${Math.floor(100 * progress)}% done, ${hours}:${minutes}:${seconds} remaining`; + self.sendStatusMessage(msg); + } + + /** + * Early rotor description string validation. + * Drops stepping information. + * @param {string} rstr - The rotor description string + * @returns {string} - Rotor description with stepping stripped, if any + */ + validateRotor(rstr) { + // The Bombe doesn't take stepping into account so we'll just ignore it here + if (rstr.includes("<")) { + rstr = rstr.split("<", 2)[0]; + } + // Duplicate the validation of the rotor strings here, otherwise you might get an error + // thrown halfway into a big Bombe run + if (!/^[A-Z]{26}$/.test(rstr)) { + throw new OperationError("Rotor wiring must be 26 unique uppercase letters"); + } + if (new Set(rstr).size !== 26) { + throw new OperationError("Rotor wiring must be 26 unique uppercase letters"); + } + return rstr; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const mainRotorsStr = args[1]; + const fourthRotorsStr = args[2]; + const reflectorsStr = args[3]; + let crib = args[4]; + const offset = args[5]; + const check = args[6]; + const rotors = []; + const fourthRotors = []; + const reflectors = []; + for (let rstr of mainRotorsStr.split("\n")) { + rstr = this.validateRotor(rstr); + rotors.push(rstr); + } + if (rotors.length < 3) { + throw new OperationError("A minimum of three rotors must be supplied"); + } + if (fourthRotorsStr !== "") { + for (let rstr of fourthRotorsStr.split("\n")) { + rstr = this.validateRotor(rstr); + fourthRotors.push(rstr); + } + } + if (fourthRotors.length === 0) { + fourthRotors.push(""); + } + for (const rstr of reflectorsStr.split("\n")) { + const reflector = new Reflector(rstr); + reflectors.push(reflector); + } + if (reflectors.length === 0) { + throw new OperationError("A minimum of one reflector must be supplied"); + } + if (crib.length === 0) { + throw new OperationError("Crib cannot be empty"); + } + if (offset < 0) { + throw new OperationError("Offset cannot be negative"); + } + // For symmetry with the Enigma op, for the input we'll just remove all invalid characters + input = input.replace(/[^A-Za-z]/g, "").toUpperCase(); + crib = crib.replace(/[^A-Za-z]/g, "").toUpperCase(); + const ciphertext = input.slice(offset); + let update; + if (isWorkerEnvironment()) { + update = this.updateStatus; + } else { + update = undefined; + } + let bombe = undefined; + const output = {bombeRuns: []}; + // I could use a proper combinatorics algorithm here... but it would be more code to + // write one, and we don't seem to have one in our existing libraries, so massively nested + // for loop it is + const totalRuns = choose(rotors.length, 3) * 6 * fourthRotors.length * reflectors.length; + let nRuns = 0; + let nStops = 0; + const start = Date.now(); + for (const rotor1 of rotors) { + for (const rotor2 of rotors) { + if (rotor2 === rotor1) { + continue; + } + for (const rotor3 of rotors) { + if (rotor3 === rotor2 || rotor3 === rotor1) { + continue; + } + for (const rotor4 of fourthRotors) { + for (const reflector of reflectors) { + nRuns++; + const runRotors = [rotor1, rotor2, rotor3]; + if (rotor4 !== "") { + runRotors.push(rotor4); + } + if (bombe === undefined) { + bombe = new BombeMachine(runRotors, reflector, ciphertext, crib, check); + output.nLoops = bombe.nLoops; + } else { + bombe.changeRotors(runRotors, reflector); + } + const result = bombe.run(); + nStops += result.length; + if (update !== undefined) { + update(bombe.nLoops, nStops, nRuns / totalRuns, start); + } + if (result.length > 0) { + output.bombeRuns.push({ + rotors: runRotors, + reflector: reflector.pairs, + result: result + }); + } + } + } + } + } + } + return output; + } + + + /** + * Displays the MultiBombe results in an HTML table + * + * @param {Object} output + * @param {number} output.nLoops + * @param {Array[]} output.result + * @returns {html} + */ + present(output) { + let html = `Bombe run on menu with ${output.nLoops} loop${output.nLoops === 1 ? "" : "s"} (2+ desirable). Note: Rotors and rotor positions are listed left to right, ignore stepping and the ring setting, and positions start at the beginning of the crib. Some plugboard settings are determined. A decryption preview starting at the beginning of the crib and ignoring stepping is also provided.\n`; + + for (const run of output.bombeRuns) { + html += `\nRotors: ${run.rotors.slice().reverse().join(", ")}\nReflector: ${run.reflector}\n`; + html += "\n"; + for (const [setting, stecker, decrypt] of run.result) { + html += `\n`; + } + html += "
Rotor stops Partial plugboard Decryption preview
${setting} ${stecker} ${decrypt}
\n"; + } + return html; + } +} + +export default MultipleBombe; diff --git a/plugins/srktoolbox/src/core/operations/Multiply.mjs b/plugins/srktoolbox/src/core/operations/Multiply.mjs new file mode 100644 index 00000000..f6a2da1c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Multiply.mjs @@ -0,0 +1,54 @@ +/** + * @author bwhitn [brian.m.whitney@outlook.com] + * @author d98762625 [d98762625@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import BigNumber from "bignumber.js"; +import Operation from "../Operation.mjs"; +import { multi, createNumArray } from "../lib/Arithmetic.mjs"; +import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs"; + + +/** + * Multiply operation + */ +class Multiply extends Operation { + + /** + * Multiply constructor + */ + constructor() { + super(); + + this.name = "求积"; + this.module = "Default"; + this.description = "对一组数字求积(aka. 乘法)。非数字的值会被忽略。

例: 0x0a 8 .5 计算为 40"; + this.infoURL = "https://wikipedia.org/wiki/Multiplication"; + this.inputType = "string"; + this.outputType = "BigNumber"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": ARITHMETIC_DELIM_OPTIONS, + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {BigNumber} + */ + run(input, args) { + const val = multi(createNumArray(input, args[0])); + return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN); + } + +} + +export default Multiply; diff --git a/plugins/srktoolbox/src/core/operations/MurmurHash3.mjs b/plugins/srktoolbox/src/core/operations/MurmurHash3.mjs new file mode 100644 index 00000000..12dd3518 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/MurmurHash3.mjs @@ -0,0 +1,141 @@ +/** + * Based on murmurhash-js (https://github.com/garycourt/murmurhash-js) + * @author Gary Court + * @license MIT + * + * @author AliceGrey [alice@grey.systems] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * MurmurHash3 operation + */ +class MurmurHash3 extends Operation { + + /** + * MurmurHash3 constructor + */ + constructor() { + super(); + + this.name = "MurmurHash3"; + this.module = "Hashing"; + this.description = "对给定的输入字符串(可自选种子)生成对应的MurmurHash v3哈希。"; + this.infoURL = "https://wikipedia.org/wiki/MurmurHash"; + this.inputType = "string"; + this.outputType = "number"; + this.args = [ + { + name: "种子", + type: "number", + value: 0 + }, + { + name: "转换为有符号数值", + type: "boolean", + value: false + } + ]; + } + + /** + * Calculates the MurmurHash3 hash of the input. + * Based on Gary Court's JS MurmurHash implementation + * @see http://github.com/garycourt/murmurhash-js + * @author AliceGrey [alice@grey.systems] + * @param {string} input ASCII only + * @param {number} seed Positive integer only + * @return {number} 32-bit positive integer hash + */ + mmh3(input, seed) { + let h1b; + let k1; + const remainder = input.length & 3; // input.length % 4 + const bytes = input.length - remainder; + let h1 = seed; + const c1 = 0xcc9e2d51; + const c2 = 0x1b873593; + let i = 0; + + while (i < bytes) { + k1 = + ((input.charCodeAt(i) & 0xff)) | + ((input.charCodeAt(++i) & 0xff) << 8) | + ((input.charCodeAt(++i) & 0xff) << 16) | + ((input.charCodeAt(++i) & 0xff) << 24); + ++i; + + k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff; + + h1 ^= k1; + h1 = (h1 << 13) | (h1 >>> 19); + h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff; + h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16)); + } + + k1 = 0; + + if (remainder === 3) { + k1 ^= (input.charCodeAt(i + 2) & 0xff) << 16; + } + + if (remainder === 3 || remainder === 2) { + k1 ^= (input.charCodeAt(i + 1) & 0xff) << 8; + } + + if (remainder === 3 || remainder === 2 || remainder === 1) { + k1 ^= (input.charCodeAt(i) & 0xff); + + k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff; + h1 ^= k1; + } + + h1 ^= input.length; + + h1 ^= h1 >>> 16; + h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff; + h1 ^= h1 >>> 13; + h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff; + h1 ^= h1 >>> 16; + + return h1 >>> 0; + } + + /** + * Converts an unsigned 32-bit integer to a signed 32-bit integer + * @author AliceGrey [alice@grey.systems] + * @param {value} 32-bit unsigned integer + * @return {number} 32-bit signed integer + */ + unsignedToSigned(value) { + return value & 0x80000000 ? -0x100000000 + value : value; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {number} + */ + run(input, args) { + if (args && args.length >= 1) { + const seed = args[0]; + const hash = this.mmh3(input, seed); + if (args.length > 1 && args[1]) { + return this.unsignedToSigned(hash); + } + return hash; + } + return this.mmh3(input); + } +} + +export default MurmurHash3; diff --git a/plugins/srktoolbox/src/core/operations/NOT.mjs b/plugins/srktoolbox/src/core/operations/NOT.mjs new file mode 100644 index 00000000..9aaa71a1 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/NOT.mjs @@ -0,0 +1,70 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { bitOp, not } from "../lib/BitwiseOp.mjs"; + +/** + * NOT operation + */ +class NOT extends Operation { + + /** + * NOT constructor + */ + constructor() { + super(); + + this.name = "NOT"; + this.module = "Default"; + this.description = "对每个字节取反。"; + this.infoURL = "https://wikipedia.org/wiki/Bitwise_operation#NOT"; + this.inputType = "ArrayBuffer"; + this.outputType = "byteArray"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + input = new Uint8Array(input); + return bitOp(input, null, not); + } + + /** + * Highlight NOT + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight NOT in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default NOT; diff --git a/plugins/srktoolbox/src/core/operations/NTHash.mjs b/plugins/srktoolbox/src/core/operations/NTHash.mjs new file mode 100644 index 00000000..1a418fb3 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/NTHash.mjs @@ -0,0 +1,50 @@ +/** + * @author brun0ne [brunonblok@gmail.com] + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * NT Hash operation + */ +class NTHash extends Operation { + + /** + * NTHash constructor + */ + constructor() { + super(); + + this.name = "NT哈希"; + this.module = "Crypto"; + this.description = "NT哈希,有时又叫NTLM哈希,是Windows系统用于存储密码的一种方法。原理为在UTF-16LE编码的输入上执行MD4。由于NTLM哈希在现代硬件设备上非常容易被暴力破解,目前认为其安全性较弱。"; + this.infoURL = "https://wikipedia.org/wiki/NT_LAN_Manager"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + // Convert to UTF-16LE + const buf = new ArrayBuffer(input.length * 2); + const bufView = new Uint16Array(buf); + for (let i = 0; i < input.length; i++) { + bufView[i] = input.charCodeAt(i); + } + + const hashed = runHash("md4", buf); + return hashed.toUpperCase(); + } +} + +export default NTHash; diff --git a/plugins/srktoolbox/src/core/operations/NormaliseImage.mjs b/plugins/srktoolbox/src/core/operations/NormaliseImage.mjs new file mode 100644 index 00000000..8a06d10d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/NormaliseImage.mjs @@ -0,0 +1,85 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { Jimp, JimpMime } from "jimp"; + +/** + * Normalise Image operation + */ +class NormaliseImage extends Operation { + /** + * NormaliseImage constructor + */ + constructor() { + super(); + + this.name = "图像归一化"; + this.module = "Image"; + this.description = "图像色彩归一化(Normalize)。"; + this.infoURL = ""; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + async run(input, args) { + if (!isImage(input)) { + throw new OperationError("无效的文件类型。"); + } + + let image; + try { + image = await Jimp.read(input); + } catch (err) { + throw new OperationError(`打开图像文件出错:(${err})`); + } + + try { + image.normalize(); + + let imageBuffer; + if (image.mime === "image/gif") { + imageBuffer = await image.getBuffer(JimpMime.png); + } else { + imageBuffer = await image.getBuffer(image.mime); + } + return imageBuffer.buffer; + } catch (err) { + throw new OperationError(`归一化图像出错:(${err})`); + } + } + + /** + * Displays the normalised image using HTML for web apps + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const dataArray = new Uint8Array(data); + + const type = isImage(dataArray); + if (!type) { + throw new OperationError("无效的文件类型。"); + } + + return ``; + } +} + +export default NormaliseImage; diff --git a/plugins/srktoolbox/src/core/operations/NormaliseUnicode.mjs b/plugins/srktoolbox/src/core/operations/NormaliseUnicode.mjs new file mode 100644 index 00000000..429df3d3 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/NormaliseUnicode.mjs @@ -0,0 +1,64 @@ +/** + * @author Matthieu [m@tthieu.xyz] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {UNICODE_NORMALISATION_FORMS} from "../lib/ChrEnc.mjs"; +import unorm from "unorm"; + +/** + * Normalise Unicode operation + */ +class NormaliseUnicode extends Operation { + + /** + * NormaliseUnicode constructor + */ + constructor() { + super(); + + this.name = "Unicode正规化"; + this.module = "Encodings"; + this.description = "按照选定的正规形式对Unicode字符执行正规化操作。"; + this.infoURL = "https://wikipedia.org/wiki/Unicode_equivalence#Normal_forms"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "正规形式", + type: "option", + value: UNICODE_NORMALISATION_FORMS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [normalForm] = args; + + switch (normalForm) { + case "NFD": + return unorm.nfd(input); + case "NFC": + return unorm.nfc(input); + case "NFKD": + return unorm.nfkd(input); + case "NFKC": + return unorm.nfkc(input); + default: + throw new OperationError("未知的正规形式"); + } + } + +} + +export default NormaliseUnicode; diff --git a/plugins/srktoolbox/src/core/operations/Numberwang.mjs b/plugins/srktoolbox/src/core/operations/Numberwang.mjs new file mode 100644 index 00000000..7f94e360 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Numberwang.mjs @@ -0,0 +1,101 @@ +/** + * @author Unknown Male 282 + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; + +/** + * Numberwang operation. Remain indoors. + */ +class Numberwang extends Operation { + + /** + * Numberwang constructor + */ + constructor() { + super(); + + this.name = "Numberwang"; + this.module = "Default"; + this.description = "Based on the popular gameshow by Mitchell and Webb."; + this.infoURL = "https://wikipedia.org/wiki/That_Mitchell_and_Webb_Look#Recurring_sketches"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let output; + if (!input) { + output = "Let's play Wangernumb!"; + } else { + const match = input.match(/(f0rty-s1x|shinty-six|filth-hundred and neeb|-?√?\d+(\.\d+)?i?([a-z]?)%?)/i); + if (match) { + if (match[3]) output = match[0] + "! That's AlphaNumericWang!"; + else output = match[0] + "! That's Numberwang!"; + } else { + // That's a bad miss! + output = "Sorry, that's not Numberwang. Let's rotate the board!"; + } + } + + const rand = Math.floor(Math.random() * didYouKnow.length); + return output + "\n\nDid you know: " + didYouKnow[rand]; + } + +} + +/** + * Taken from http://numberwang.wikia.com/wiki/Numberwang_Wikia + * + * @constant + */ +const didYouKnow = [ + "Numberwang, contrary to popular belief, is a fruit and not a vegetable.", + "Robert Webb once got WordWang while presenting an episode of Numberwang.", + "The 6705th digit of pi is Numberwang.", + "Numberwang was invented on a Sevenday.", + "Contrary to popular belief, Albert Einstein always got good grades in Numberwang at school. He once scored ^4$ on a test.", + "680 asteroids have been named after Numberwang.", + "Archimedes is most famous for proclaiming \"That's Numberwang!\" during an epiphany about water displacement he had while taking a bath.", + "Numberwang Day is celebrated in Japan on every day of the year apart from June 6.", + "Biologists recently discovered Numberwang within a strand of human DNA.", + "Numbernot is a special type of non-Numberwang number. It is divisible by 3 and the letter \"y\".", + "Julie once got 612.04 Numberwangs in a single episode of Emmerdale.", + "In India, it is traditional to shout out \"Numberwang!\" instead of checkmate during games of chess.", + "There is a rule on Countdown which states that if you get Numberwang in the numbers round, you automatically win. It has only ever been invoked twice.", + "\"Numberwang\" was the third-most common baby name for a brief period in 1722.", + "\"The Lion King\" was loosely based on Numberwang.", + "\"A Numberwang a day keeps the doctor away\" is how Donny Cosy, the oldest man in the world, explained how he was in such good health at the age of 136.", + "The \"number lock\" button on a keyboard is based on the popular round of the same name in \"Numberwang\".", + "Cambridge became the first university to offer a course in Numberwang in 1567.", + "Schrödinger's Numberwang is a number that has been confusing dentists for centuries.", + "\"Harry Potter and the Numberwang of Numberwang\" was rejected by publishers -41 times before it became a bestseller.", + "\"Numberwang\" is the longest-running British game show in history; it has aired 226 seasons, each containing 19 episodes, which makes a grand total of 132 episodes.", + "The triple Numberwang bonus was discovered by archaeologist Thomas Jefferson in Somerset.", + "Numberwang is illegal in parts of Czechoslovakia.", + "Numberwang was discovered in India in the 12th century.", + "Numberwang has the chemical formula Zn4SO2(HgEs)3.", + "The first pack of cards ever created featured two \"Numberwang\" cards instead of jokers.", + "Julius Caesar was killed by an overdose of Numberwang.", + "The most Numberwang musical note is G#.", + "In 1934, the forty-third Google Doodle promoted the upcoming television show \"Numberwang on Ice\".", + "A recent psychology study found that toddlers were 17% faster at identifying numbers which were Numberwang.", + "There are 700 ways to commit a foul in the television show \"Numberwang\". All 700 of these fouls were committed by Julie in one single episode in 1473.", + "Astronomers suspect God is Numberwang.", + "Numberwang is the official beverage of Canada.", + "In the pilot episode of \"The Price is Right\", if a contestant got the value of an item exactly right they were told \"That's Numberwang!\" and immediately won ₹5.7032.", + "The first person to get three Numberwangs in a row was Madonna.", + "\"Numberwang\" has the code U+46402 in Unicode.", + "The musical note \"Numberwang\" is between D# and E♮.", + "Numberwang was first played on the moon in 1834.", +]; + +export default Numberwang; diff --git a/plugins/srktoolbox/src/core/operations/OR.mjs b/plugins/srktoolbox/src/core/operations/OR.mjs new file mode 100644 index 00000000..5c11e2a5 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/OR.mjs @@ -0,0 +1,80 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import { bitOp, or, BITWISE_OP_DELIMS } from "../lib/BitwiseOp.mjs"; + +/** + * OR operation + */ +class OR extends Operation { + + /** + * OR constructor + */ + constructor() { + super(); + + this.name = "OR"; + this.module = "Default"; + this.description = "使用给定的Key对输入进行OR(按位或)运算
e.g. fe023da5"; + this.infoURL = "https://wikipedia.org/wiki/Bitwise_operation#OR"; + this.inputType = "ArrayBuffer"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "Key", + "type": "toggleString", + "value": "", + "toggleValues": BITWISE_OP_DELIMS + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const key = Utils.convertToByteArray(args[0].string || "", args[0].option); + input = new Uint8Array(input); + + return bitOp(input, key, or); + } + + /** + * Highlight OR + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight OR in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default OR; diff --git a/plugins/srktoolbox/src/core/operations/ObjectIdentifierToHex.mjs b/plugins/srktoolbox/src/core/operations/ObjectIdentifierToHex.mjs new file mode 100644 index 00000000..47f671ff --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ObjectIdentifierToHex.mjs @@ -0,0 +1,43 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import r from "jsrsasign"; +import Operation from "../Operation.mjs"; + +/** + * Object Identifier to Hex operation + */ +class ObjectIdentifierToHex extends Operation { + + /** + * ObjectIdentifierToHex constructor + */ + constructor() { + super(); + + this.name = "OID转十六进制"; + this.module = "PublicKey"; + this.description = "把对象标识符(object identifier,OID)转换成对应的十六进制字符串。"; + this.infoURL = "https://wikipedia.org/wiki/Object_identifier"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return r.KJUR.asn1.ASN1Util.oidIntToHex(input); + } + +} + +export default ObjectIdentifierToHex; diff --git a/plugins/srktoolbox/src/core/operations/OffsetChecker.mjs b/plugins/srktoolbox/src/core/operations/OffsetChecker.mjs new file mode 100644 index 00000000..e7cabc24 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/OffsetChecker.mjs @@ -0,0 +1,109 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Offset checker operation + */ +class OffsetChecker extends Operation { + + /** + * OffsetChecker constructor + */ + constructor() { + super(); + + this.name = "偏移检测"; + this.module = "Default"; + this.description = "高亮显示在所有给定内容中位置相同的字符,多个输入由给定的分隔符分隔。"; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + "name": "分隔符", + "type": "binaryString", + "value": "\\n\\n" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const sampleDelim = args[0], + samples = input.split(sampleDelim), + outputs = new Array(samples.length); + let i = 0, + s = 0, + match = false, + inMatch = false, + chr; + + if (!samples || samples.length < 2) { + throw new OperationError("内容不足,至少需要两组文本,请添加更多内容或重新选择分隔符。"); + } + + // Initialise output strings + outputs.fill("", 0, samples.length); + + // Loop through each character in the first sample + for (i = 0; i < samples[0].length; i++) { + chr = samples[0][i]; + match = false; + + // Loop through each sample to see if the chars are the same + for (s = 1; s < samples.length; s++) { + if (samples[s][i] !== chr) { + match = false; + break; + } + match = true; + } + + // Write output for each sample + for (s = 0; s < samples.length; s++) { + if (samples[s].length <= i) { + if (inMatch) outputs[s] += ""; + if (s === samples.length - 1) inMatch = false; + continue; + } + + if (match && !inMatch) { + outputs[s] += "" + Utils.escapeHtml(samples[s][i]); + if (samples[s].length === i + 1) outputs[s] += ""; + if (s === samples.length - 1) inMatch = true; + } else if (!match && inMatch) { + outputs[s] += "" + Utils.escapeHtml(samples[s][i]); + if (s === samples.length - 1) inMatch = false; + } else { + outputs[s] += Utils.escapeHtml(samples[s][i]); + if (inMatch && samples[s].length === i + 1) { + outputs[s] += ""; + if (samples[s].length - 1 !== i) inMatch = false; + } + } + + if (samples[0].length - 1 === i) { + if (inMatch) outputs[s] += ""; + outputs[s] += Utils.escapeHtml(samples[s].substring(i + 1)); + } + } + } + + return outputs.join(sampleDelim); + } + +} + +export default OffsetChecker; diff --git a/plugins/srktoolbox/src/core/operations/OpticalCharacterRecognition.mjs b/plugins/srktoolbox/src/core/operations/OpticalCharacterRecognition.mjs new file mode 100644 index 00000000..ee586f61 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/OpticalCharacterRecognition.mjs @@ -0,0 +1,98 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @author mshwed [m@ttshwed.com] + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; + +import { createWorker } from "tesseract.js"; + +const OEM_MODES = ["Tesseract only", "LSTM only", "Tesseract/LSTM Combined"]; + +/** + * Optical Character Recognition operation + */ +class OpticalCharacterRecognition extends Operation { + + /** + * OpticalCharacterRecognition constructor + */ + constructor() { + super(); + + this.name = "光学字符识别"; + this.module = "OCR"; + this.description = "光学字符识别(英语:Optical Character Recognition,OCR)是指对文本资料的图像文件进行分析识别处理,获取文字及版面信息的过程。

目前仅支持识别英文。

支持的图像格式:png、 jpg、bmp、pbm。"; + this.infoURL = "https://wikipedia.org/wiki/Optical_character_recognition"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "显示置信度", + type: "boolean", + value: true + }, + { + name: "OCR Engine Mode", + type: "option", + value: OEM_MODES, + defaultIndex: 1 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const [showConfidence, oemChoice] = args; + + if (!isWorkerEnvironment()) throw new OperationError("此操作仅支持在浏览器运行"); + + const type = isImage(input); + if (!type) { + throw new OperationError("不支持的文件格式(仅支持:jpg、png、pbm、bmp)或未提供文件"); + } + + const assetDir = `${self.docURL}/assets/`; + const oem = OEM_MODES.indexOf(oemChoice); + + try { + self.sendStatusMessage("启动Tesseract worker……"); + const image = `data:${type};base64,${toBase64(input)}`; + const worker = await createWorker("eng", oem, { + workerPath: `${assetDir}tesseract/worker.min.js`, + langPath: `${assetDir}tesseract/lang-data`, + corePath: `${assetDir}tesseract/tesseract-core.wasm.js`, + logger: progress => { + if (isWorkerEnvironment()) { + self.sendStatusMessage(`状态: ${progress.status}${progress.status === "recognizing text" ? ` - ${(parseFloat(progress.progress)*100).toFixed(2)}%`: "" }`); + } + } + }); + self.sendStatusMessage("识别文本……"); + const result = await worker.recognize(image); + + if (showConfidence) { + return `置信度 ${result.data.confidence}%\n\n${result.data.text}`; + } else { + return result.data.text; + } + } catch (err) { + throw new OperationError(`OCR时报错:(${err})`); + } + } +} + +export default OpticalCharacterRecognition; diff --git a/plugins/srktoolbox/src/core/operations/PEMToHex.mjs b/plugins/srktoolbox/src/core/operations/PEMToHex.mjs new file mode 100644 index 00000000..b5f35991 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PEMToHex.mjs @@ -0,0 +1,70 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @author cplussharp + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import { fromBase64 } from "../lib/Base64.mjs"; +import { toHexFast } from "../lib/Hex.mjs"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * PEM to Hex operation + */ +class PEMToHex extends Operation { + + /** + * PEMToHex constructor + */ + constructor() { + super(); + + this.name = "PEM转十六进制"; + this.module = "Default"; + this.description = "把PEM(Privacy Enhanced Mail)格式转换成十六进制DER(Distinguished Encoding Rules)格式字符串。"; + this.infoURL = "https://wikipedia.org/wiki/Privacy-Enhanced_Mail#Format"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + this.checks = [ + { + "pattern": "----BEGIN ([A-Z][A-Z ]+[A-Z])-----", + "args": [] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const output = []; + let match; + const regex = /-----BEGIN ([A-Z][A-Z ]+[A-Z])-----/g; + while ((match = regex.exec(input)) !== null) { + // find corresponding end tag + const indexBase64 = match.index + match[0].length; + const footer = `-----END ${match[1]}-----`; + const indexFooter = input.indexOf(footer, indexBase64); + if (indexFooter === -1) { + throw new OperationError(`PEM footer '${footer}' not found`); + } + + // decode base64 content + const base64 = input.substring(indexBase64, indexFooter); + const bytes = fromBase64(base64, "A-Za-z0-9+/=", "byteArray", true); + const hex = toHexFast(bytes); + output.push(hex); + } + return output.join("\n"); + } + +} + +export default PEMToHex; diff --git a/plugins/srktoolbox/src/core/operations/PEMToJWK.mjs b/plugins/srktoolbox/src/core/operations/PEMToJWK.mjs new file mode 100644 index 00000000..ab58ad5e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PEMToJWK.mjs @@ -0,0 +1,90 @@ +/** + * @author cplussharp + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import r from "jsrsasign"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * PEM to JWK operation + */ +class PEMToJWK extends Operation { + + /** + * PEMToJWK constructor + */ + constructor() { + super(); + + this.name = "PEM转JWK"; + this.module = "PublicKey"; + this.description = "将PEM格式转换为JSON Web Key格式。"; + this.infoURL = "https://datatracker.ietf.org/doc/html/rfc7517"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + this.checks = [ + { + "pattern": "-----BEGIN ((RSA |EC )?(PRIVATE|PUBLIC) KEY|CERTIFICATE)-----", + "args": [] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let output = ""; + let match; + const regex = /-----BEGIN ([A-Z][A-Z ]+[A-Z])-----/g; + while ((match = regex.exec(input)) !== null) { + // find corresponding end tag + const indexBase64 = match.index + match[0].length; + const header = input.substring(match.index, indexBase64); + const footer = `-----END ${match[1]}-----`; + const indexFooter = input.indexOf(footer, indexBase64); + if (indexFooter === -1) { + throw new OperationError(`未找到PEM footer '${footer}'`); + } + + const pem = input.substring(match.index, indexFooter + footer.length); + if (match[1].indexOf("KEY") !== -1) { + if (header === "-----BEGIN RSA PUBLIC KEY-----") { + throw new OperationError("不支持的RSA公钥格式。仅支持PKCS#8。"); + } + + const key = r.KEYUTIL.getKey(pem); + if (key.type === "DSA") { + throw new OperationError("JWK不支持DSA密钥。"); + } + const jwk = r.KEYUTIL.getJWKFromKey(key); + if (output.length > 0) { + output += "\n"; + } + output += JSON.stringify(jwk); + } else if (match[1] === "CERTIFICATE") { + const cert = new r.X509(); + cert.readCertPEM(pem); + const key = cert.getPublicKey(); + const jwk = r.KEYUTIL.getJWKFromKey(key); + if (output.length > 0) { + output += "\n"; + } + output += JSON.stringify(jwk); + } else { + throw new OperationError(`不支持的PEM类型'${match[1]}'`); + } + } + return output; + } +} + +export default PEMToJWK; diff --git a/plugins/srktoolbox/src/core/operations/PGPDecrypt.mjs b/plugins/srktoolbox/src/core/operations/PGPDecrypt.mjs new file mode 100644 index 00000000..90fb5c1e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PGPDecrypt.mjs @@ -0,0 +1,89 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import kbpgp from "kbpgp"; +import { ASP, importPrivateKey } from "../lib/PGP.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import * as es6promisify from "es6-promisify"; +const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify; + +/** + * PGP Decrypt operation + */ +class PGPDecrypt extends Operation { + + /** + * PGPDecrypt constructor + */ + constructor() { + super(); + + this.name = "PGP解密"; + this.module = "PGP"; + this.description = [ + "输入:你想要解密的经过ASCII-armour处理的PGP信息。", + "

", + "参数:经过ASCII-armour处理的接收者PGP私钥。", + "(如果有口令的话还需要填写口令)", + "

", + "PGP(英语:Pretty Good Privacy,直译:优良保密协议)是一套用于讯息加密、验证的应用程序。", + "

", + "此操作使用Keybase实现的PGP。", + ].join("\n"); + this.infoURL = "https://wikipedia.org/wiki/Pretty_Good_Privacy"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "接收者私钥", + "type": "text", + "value": "" + }, + { + "name": "私钥口令", + "type": "string", + "value": "" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + * + * @throws {OperationError} if invalid private key + */ + async run(input, args) { + const encryptedMessage = input, + [privateKey, passphrase] = args, + keyring = new kbpgp.keyring.KeyRing(); + let plaintextMessage; + + if (!privateKey) throw new OperationError("请输入接收者的私钥"); + + const key = await importPrivateKey(privateKey, passphrase); + keyring.add_key_manager(key); + + try { + plaintextMessage = await promisify(kbpgp.unbox)({ + armored: encryptedMessage, + keyfetch: keyring, + asp: ASP + }); + } catch (err) { + throw new OperationError(`无法使用提供的私钥解密: ${err}`); + } + + return plaintextMessage.toString(); + } + +} + +export default PGPDecrypt; diff --git a/plugins/srktoolbox/src/core/operations/PGPDecryptAndVerify.mjs b/plugins/srktoolbox/src/core/operations/PGPDecryptAndVerify.mjs new file mode 100644 index 00000000..eaabb5f5 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PGPDecryptAndVerify.mjs @@ -0,0 +1,126 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import kbpgp from "kbpgp"; +import { ASP, importPrivateKey, importPublicKey } from "../lib/PGP.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import * as es6promisify from "es6-promisify"; +const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify; + +/** + * PGP Decrypt and Verify operation + */ +class PGPDecryptAndVerify extends Operation { + + /** + * PGPDecryptAndVerify constructor + */ + constructor() { + super(); + + this.name = "PGP解密并验证"; + this.module = "PGP"; + this.description = [ + "输入:你想要验证的经过ASCII-armour处理的PGP信息。", + "

", + "参数:经过ASCII-armour处理的签名者PGP公钥", + "和经过ASCII-armour处理的接收者PGP私钥(以及口令,如果有)。", + "

", + "此操作用PGP来解密并验证数字签名。", + "

", + "PGP(英语:Pretty Good Privacy,直译:优良保密协议)是一套用于讯息加密、验证的应用程序。", + "

", + "此操作使用Keybase实现的PGP。", + ].join("\n"); + this.infoURL = "https://wikipedia.org/wiki/Pretty_Good_Privacy"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "签名者公钥", + "type": "text", + "value": "" + }, + { + "name": "接收者私钥", + "type": "text", + "value": "" + }, + { + "name": "私钥口令", + "type": "string", + "value": "" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const signedMessage = input, + [publicKey, privateKey, passphrase] = args, + keyring = new kbpgp.keyring.KeyRing(); + let unboxedLiterals; + + if (!publicKey) throw new OperationError("请输入签名者公钥。"); + if (!privateKey) throw new OperationError("请输入接收者私钥。"); + const privKey = await importPrivateKey(privateKey, passphrase); + const pubKey = await importPublicKey(publicKey); + keyring.add_key_manager(privKey); + keyring.add_key_manager(pubKey); + + try { + unboxedLiterals = await promisify(kbpgp.unbox)({ + armored: signedMessage, + keyfetch: keyring, + asp: ASP + }); + const ds = unboxedLiterals[0].get_data_signer(); + if (ds) { + const km = ds.get_key_manager(); + if (km) { + const signer = km.get_userids_mark_primary()[0].components; + let text = "签名: "; + if (signer.email || signer.username || signer.comment) { + if (signer.username) { + text += `${signer.username} `; + } + if (signer.comment) { + text += `(${signer.comment}) `; + } + if (signer.email) { + text += `<${signer.email}>`; + } + text += "\n"; + } + text += [ + `PGP key ID:${km.get_pgp_short_key_id()}`, + `PGP指纹:${km.get_pgp_fingerprint().toString("hex")}`, + `签名时间: ${new Date(ds.sig.when_generated() * 1000).toUTCString()}`, + "----------------------------------\n" + ].join("\n"); + text += unboxedLiterals.toString(); + return text.trim(); + } else { + throw new OperationError("Could not identify a key manager."); + } + } else { + throw new OperationError("数据似乎未被签名。"); + } + } catch (err) { + throw new OperationError(`无法验证消息: ${err}`); + } + } + +} + +export default PGPDecryptAndVerify; diff --git a/plugins/srktoolbox/src/core/operations/PGPEncrypt.mjs b/plugins/srktoolbox/src/core/operations/PGPEncrypt.mjs new file mode 100644 index 00000000..1346e54f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PGPEncrypt.mjs @@ -0,0 +1,81 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import kbpgp from "kbpgp"; +import { ASP, importPublicKey } from "../lib/PGP.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import * as es6promisify from "es6-promisify"; +const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify; + +/** + * PGP Encrypt operation + */ +class PGPEncrypt extends Operation { + + /** + * PGPEncrypt constructor + */ + constructor() { + super(); + + this.name = "PGP加密"; + this.module = "PGP"; + this.description = [ + "输入:你想要加密的信息。", + "

", + "参数:经过ASCII-armour处理的接收者PGP公钥。", + "

", + "PGP(英语:Pretty Good Privacy,直译:优良保密协议)是一套用于讯息加密、验证的应用程序。", + "

", + "此操作使用Keybase实现的PGP。", + ].join("\n"); + this.infoURL = "https://wikipedia.org/wiki/Pretty_Good_Privacy"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "接收者公钥", + "type": "text", + "value": "" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + * + * @throws {OperationError} if failed private key import or failed encryption + */ + async run(input, args) { + const plaintextMessage = input, + plainPubKey = args[0]; + let encryptedMessage; + + if (!plainPubKey) throw new OperationError("请输入接收者的公钥"); + + const key = await importPublicKey(plainPubKey); + + try { + encryptedMessage = await promisify(kbpgp.box)({ + "msg": plaintextMessage, + "encrypt_for": key, + "asp": ASP + }); + } catch (err) { + throw new OperationError(`无法使用提供的公钥加密: ${err}`); + } + + return encryptedMessage.toString(); + } + +} + +export default PGPEncrypt; diff --git a/plugins/srktoolbox/src/core/operations/PGPEncryptAndSign.mjs b/plugins/srktoolbox/src/core/operations/PGPEncryptAndSign.mjs new file mode 100644 index 00000000..0eb24437 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PGPEncryptAndSign.mjs @@ -0,0 +1,96 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import kbpgp from "kbpgp"; +import { ASP, importPrivateKey, importPublicKey } from "../lib/PGP.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import * as es6promisify from "es6-promisify"; +const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify; + +/** + * PGP Encrypt and Sign operation + */ +class PGPEncryptAndSign extends Operation { + + /** + * PGPEncryptAndSign constructor + */ + constructor() { + super(); + + this.name = "PGP加密并签名"; + this.module = "PGP"; + this.description = [ + "输入:你想要签名的明文内容。", + "

", + "参数:经过ASCII-armour处理的签名者私钥(以及口令,如果有)", + "经过ASCII-armour处理的接收者公钥。", + "

", + "此操作用PGP产生加密的数字签名。", + "

", + "PGP(英语:Pretty Good Privacy,直译:优良保密协议)是一套用于讯息加密、验证的应用程序。", + "

", + "此操作使用Keybase实现的PGP。", + ].join("\n"); + this.infoURL = "https://wikipedia.org/wiki/Pretty_Good_Privacy"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "签名者私钥", + "type": "text", + "value": "" + }, + { + "name": "私钥口令", + "type": "string", + "value": "" + }, + { + "name": "接收者公钥", + "type": "text", + "value": "" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + * + * @throws {OperationError} if failure to sign message + */ + async run(input, args) { + const message = input, + [privateKey, passphrase, publicKey] = args; + let signedMessage; + + if (!privateKey) throw new OperationError("请输入签名者私钥。"); + if (!publicKey) throw new OperationError("请输入接收者公钥。"); + const privKey = await importPrivateKey(privateKey, passphrase); + const pubKey = await importPublicKey(publicKey); + + try { + signedMessage = await promisify(kbpgp.box)({ + "msg": message, + "encrypt_for": pubKey, + "sign_with": privKey, + "asp": ASP + }); + } catch (err) { + throw new OperationError(`无法给消息签名: ${err}`); + } + + return signedMessage; + } + +} + +export default PGPEncryptAndSign; diff --git a/plugins/srktoolbox/src/core/operations/PGPVerify.mjs b/plugins/srktoolbox/src/core/operations/PGPVerify.mjs new file mode 100644 index 00000000..4c46e259 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PGPVerify.mjs @@ -0,0 +1,113 @@ +/** + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +import kbpgp from "kbpgp"; +import { ASP, importPublicKey } from "../lib/PGP.mjs"; +import * as es6promisify from "es6-promisify"; +const promisify = es6promisify.default ? es6promisify.default.promisify : es6promisify.promisify; + +/** + * PGP Verify operation + */ +class PGPVerify extends Operation { + + /** + * PGPVerify constructor + */ + constructor() { + super(); + + this.name = "PGP验证"; + this.module = "PGP"; + this.description = [ + "输入:你想要验证的经过ASCII-armour处理的PGP信息。", + "

", + "参数:经过ASCII-armour处理的签名者PGP公钥。", + "

", + "此操作解密使用clearsign参数生成的PGP信息", + "

", + "PGP(英语:Pretty Good Privacy,直译:优良保密协议)是一套用于讯息加密、验证的应用程序。", + "

", + "此操作使用Keybase实现的PGP。", + ].join("\n"); + this.infoURL = "https://wikipedia.org/wiki/Pretty_Good_Privacy"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "签名者公钥", + "type": "text", + "value": "" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const signedMessage = input, + [publicKey] = args, + keyring = new kbpgp.keyring.KeyRing(); + let unboxedLiterals; + + if (!publicKey) throw new OperationError("请输入签名者的公钥"); + const pubKey = await importPublicKey(publicKey); + keyring.add_key_manager(pubKey); + + try { + unboxedLiterals = await promisify(kbpgp.unbox)({ + armored: signedMessage, + keyfetch: keyring, + asp: ASP + }); + const ds = unboxedLiterals[0].get_data_signer(); + if (ds) { + const km = ds.get_key_manager(); + if (km) { + const signer = km.get_userids_mark_primary()[0].components; + let text = "签名:"; + if (signer.email || signer.username || signer.comment) { + if (signer.username) { + text += `${signer.username} `; + } + if (signer.comment) { + text += `(${signer.comment}) `; + } + if (signer.email) { + text += `<${signer.email}>`; + } + text += "\n"; + } + text += [ + `PGP key ID: ${km.get_pgp_short_key_id()}`, + `PGP指纹: ${km.get_pgp_fingerprint().toString("hex")}`, + `签名日期: ${new Date(ds.sig.when_generated() * 1000).toUTCString()}`, + "----------------------------------\n" + ].join("\n"); + text += unboxedLiterals.toString(); + return text.trim(); + } else { + throw new OperationError("Could not identify a key manager."); + } + } else { + throw new OperationError("数据似乎未签名"); + } + } catch (err) { + throw new OperationError(`无法验证消息: ${err}`); + } + } + +} + +export default PGPVerify; diff --git a/plugins/srktoolbox/src/core/operations/PHPDeserialize.mjs b/plugins/srktoolbox/src/core/operations/PHPDeserialize.mjs new file mode 100644 index 00000000..2daaf216 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PHPDeserialize.mjs @@ -0,0 +1,173 @@ +/** + * @author Jarmo van Lenthe [github.com/jarmovanlenthe] + * @copyright Jarmo van Lenthe + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * PHP Deserialize operation + */ +class PHPDeserialize extends Operation { + + /** + * PHPDeserialize constructor + */ + constructor() { + super(); + + this.name = "PHP反序列化"; + this.module = "Default"; + this.description = "对PHP序列化数据进行反序列化,输出JSON。

此操作不支持 object 标签。

例如:
a:2:{s:1:"a";i:10;i:0;a:1:{s:2:"ab";b:1;}}
反序列化为
{"a": 10,0: {"ab": true}}

输出合法JSON: JSON不支持整数作为键,但PHP支持。开启此项会将整数转为字符串。同样也会转义反斜杠。"; + this.infoURL = "http://www.phpinternalsbook.com/classes_objects/serialization.html"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "输出合法JSON", + "type": "boolean", + "value": true + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + /** + * Recursive method for deserializing. + * @returns {*} + */ + function handleInput() { + /** + * Read `length` characters from the input, shifting them out the input. + * @param length + * @returns {string} + */ + function read(length) { + let result = ""; + for (let idx = 0; idx < length; idx++) { + const char = inputPart.shift(); + if (char === undefined) { + throw new OperationError("输入内容不完整"); + } + result += char; + } + return result; + } + + /** + * Read characters from the input until `until` is found. + * @param until + * @returns {string} + */ + function readUntil(until) { + let result = ""; + for (;;) { + const char = read(1); + if (char === until) { + break; + } else { + result += char; + } + } + return result; + + } + + /** + * Read characters from the input that must be equal to `expect` + * @param expect + * @returns {string} + */ + function expect(expect) { + const result = read(expect.length); + if (result !== expect) { + throw new OperationError("检测到错误输入内容"); + } + return result; + } + + /** + * Helper function to handle deserialized arrays. + * @returns {Array} + */ + function handleArray() { + const items = parseInt(readUntil(":"), 10) * 2; + expect("{"); + const result = []; + let isKey = true; + let lastItem = null; + for (let idx = 0; idx < items; idx++) { + const item = handleInput(); + if (isKey) { + lastItem = item; + isKey = false; + } else { + const numberCheck = lastItem.match(/[0-9]+/); + if (args[0] && numberCheck && numberCheck[0].length === lastItem.length) { + result.push('"' + lastItem + '": ' + item); + } else { + result.push(lastItem + ": " + item); + } + isKey = true; + } + } + expect("}"); + return result; + } + + + const kind = read(1).toLowerCase(); + + switch (kind) { + case "n": + expect(";"); + return "null"; + case "i": + case "d": + case "b": { + expect(":"); + const data = readUntil(";"); + if (kind === "b") { + return (parseInt(data, 10) !== 0); + } + return data; + } + + case "a": + expect(":"); + return "{" + handleArray() + "}"; + + case "s": { + expect(":"); + const length = readUntil(":"); + expect("\""); + const value = read(length); + expect('";'); + if (args[0]) { + return '"' + value.replace(/"/g, '\\"') + '"'; // lgtm [js/incomplete-sanitization] + } else { + return '"' + value + '"'; + } + } + + default: + throw new OperationError("未知类型: " + kind); + } + } + + const inputPart = input.split(""); + return handleInput(); + } + +} + +export default PHPDeserialize; diff --git a/plugins/srktoolbox/src/core/operations/PHPSerialize.mjs b/plugins/srktoolbox/src/core/operations/PHPSerialize.mjs new file mode 100644 index 00000000..00fb1380 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PHPSerialize.mjs @@ -0,0 +1,126 @@ +/** + * @author brun0ne [brunonblok@gmail.com] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * PHP Serialize operation + */ +class PHPSerialize extends Operation { + + /** + * PHPSerialize constructor + */ + constructor() { + super(); + + this.name = "PHP Serialize"; + this.module = "Default"; + this.description = "Performs PHP serialization on JSON data.

This function does not support object tags.

Since PHP doesn't distinguish dicts and arrays, this operation is not always symmetric to PHP Deserialize.

Example:
[5,"abc",true]
becomes
a:3:{i:0;i:5;i:1;s:3:"abc";i:2;b:1;}"; + this.infoURL = "https://www.phpinternalsbook.com/php5/classes_objects/serialization.html"; + this.inputType = "JSON"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {JSON} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + /** + * Determines if a number is an integer + * @param {number} value + * @returns {boolean} + */ + function isInteger(value) { + return typeof value === "number" && parseInt(value.toString(), 10) === value; + } + + /** + * Serialize basic types + * @param {string | number | boolean} content + * @returns {string} + */ + function serializeBasicTypes(content) { + const basicTypes = { + "string": "s", + "integer": "i", + "float": "d", + "boolean": "b" + }; + /** + * Booleans + * cast to 0 or 1 + */ + if (typeof content === "boolean") { + return `${basicTypes.boolean}:${content ? 1 : 0}`; + } + /* Numbers */ + if (typeof content === "number") { + if (isInteger(content)) { + return `${basicTypes.integer}:${content.toString()}`; + } else { + return `${basicTypes.float}:${content.toString()}`; + } + } + /* Strings */ + if (typeof content === "string") + return `${basicTypes.string}:${content.length}:"${content}"`; + + /** This should be unreachable */ + throw new OperationError(`Encountered a non-implemented type: ${typeof content}`); + } + + /** + * Recursively serialize + * @param {*} object + * @returns {string} + */ + function serialize(object) { + /* Null */ + if (object == null) { + return `N;`; + } + + if (typeof object !== "object") { + /* Basic types */ + return `${serializeBasicTypes(object)};`; + } else if (object instanceof Array) { + /* Arrays */ + const serializedElements = []; + + for (let i = 0; i < object.length; i++) { + serializedElements.push(`${serialize(i)}${serialize(object[i])}`); + } + + return `a:${object.length}:{${serializedElements.join("")}}`; + } else if (object instanceof Object) { + /** + * Objects + * Note: the output cannot be guaranteed to be in the same order as the input + */ + const serializedElements = []; + const keys = Object.keys(object); + + for (const key of keys) { + serializedElements.push(`${serialize(key)}${serialize(object[key])}`); + } + + return `a:${keys.length}:{${serializedElements.join("")}}`; + } + + /** This should be unreachable */ + throw new OperationError(`Encountered a non-implemented type: ${typeof object}`); + } + + return serialize(input); + } +} + +export default PHPSerialize; diff --git a/plugins/srktoolbox/src/core/operations/PLISTViewer.mjs b/plugins/srktoolbox/src/core/operations/PLISTViewer.mjs new file mode 100644 index 00000000..7cbed5f9 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PLISTViewer.mjs @@ -0,0 +1,135 @@ +/** + * @author n1073645 [n1073645@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * P-list Viewer operation + */ +class PlistViewer extends Operation { + + /** + * PlistViewer constructor + */ + constructor() { + super(); + + this.name = "P-list查看器"; + this.module = "Default"; + this.description = "在macOS、iOS、NeXTSTEP和GNUstep编程框架中,属性列表文件(Property list file)用于存储序列化对象。属性列表文件使用扩展名.plist,因此通常被称作p-list文件。

此操作将plist文件展示为人类可读格式。"; + this.infoURL = "https://wikipedia.org/wiki/Property_list"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + + // Regexes are designed to transform the xml format into a more readable string format. + input = input.slice(input.indexOf("/g, "plist => ") + .replace(//g, "{") + .replace(/<\/dict>/g, "}") + .replace(//g, "[") + .replace(/<\/array>/g, "]") + .replace(/.+<\/key>/g, m => `${m.slice(5, m.indexOf(/<\/key>/g)-5)}\t=> `) + .replace(/.+<\/real>/g, m => `${m.slice(6, m.indexOf(/<\/real>/g)-6)}\n`) + .replace(/.+<\/string>/g, m => `"${m.slice(8, m.indexOf(/<\/string>/g)-8)}"\n`) + .replace(/.+<\/integer>/g, m => `${m.slice(9, m.indexOf(/<\/integer>/g)-9)}\n`) + .replace(//g, m => "false") + .replace(//g, m => "true") + .replace(/<\/plist>/g, "/plist") + .replace(/.+<\/date>/g, m => `${m.slice(6, m.indexOf(/<\/integer>/g)-6)}`) + .replace(/[\s\S]+?<\/data>/g, m => `${m.slice(6, m.indexOf(/<\/data>/g)-6)}`) + .replace(/[ \t\r\f\v]/g, ""); + + /** + * Depending on the type of brace, it will increment the depth and amount of arrays accordingly. + * + * @param {string} elem + * @param {array} vals + * @param {number} offset + */ + function braces(elem, vals, offset) { + const temp = vals.indexOf(elem); + if (temp !== -1) { + depthCount += offset; + if (temp === 1) + arrCount += offset; + } + } + + let result = ""; + let arrCount = 0; + let depthCount = 0; + + /** + * Formats the input after the regex has replaced all of the relevant parts. + * + * @param {array} input + * @param {number} index + */ + function printIt(input, index) { + if (!(input.length)) + return; + + let temp = ""; + const origArr = arrCount; + let currElem = input[0]; + + // If the current position points at a larger dynamic structure. + if (currElem.indexOf("=>") !== -1) { + + // If the LHS also points at a larger structure (nested plists in a dictionary). + if (input[1].indexOf("=>") !== -1) + temp = currElem.slice(0, -2) + " => " + input[1].slice(0, -2) + " =>\n"; + else + temp = currElem.slice(0, -2) + " => " + input[1] + "\n"; + + input = input.slice(1); + } else { + // Controls the tab depth for how many closing braces there have been. + + braces(currElem, ["}", "]"], -1); + + // Has to be here since the formatting breaks otherwise. + temp = currElem + "\n"; + } + + currElem = input[0]; + + // Tab out to the correct distance. + result += ("\t".repeat(depthCount)); + + // If it is enclosed in an array show index. + if (arrCount > 0 && currElem !== "]") + result += index.toString() + " => "; + + result += temp; + + // Controls the tab depth for how many opening braces there have been. + braces(currElem, ["{", "["], 1); + + // If there has been a new array then reset index. + if (arrCount > origArr) + return printIt(input.slice(1), 0); + return printIt(input.slice(1), ++index); + } + + input = input.split("\n").filter(e => e !== ""); + printIt(input, 0); + return result; + } +} + +export default PlistViewer; diff --git a/plugins/srktoolbox/src/core/operations/PadLines.mjs b/plugins/srktoolbox/src/core/operations/PadLines.mjs new file mode 100644 index 00000000..589c42fc --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PadLines.mjs @@ -0,0 +1,72 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Pad lines operation + */ +class PadLines extends Operation { + + /** + * PadLines constructor + */ + constructor() { + super(); + + this.name = "填充行"; + this.module = "Default"; + this.description = "在每一行之前或之后添加特定数量的特定字符。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "位置", + "type": "option", + "value": ["开头", "末尾"] + }, + { + "name": "长度", + "type": "number", + "value": 5 + }, + { + "name": "字符", + "type": "binaryShortString", + "value": " " + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [position, len, chr] = args, + lines = input.split("\n"); + let output = "", + i = 0; + + if (position === "开头") { + for (i = 0; i < lines.length; i++) { + output += lines[i].padStart(lines[i].length+len, chr) + "\n"; + } + } else if (position === "末尾") { + for (i = 0; i < lines.length; i++) { + output += lines[i].padEnd(lines[i].length+len, chr) + "\n"; + } + } + + return output.slice(0, output.length-1); + } + +} + +export default PadLines; diff --git a/plugins/srktoolbox/src/core/operations/ParseASN1HexString.mjs b/plugins/srktoolbox/src/core/operations/ParseASN1HexString.mjs new file mode 100644 index 00000000..635730c8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseASN1HexString.mjs @@ -0,0 +1,57 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import r from "jsrsasign"; +import Operation from "../Operation.mjs"; + +/** + * Parse ASN.1 hex string operation + */ +class ParseASN1HexString extends Operation { + + /** + * ParseASN1HexString constructor + */ + constructor() { + super(); + + this.name = "解析ASN.1十六进制字符串"; + this.module = "PublicKey"; + this.description = "在电信和计算机网络领域,ASN.1(Abstract Syntax Notation One) 是一套标准,是描述数据的表示、编码、传输、解码的灵活的记法。

此操作可解析任意的ASN.1数据(必须为十六进制字符串,如果需要可以用“字符转十六进制”操作预处理)并展示结果树。"; + this.infoURL = "https://wikipedia.org/wiki/Abstract_Syntax_Notation_One"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "起始位置索引", + "type": "number", + "value": 0 + }, + { + "name": "截断超过以下长度的八字节字符串", + "type": "number", + "value": 32 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [index, truncateLen] = args; + return r.ASN1HEX.dump(input.replace(/\s/g, "").toLowerCase(), { + "ommit_long_octet": truncateLen + }, index); + } + +} + +export default ParseASN1HexString; diff --git a/plugins/srktoolbox/src/core/operations/ParseCSR.mjs b/plugins/srktoolbox/src/core/operations/ParseCSR.mjs new file mode 100644 index 00000000..39a76638 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseCSR.mjs @@ -0,0 +1,392 @@ +/** + * @author jkataja + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import r from "jsrsasign"; +import Operation from "../Operation.mjs"; +import { formatDnObj } from "../lib/PublicKey.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Parse CSR operation + */ +class ParseCSR extends Operation { + + /** + * ParseCSR constructor + */ + constructor() { + super(); + + this.name = "解析CSR"; + this.module = "PublicKey"; + this.description = "解析X.509证书的证书签名申请(Certificate Signing Request,CSR)数据。"; + this.infoURL = "https://wikipedia.org/wiki/Certificate_signing_request"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "输入格式", + "type": "option", + "value": ["PEM"] + } + ]; + this.checks = [ + { + "pattern": "^-+BEGIN CERTIFICATE REQUEST-+\\r?\\n[\\da-z+/\\n\\r]+-+END CERTIFICATE REQUEST-+\\r?\\n?$", + "flags": "i", + "args": ["PEM"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} Human-readable description of a Certificate Signing Request (CSR). + */ + run(input, args) { + if (!input.length) { + return "输入内容为空"; + } + + // Parse the CSR into JSON parameters + const csrParam = new r.KJUR.asn1.csr.CSRUtil.getParam(input); + + return `主体\n${formatDnObj(csrParam.subject, 2)} +公钥${formatSubjectPublicKey(csrParam.sbjpubkey)} +签名${formatSignature(csrParam.sigalg, csrParam.sighex)} +请求的扩展程序${formatRequestedExtensions(csrParam)}`; + } +} + +/** + * Format signature of a CSR + * @param {*} sigAlg string + * @param {*} sigHex string + * @returns Multi-line string describing CSR Signature + */ +function formatSignature(sigAlg, sigHex) { + let out = `\n`; + + out += ` 算法: ${sigAlg}\n`; + + if (new RegExp("withdsa", "i").test(sigAlg)) { + const d = new r.KJUR.crypto.DSA(); + const sigParam = d.parseASN1Signature(sigHex); + out += ` 签名: + R: ${formatHexOntoMultiLine(absBigIntToHex(sigParam[0]))} + S: ${formatHexOntoMultiLine(absBigIntToHex(sigParam[1]))}\n`; + } else if (new RegExp("withrsa", "i").test(sigAlg)) { + out += ` 签名: ${formatHexOntoMultiLine(sigHex)}\n`; + } else { + out += ` 签名: ${formatHexOntoMultiLine(ensureHexIsPositiveInTwosComplement(sigHex))}\n`; + } + + return chop(out); +} + +/** + * Format Subject Public Key from PEM encoded public key string + * @param {*} publicKeyPEM string + * @returns Multi-line string describing Subject Public Key Info + */ +function formatSubjectPublicKey(publicKeyPEM) { + let out = "\n"; + + const publicKey = r.KEYUTIL.getKey(publicKeyPEM); + if (publicKey instanceof r.RSAKey) { + out += ` 算法: RSA + 长度: ${publicKey.n.bitLength()} bits + 模数: ${formatHexOntoMultiLine(absBigIntToHex(publicKey.n))} + 指数: ${publicKey.e} (0x${Utils.hex(publicKey.e)})\n`; + } else if (publicKey instanceof r.KJUR.crypto.ECDSA) { + out += ` 算法: ECDSA + 长度: ${publicKey.ecparams.keylen} bits + Pub: ${formatHexOntoMultiLine(publicKey.pubKeyHex)} + ASN1 OID: ${r.KJUR.crypto.ECDSA.getName(publicKey.getShortNISTPCurveName())} + NIST CURVE: ${publicKey.getShortNISTPCurveName()}\n`; + } else if (publicKey instanceof r.KJUR.crypto.DSA) { + out += ` 算法: DSA + 长度: ${publicKey.p.toString(16).length * 4} bits + Pub: ${formatHexOntoMultiLine(absBigIntToHex(publicKey.y))} + P: ${formatHexOntoMultiLine(absBigIntToHex(publicKey.p))} + Q: ${formatHexOntoMultiLine(absBigIntToHex(publicKey.q))} + G: ${formatHexOntoMultiLine(absBigIntToHex(publicKey.g))}\n`; + } else { + out += `不支持的公钥算法\n`; + } + + return chop(out); +} + +/** + * Format known extensions of a CSR + * @param {*} csrParam object + * @returns Multi-line string describing CSR Requested Extensions + */ +function formatRequestedExtensions(csrParam) { + const formattedExtensions = new Array(4).fill(""); + + if (Object.hasOwn(csrParam, "extreq")) { + for (const extension of csrParam.extreq) { + let parts = []; + switch (extension.extname) { + case "basicConstraints" : + parts = describeBasicConstraints(extension); + formattedExtensions[0] = ` 证书基本约束:${formatExtensionCriticalTag(extension)}\n${indent(4, parts)}`; + break; + case "keyUsage" : + parts = describeKeyUsage(extension); + formattedExtensions[1] = ` 证书密钥用法:${formatExtensionCriticalTag(extension)}\n${indent(4, parts)}`; + break; + case "extKeyUsage" : + parts = describeExtendedKeyUsage(extension); + formattedExtensions[2] = ` 扩展密钥用法:${formatExtensionCriticalTag(extension)}\n${indent(4, parts)}`; + break; + case "subjectAltName" : + parts = describeSubjectAlternativeName(extension); + formattedExtensions[3] = ` 主体备用名称:${formatExtensionCriticalTag(extension)}\n${indent(4, parts)}`; + break; + default : + parts = ["(不支持的扩展程序)"]; + formattedExtensions.push(` ${extension.extname}:${formatExtensionCriticalTag(extension)}\n${indent(4, parts)}`); + } + } + } + + let out = "\n"; + + formattedExtensions.forEach((formattedExtension) => { + if (formattedExtension !== undefined && formattedExtension !== null && formattedExtension.length !== 0) { + out += formattedExtension; + } + }); + + return chop(out); +} + +/** + * Format extension critical tag + * @param {*} extension Object + * @returns String describing whether the extension is critical or not + */ +function formatExtensionCriticalTag(extension) { + return Object.hasOwn(extension, "critical") && extension.critical ? " 关键" : ""; +} + +/** + * Format string input as a comma separated hex string on multiple lines + * @param {*} hex String + * @returns Multi-line string describing the Hex input + */ +function formatHexOntoMultiLine(hex) { + if (hex.length % 2 !== 0) { + hex = "0" + hex; + } + + return formatMultiLine(chop(hex.replace(/(..)/g, "$&:"))); +} + +/** + * Convert BigInt to abs value in Hex + * @param {*} int BigInt + * @returns String representing absolute value in Hex + */ +function absBigIntToHex(int) { + int = int < 0n ? -int : int; + + return ensureHexIsPositiveInTwosComplement(int.toString(16)); +} + +/** + * Ensure Hex String remains positive in 2's complement + * @param {*} hex String + * @returns Hex String ensuring value remains positive in 2's complement + */ +function ensureHexIsPositiveInTwosComplement(hex) { + if (hex.length % 2 !== 0) { + return "0" + hex; + } + + // prepend 00 if most significant bit is 1 (sign bit) + if (hex.length >=2 && (parseInt(hex.substring(0, 2), 16) & 128)) { + hex = "00" + hex; + } + + return hex; +} + +/** + * Format string onto multiple lines + * @param {*} longStr + * @returns String as a multi-line string + */ +function formatMultiLine(longStr) { + const lines = []; + + for (let remain = longStr ; remain !== "" ; remain = remain.substring(48)) { + lines.push(remain.substring(0, 48)); + } + + return lines.join("\n "); +} + +/** + * Describe Basic Constraints + * @see RFC 5280 4.2.1.9. Basic Constraints https://www.ietf.org/rfc/rfc5280.txt + * @param {*} extension CSR extension with the name `basicConstraints` + * @returns Array of strings describing Basic Constraints + */ +function describeBasicConstraints(extension) { + const constraints = []; + + constraints.push(`CA = ${Object.hasOwn(extension, "cA") && extension.cA ? "是" : "否"}`); + if (Object.hasOwn(extension, "pathLen")) constraints.push(`中级CA证书数目上限 = ${extension.pathLen}`); + + return constraints; +} + +/** + * Describe Key Usage extension permitted use cases + * @see RFC 5280 4.2.1.3. Key Usage https://www.ietf.org/rfc/rfc5280.txt + * @param {*} extension CSR extension with the name `keyUsage` + * @returns Array of strings describing Key Usage extension permitted use cases + */ +function describeKeyUsage(extension) { + const usage = []; + + const kuIdentifierToName = { + digitalSignature: "签名", + nonRepudiation: "非否认", + keyEncipherment: "密钥加密", + dataEncipherment: "数据加密", + keyAgreement: "密钥协商", + keyCertSign: "证书签名", + cRLSign: "CRL签名", + encipherOnly: "仅加密", + decipherOnly: "仅解密", + }; + + if (Object.hasOwn(extension, "names")) { + extension.names.forEach((ku) => { + if (Object.hasOwn(kuIdentifierToName, ku)) { + usage.push(kuIdentifierToName[ku]); + } else { + usage.push(`未知的密钥用法 (${ku})`); + } + }); + } + + if (usage.length === 0) usage.push("(无)"); + + return usage; +} + +/** + * Describe Extended Key Usage extension permitted use cases + * @see RFC 5280 4.2.1.12. Extended Key Usage https://www.ietf.org/rfc/rfc5280.txt + * @param {*} extension CSR extension with the name `extendedKeyUsage` + * @returns Array of strings describing Extended Key Usage extension permitted use cases + */ +function describeExtendedKeyUsage(extension) { + const usage = []; + + const ekuIdentifierToName = { + "serverAuth": "TLS WWW 服务器身份验证", + "clientAuth": "TLS WWW 客户端身份验证", + "codeSigning": "代码签名", + "emailProtection": "电子邮件保护 (S/MIME)", + "timeStamping": "可信任时间戳", + "1.3.6.1.4.1.311.2.1.21": "Microsoft Individual Code Signing", // msCodeInd + "1.3.6.1.4.1.311.2.1.22": "Microsoft Commercial Code Signing", // msCodeCom + "1.3.6.1.4.1.311.10.3.1": "Microsoft Trust List Signing", // msCTLSign + "1.3.6.1.4.1.311.10.3.3": "Microsoft Server Gated Crypto", // msSGC + "1.3.6.1.4.1.311.10.3.4": "Microsoft Encrypted File System", // msEFS + "1.3.6.1.4.1.311.20.2.2": "Microsoft Smartcard Login", // msSmartcardLogin + "2.16.840.1.113730.4.1": "Netscape Server Gated Crypto", // nsSGC + }; + + if (Object.hasOwn(extension, "array")) { + extension.array.forEach((eku) => { + if (Object.hasOwn(ekuIdentifierToName, eku)) { + usage.push(ekuIdentifierToName[eku]); + } else { + usage.push(eku); + } + }); + } + + if (usage.length === 0) usage.push("(无)"); + + return usage; +} + +/** + * Format Subject Alternative Names from the name `subjectAltName` extension + * @see RFC 5280 4.2.1.6. Subject Alternative Name https://www.ietf.org/rfc/rfc5280.txt + * @param {*} extension object + * @returns Array of strings describing Subject Alternative Name extension + */ +function describeSubjectAlternativeName(extension) { + const names = []; + + if (Object.hasOwn(extension, "extname") && extension.extname === "subjectAltName") { + if (Object.hasOwn(extension, "array")) { + for (const altName of extension.array) { + Object.keys(altName).forEach((key) => { + switch (key) { + case "rfc822": + names.push(`EMAIL: ${altName[key]}`); + break; + case "dns": + names.push(`DNS: ${altName[key]}`); + break; + case "uri": + names.push(`URI: ${altName[key]}`); + break; + case "ip": + names.push(`IP: ${altName[key]}`); + break; + case "dn": + names.push(`DIR: ${altName[key].str}`); + break; + case "other" : + names.push(`Other: ${altName[key].oid}::${altName[key].value.utf8str.str}`); + break; + default: + names.push(`(无法格式化SAN '${key}':${altName[key]})\n`); + } + }); + } + } + } + + return names; +} + +/** + * Join an array of strings and add leading spaces to each line. + * @param {*} n How many leading spaces + * @param {*} parts Array of strings + * @returns Joined and indented string. + */ +function indent(n, parts) { + const fluff = " ".repeat(n); + return fluff + parts.join("\n" + fluff) + "\n"; +} + +/** + * Remove last character from a string. + * @param {*} s String + * @returns Chopped string. + */ +function chop(s) { + return s.substring(0, s.length - 1); +} + +export default ParseCSR; diff --git a/plugins/srktoolbox/src/core/operations/ParseColourCode.mjs b/plugins/srktoolbox/src/core/operations/ParseColourCode.mjs new file mode 100644 index 00000000..d61c2ea4 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseColourCode.mjs @@ -0,0 +1,198 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Parse colour code operation + */ +class ParseColourCode extends Operation { + + /** + * ParseColourCode constructor + */ + constructor() { + super(); + + this.name = "解析颜色代码"; + this.module = "Default"; + this.description = "将标准格式的颜色代码转换成其它标准格式并展示这个颜色。

示例输入
  • #d9edf7
  • rgba(217,237,247,1)
  • hsla(200,65%,91%,1)
  • cmyk(0.12, 0.04, 0.00, 0.03)
"; + this.infoURL = "https://wikipedia.org/wiki/Web_colors"; + this.inputType = "string"; + this.outputType = "html"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + let m = null, + r = 0, g = 0, b = 0, a = 1; + + // Read in the input + if ((m = input.match(/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/i))) { + // Hex - #d9edf7 + r = parseInt(m[1], 16); + g = parseInt(m[2], 16); + b = parseInt(m[3], 16); + } else if ((m = input.match(/rgba?\((\d{1,3}(?:\.\d+)?),\s?(\d{1,3}(?:\.\d+)?),\s?(\d{1,3}(?:\.\d+)?)(?:,\s?(\d(?:\.\d+)?))?\)/i))) { + // RGB or RGBA - rgb(217,237,247) or rgba(217,237,247,1) + r = parseFloat(m[1]); + g = parseFloat(m[2]); + b = parseFloat(m[3]); + a = m[4] ? parseFloat(m[4]) : 1; + } else if ((m = input.match(/hsla?\((\d{1,3}(?:\.\d+)?),\s?(\d{1,3}(?:\.\d+)?)%,\s?(\d{1,3}(?:\.\d+)?)%(?:,\s?(\d(?:\.\d+)?))?\)/i))) { + // HSL or HSLA - hsl(200, 65%, 91%) or hsla(200, 65%, 91%, 1) + const h_ = parseFloat(m[1]) / 360, + s_ = parseFloat(m[2]) / 100, + l_ = parseFloat(m[3]) / 100, + rgb_ = ParseColourCode._hslToRgb(h_, s_, l_); + + r = rgb_[0]; + g = rgb_[1]; + b = rgb_[2]; + a = m[4] ? parseFloat(m[4]) : 1; + } else if ((m = input.match(/cmyk\((\d(?:\.\d+)?),\s?(\d(?:\.\d+)?),\s?(\d(?:\.\d+)?),\s?(\d(?:\.\d+)?)\)/i))) { + // CMYK - cmyk(0.12, 0.04, 0.00, 0.03) + const c_ = parseFloat(m[1]), + m_ = parseFloat(m[2]), + y_ = parseFloat(m[3]), + k_ = parseFloat(m[4]); + + r = Math.round(255 * (1 - c_) * (1 - k_)); + g = Math.round(255 * (1 - m_) * (1 - k_)); + b = Math.round(255 * (1 - y_) * (1 - k_)); + } + + const hsl_ = ParseColourCode._rgbToHsl(r, g, b), + h = Math.round(hsl_[0] * 360), + s = Math.round(hsl_[1] * 100), + l = Math.round(hsl_[2] * 100); + let k = 1 - Math.max(r/255, g/255, b/255), + c = (1 - r/255 - k) / (1 - k), + y = (1 - b/255 - k) / (1 - k); + + m = (1 - g/255 - k) / (1 - k); + + c = isNaN(c) ? "0" : c.toFixed(2); + m = isNaN(m) ? "0" : m.toFixed(2); + y = isNaN(y) ? "0" : y.toFixed(2); + k = k.toFixed(2); + + const hex = "#" + + Math.round(r).toString(16).padStart(2, "0") + + Math.round(g).toString(16).padStart(2, "0") + + Math.round(b).toString(16).padStart(2, "0"), + rgb = "rgb(" + r + ", " + g + ", " + b + ")", + rgba = "rgba(" + r + ", " + g + ", " + b + ", " + a + ")", + hsl = "hsl(" + h + ", " + s + "%, " + l + "%)", + hsla = "hsla(" + h + ", " + s + "%, " + l + "%, " + a + ")", + cmyk = "cmyk(" + c + ", " + m + ", " + y + ", " + k + ")"; + + // Generate output + return `
+Hex: ${hex} +RGB: ${rgb} +RGBA: ${rgba} +HSL: ${hsl} +HSLA: ${hsla} +CMYK: ${cmyk} +`; + } + + /** + * Converts an HSL color value to RGB. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_colorSpace. + * Assumes h, s, and l are contained in the set [0, 1] and + * returns r, g, and b in the set [0, 255]. + * + * @author Mohsen (http://stackoverflow.com/a/9493060) + * + * @param {number} h - The hue + * @param {number} s - The saturation + * @param {number} l - The lightness + * @return {Array} The RGB representation + */ + static _hslToRgb(h, s, l) { + let r, g, b; + + if (s === 0) { + r = g = b = l; // achromatic + } else { + const hue2rgb = function hue2rgb(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1/6) return p + (q - p) * 6 * t; + if (t < 1/2) return q; + if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; + }; + + const q = l < 0.5 ? l * (1 + s) : l + s - l * s; + const p = 2 * l - q; + r = hue2rgb(p, q, h + 1/3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1/3); + } + + return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; + } + + /** + * Converts an RGB color value to HSL. Conversion formula + * adapted from http://en.wikipedia.org/wiki/HSL_colorSpace. + * Assumes r, g, and b are contained in the set [0, 255] and + * returns h, s, and l in the set [0, 1]. + * + * @author Mohsen (http://stackoverflow.com/a/9493060) + * + * @param {number} r - The red color value + * @param {number} g - The green color value + * @param {number} b - The blue color value + * @return {Array} The HSL representation + */ + static _rgbToHsl(r, g, b) { + r /= 255; g /= 255; b /= 255; + const max = Math.max(r, g, b), + min = Math.min(r, g, b), + l = (max + min) / 2; + let h, s; + + if (max === min) { + h = s = 0; // achromatic + } else { + const d = max - min; + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + + return [h, s, l]; + } +} + +export default ParseColourCode; diff --git a/plugins/srktoolbox/src/core/operations/ParseDateTime.mjs b/plugins/srktoolbox/src/core/operations/ParseDateTime.mjs new file mode 100644 index 00000000..eac20a24 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseDateTime.mjs @@ -0,0 +1,85 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import moment from "moment-timezone"; +import {DATETIME_FORMATS, FORMAT_EXAMPLES} from "../lib/DateTime.mjs"; + +/** + * Parse DateTime operation + */ +class ParseDateTime extends Operation { + + /** + * ParseDateTime constructor + */ + constructor() { + super(); + + this.name = "解析DateTime"; + this.module = "Default"; + this.description = "根据指定的格式与时区解析DateTime字符串。可解析出以下内容:
  • 日期
  • 时间
  • 上下午 (AM/PM)
  • 时区
  • UTC偏移量
  • 夏令时
  • 闰年
  • 当月天数
  • 当年的第几天
  • 星期
  • 季度
不输入任何内容来查看格式示例字符串。"; + this.infoURL = "https://momentjs.com/docs/#/parsing/string-format/"; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + "name": "内置格式", + "type": "populateOption", + "value": DATETIME_FORMATS, + "target": 1 + }, + { + "name": "输入格式", + "type": "binaryString", + "value": "DD/MM/YYYY HH:mm:ss" + }, + { + "name": "输入时区", + "type": "option", + "value": ["UTC"].concat(moment.tz.names()) + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const inputFormat = args[1], + inputTimezone = args[2]; + let date, + output = ""; + + try { + date = moment.tz(input, inputFormat, inputTimezone); + if (!date || date.format() === "Invalid date") throw Error; + } catch (err) { + return `无效格式。\n\n${FORMAT_EXAMPLES}`; + } + + output += "日期: " + date.format("dddd Do MMMM YYYY") + + "\n时间: " + date.format("HH:mm:ss") + + "\n上下午: " + date.format("A") + + "\n时区: " + date.format("z") + + "\nUTC偏移量: " + date.format("ZZ") + + "\n\n夏令时: " + date.isDST() + + "\n闰年: " + date.isLeapYear() + + "\n当月天数: " + date.daysInMonth() + + "\n\n当年第几天: " + date.dayOfYear() + + "\n当年第几周: " + date.week() + + "\n季度: " + date.quarter(); + + return output; + } + +} + +export default ParseDateTime; diff --git a/plugins/srktoolbox/src/core/operations/ParseIPRange.mjs b/plugins/srktoolbox/src/core/operations/ParseIPRange.mjs new file mode 100644 index 00000000..91d03ea0 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseIPRange.mjs @@ -0,0 +1,91 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @author Klaxon [klaxon@veyr.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {ipv4CidrRange, ipv4HyphenatedRange, ipv4ListedRange, ipv6CidrRange, ipv6HyphenatedRange, ipv6ListedRange} from "../lib/IP.mjs"; + +/** + * Parse IP range operation + */ +class ParseIPRange extends Operation { + + /** + * ParseIPRange constructor + */ + constructor() { + super(); + + this.name = "解析IP范围"; + this.module = "Default"; + this.description = "输入 CIDR 范围 (例: 10.0.0.0/24) 、连字符表示的范围 (例: 10.0.0.0 - 10.0.1.0)或一系列的IP和CIDR(回车分隔),此操作会解析输入IP范围的网络信息与列出所有可能的IP地址。

支持IPv6但不会列出详细地址。"; + this.infoURL = "https://wikipedia.org/wiki/Subnetwork"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "包括网络信息", + "type": "boolean", + "value": true + }, + { + "name": "列出所有IP地址", + "type": "boolean", + "value": true + }, + { + "name": "允许大数据量查询", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [ + includeNetworkInfo, + enumerateAddresses, + allowLargeList + ] = args; + + // Check what type of input we are looking at + const ipv4CidrRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\/(\d\d?)\s*$/, + ipv4RangeRegex = /^\s*((?:\d{1,3}\.){3}\d{1,3})\s*-\s*((?:\d{1,3}\.){3}\d{1,3})\s*$/, + ipv4ListRegex = /^\s*(((?:\d{1,3}\.){3}\d{1,3})(\/(\d\d?))?(\n|$)(\n*))+\s*$/, + ipv6CidrRegex = /^\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\/(\d\d?\d?)\s*$/i, + ipv6RangeRegex = /^\s*(((?=.*::)(?!.*::[^-]+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*-\s*(((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\17)::|:\b|(?![\dA-F])))|(?!\16\17)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))\s*$/i, + ipv6ListRegex = /^\s*((((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\4)::|:\b|(?![\dA-F])))|(?!\3\4)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4}))(\/(\d\d?\d?))?(\n|$)(\n*))+\s*$/i; + let match; + + if ((match = ipv4CidrRegex.exec(input))) { + return ipv4CidrRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList); + } else if ((match = ipv4RangeRegex.exec(input))) { + return ipv4HyphenatedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList); + } else if ((match = ipv4ListRegex.exec(input))) { + return ipv4ListedRange(match, includeNetworkInfo, enumerateAddresses, allowLargeList); + } else if ((match = ipv6CidrRegex.exec(input))) { + return ipv6CidrRange(match, includeNetworkInfo); + } else if ((match = ipv6RangeRegex.exec(input))) { + return ipv6HyphenatedRange(match, includeNetworkInfo); + } else if ((match = ipv6ListRegex.exec(input))) { + return ipv6ListedRange(match, includeNetworkInfo); + } else { + throw new OperationError("无效的输入。\n\n此操作支持CIDR范围(例:10.0.0.0/24)或连字符表示的范围(例:10.0.0.0 - 10.0.1.0)。同时支持IPv6。"); + } + } + +} + + +export default ParseIPRange; diff --git a/plugins/srktoolbox/src/core/operations/ParseIPv4Header.mjs b/plugins/srktoolbox/src/core/operations/ParseIPv4Header.mjs new file mode 100644 index 00000000..d09137e4 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseIPv4Header.mjs @@ -0,0 +1,132 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {fromHex, toHex} from "../lib/Hex.mjs"; +import {ipv4ToStr, protocolLookup} from "../lib/IP.mjs"; +import TCPIPChecksum from "./TCPIPChecksum.mjs"; + +/** + * Parse IPv4 header operation + */ +class ParseIPv4Header extends Operation { + + /** + * ParseIPv4Header constructor + */ + constructor() { + super(); + + this.name = "解析IPv4标头"; + this.module = "Default"; + this.description = "输入IPv4标头(Header)数据,此操作对其进行解析,用易于阅读的格式展示各字段信息。"; + this.infoURL = "https://wikipedia.org/wiki/IPv4#Header"; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + "name": "输入格式", + "type": "option", + "value": ["十六进制", "原始"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const format = args[0]; + let output; + + if (format === "十六进制") { + input = fromHex(input); + } else if (format === "原始") { + input = new Uint8Array(Utils.strToArrayBuffer(input)); + } else { + throw new OperationError("未知的输入格式。"); + } + + let ihl = input[0] & 0x0f; + const dscp = (input[1] >>> 2) & 0x3f, + ecn = input[1] & 0x03, + length = input[2] << 8 | input[3], + identification = input[4] << 8 | input[5], + flags = (input[6] >>> 5) & 0x07, + fragOffset = (input[6] & 0x1f) << 8 | input[7], + ttl = input[8], + protocol = input[9], + checksum = input[10] << 8 | input[11], + srcIP = input[12] << 24 | input[13] << 16 | input[14] << 8 | input[15], + dstIP = input[16] << 24 | input[17] << 16 | input[18] << 8 | input[19], + checksumHeader = input.slice(0, 10).concat([0, 0]).concat(input.slice(12, 20)); + let version = (input[0] >>> 4) & 0x0f, + options = []; + + + // Version + if (version !== 4) { + version = version + " (错误:对于IPv4标头,版本值应该为4)"; + } + + // IHL + if (ihl < 5) { + ihl = ihl + " (错误:应至少为5)"; + } else if (ihl > 5) { + // sort out options... + const optionsLen = ihl * 4 - 20; + options = input.slice(20, optionsLen + 20); + } + + // Protocol + const protocolInfo = protocolLookup[protocol] || {keyword: "", protocol: ""}; + + // Checksum + const correctChecksum = (new TCPIPChecksum).run(checksumHeader), + givenChecksum = Utils.hex(checksum); + let checksumResult; + if (correctChecksum === givenChecksum) { + checksumResult = givenChecksum + " (正确)"; + } else { + checksumResult = givenChecksum + " (不正确,应为 " + correctChecksum + ")"; + } + + output = ` + + + + + + + + + + + + +`; + + if (ihl > 5) { + output += ``; + } + + return output + "
字段
版本${version}
标头长度(IHL)${ihl} (${ihl * 4} 字节)
区分服务码点(DSCP)${dscp}
显式拥塞通告(ECN)${ecn}
全长${length} 字节 + IP标头: ${ihl * 4} 字节 + 数据: ${length - ihl * 4} 字节
标识符0x${Utils.hex(identification)} (${identification})
标志位0x${Utils.hex(flags, 2)} + 保留位:${flags >> 2} (必须为0) + 禁止分片:${flags >> 1 & 1} + 更多分片:${flags & 1}
分片偏移${fragOffset}
存活时间${ttl}
协议${protocol}, ${protocolInfo.protocol} (${protocolInfo.keyword})
标头检验和${checksumResult}
源地址${ipv4ToStr(srcIP)}
目的地址${ipv4ToStr(dstIP)}
选项${toHex(options)}
"; + } + +} + +export default ParseIPv4Header; diff --git a/plugins/srktoolbox/src/core/operations/ParseIPv6Address.mjs b/plugins/srktoolbox/src/core/operations/ParseIPv6Address.mjs new file mode 100644 index 00000000..94edbd99 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseIPv6Address.mjs @@ -0,0 +1,278 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {strToIpv6, ipv6ToStr, ipv4ToStr, IPV6_REGEX} from "../lib/IP.mjs"; +import BigNumber from "bignumber.js"; + +/** + * Parse IPv6 address operation + */ +class ParseIPv6Address extends Operation { + + /** + * ParseIPv6Address constructor + */ + constructor() { + super(); + + this.name = "解析IPv6地址"; + this.module = "Default"; + this.description = "显示有效IPv6地址的longhand和shorthand版本。

可识别所有保留范围以及封装/隧道地址如Teredo和6to4。"; + this.infoURL = "https://wikipedia.org/wiki/IPv6_address"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let match, + output = ""; + + if ((match = IPV6_REGEX.exec(input))) { + const ipv6 = strToIpv6(match[1]), + longhand = ipv6ToStr(ipv6), + shorthand = ipv6ToStr(ipv6, true); + + output += "Longhand: " + longhand + "\nShorthand: " + shorthand + "\n"; + + // Detect reserved addresses + if (shorthand === "::") { + // Unspecified address + output += "\n未指定的地址:对应IPv4的0.0.0.0/32。"; + output += "\n未指定的地址范围: ::/128"; + } else if (shorthand === "::1") { + // Loopback address + output += "\n本地回环地址,对应IPv4的127.0.0.1/8。"; + output += "\n本地回环地址范围: ::1/128"; + } else if (ipv6[0] === 0 && ipv6[1] === 0 && ipv6[2] === 0 && + ipv6[3] === 0 && ipv6[4] === 0 && ipv6[5] === 0xffff) { + // IPv4-mapped IPv6 address + output += "\n检测到IPv4映射地址。对于混合双栈的网络部署,IPv6客户端默认被原生支持,IPv4的客户端展示为位于此类地址的IPv6客户端。"; + output += "\nIPv4映射地址: " + ipv4ToStr((ipv6[6] << 16) + ipv6[7]); + output += "\nIPv4映射地址范围: ::ffff:0:0/96"; + } else if (ipv6[0] === 0 && ipv6[1] === 0 && ipv6[2] === 0 && + ipv6[3] === 0 && ipv6[4] === 0xffff && ipv6[5] === 0) { + // IPv4-translated address + output += "\n检测到IPv4翻译地址。无状态IP/ICMP翻译(SIIT)技术。详细信息请参考RFC 6145 和 6052。"; + output += "\nIPv4翻译地址: " + ipv4ToStr((ipv6[6] << 16) + ipv6[7]); + output += "\nIPv4翻译地址范围: ::ffff:0:0:0/96"; + } else if (ipv6[0] === 0x100) { + // Discard prefix per RFC 6666 + output += "\n检测到丢弃前缀(Discard Prefix)。一般用于抵御DoS攻击的黑洞路由。详细信息请参考RFC 6666。"; + output += "\n丢弃地址范围: 100::/64"; + } else if (ipv6[0] === 0x64 && ipv6[1] === 0xff9b && ipv6[2] === 0 && + ipv6[3] === 0 && ipv6[4] === 0 && ipv6[5] === 0) { + // IPv4/IPv6 translation per RFC 6052 + output += "\n检测到“Well-Known”前缀的IPv4/IPv6翻译地址。详细信息请参考RFC 6052。"; + output += "\nIPv4翻译地址: " + ipv4ToStr((ipv6[6] << 16) + ipv6[7]); + output += "\n“Well-Known”前缀范围: 64:ff9b::/96"; + } else if (ipv6[0] === 0x2001 && ipv6[1] === 0) { + // Teredo tunneling + output += "\n检测到Teredo隧道IPv6地址。\n"; + const serverIpv4 = (ipv6[2] << 16) + ipv6[3], + udpPort = (~ipv6[5]) & 0xffff, + clientIpv4 = ~((ipv6[6] << 16) + ipv6[7]), + flagCone = (ipv6[4] >>> 15) & 1, + flagR = (ipv6[4] >>> 14) & 1, + flagRandom1 = (ipv6[4] >>> 10) & 15, + flagUg = (ipv6[4] >>> 8) & 3, + flagRandom2 = ipv6[4] & 255; + + output += "\n服务器IPv4地址: " + ipv4ToStr(serverIpv4) + + "\n客户端IPv4地址: " + ipv4ToStr(clientIpv4) + + "\n客户端UDP端口: " + udpPort + + "\nFlag:" + + "\n\tCone: " + flagCone; + + if (flagCone) { + output += " (客户端位于锥形NAT后)"; + } else { + output += " (客户端没有位于锥形NAT后)"; + } + + output += "\n\tR: " + flagR; + + if (flagR) { + output += " 错误:这个flag应该设置为0。详细信息请参考RFC 5991 和 4380。"; + } + + output += "\n\tRandom1: " + Utils.bin(flagRandom1, 4) + + "\n\tUG: " + Utils.bin(flagUg, 2); + + if (flagUg) { + output += " 错误:这个flag应该设置为00。请参考RFC 4380。"; + } + + output += "\n\tRandom2: " + Utils.bin(flagRandom2, 8); + + if (!flagR && !flagUg && flagRandom1 && flagRandom2) { + output += "\n\n有效Teredo地址,符合RFC 4380 和 RFC 5991。"; + } else if (!flagR && !flagUg) { + output += "\n\n有效Teredo地址,符合RFC 4380,但不符合RFC 5991 (Teredo Security Updates),因为Flag字段中不包括随机数值。"; + } else { + output += "\n\n无效Teredo地址。"; + } + output += "\n\nTeredo前缀范围: 2001::/32"; + } else if (ipv6[0] === 0x2001 && ipv6[1] === 0x2 && ipv6[2] === 0) { + // Benchmarking + output += "\n分配给Benchmarking Methodology Working Group (BMWG)用于IPv6性能测试。对应IPv4的198.18.0.0/15。详细信息请参考RFC 5180。"; + output += "\nBMWG范围: 2001:2::/48"; + } else if (ipv6[0] === 0x2001 && ipv6[1] >= 0x10 && ipv6[1] <= 0x1f) { + // ORCHIDv1 + output += "\n废弃的ORCHIDv1 (Overlay Routable Cryptographic Hash Identifiers)地址。\nORCHIDv1范围: 2001:10::/28\nORCHIDv2现在使用2001:20::/28。"; + } else if (ipv6[0] === 0x2001 && ipv6[1] >= 0x20 && ipv6[1] <= 0x2f) { + // ORCHIDv2 + output += "\nORCHIDv2 (Overlay Routable Cryptographic Hash Identifiers)。\n用于加密哈希标识符(Cryptographic Hash Identifiers)的非路由IPv6地址"; + output += "\nORCHIDv2范围: 2001:20::/28"; + } else if (ipv6[0] === 0x2001 && ipv6[1] === 0xdb8) { + // Documentation + output += "\n文档用IPv6地址。此范围用于文档中需要IPv6地址举例用于描述网络场景的时候。对应IPv4的192.0.2.0/24、198.51.100.0/24和203.0.113.0/24。"; + output += "\n文档地址范围: 2001:db8::/32"; + } else if (ipv6[0] === 0x2002) { + // 6to4 + output += "\n检测到6to4过渡IPv6地址。详细信息请参考RFC 3056。" + + "\n6to4前缀范围: 2002::/16"; + + const v4Addr = ipv4ToStr((ipv6[1] << 16) + ipv6[2]), + slaId = ipv6[3], + interfaceIdStr = ipv6[4].toString(16) + ipv6[5].toString(16) + ipv6[6].toString(16) + ipv6[7].toString(16), + interfaceId = new BigNumber(interfaceIdStr, 16); + + output += "\n\n封装的IPv4地址: " + v4Addr + + "\nSLA ID: " + slaId + + "\n接口ID (16进制): " + interfaceIdStr + + "\n接口ID (10进制): " + interfaceId.toString(); + } else if (ipv6[0] >= 0xfc00 && ipv6[0] <= 0xfdff) { + // Unique local address + output += "\n唯一本地地址(Unique local address),类似于IPv4的私有地址范围10.0.0.0/8、172.16.0.0/12和192.168.0.0/16。详细信息请参考RFC 4193。"; + output += "\n唯一本地地址范围: fc00::/7"; + } else if (ipv6[0] >= 0xfe80 && ipv6[0] <= 0xfebf) { + // Link-local address + output += "\n链路本地地址(Link-local address),类似于IPv4的自动私有地址范围169.254.0.0/16。"; + output += "\n链路本地地址范围: fe80::/10"; + } else if (ipv6[0] >= 0xff00) { + // Multicast + output += "\n保留的多播地址。"; + output += "\n多播地址范围: ff00::/8"; + + switch (ipv6[0]) { + case 0xff01: + output += "\n\n保留的多播地址块,用于接口本地范围(Interface Local Scope)"; + break; + case 0xff02: + output += "\n\n保留的多播地址块,用于链路本地范围(Link Local Scope)"; + break; + case 0xff03: + output += "\n\n保留的多播地址块,用于地域本地范围(Realm Local Scope)"; + break; + case 0xff04: + output += "\n\n保留的多播地址块,用于管理本地范围(Admin Local Scope)"; + break; + case 0xff05: + output += "\n\n保留的多播地址块,用于站点本地范围(Site Local Scope)"; + break; + case 0xff08: + output += "\n\n保留的多播地址块,用于组织本地范围(Organisation Local Scope)"; + break; + case 0xff0e: + output += "\n\n保留的多播地址块,用于全局范围(Global Scope)"; + break; + } + + if (ipv6[6] === 1) { + if (ipv6[7] === 2) { + output += "\n保留的多播地址,用于 'All DHCP Servers and Relay Agents (defined in RFC3315)'"; + } else if (ipv6[7] === 3) { + output += "\n保留的多播地址,用于 'All LLMNR Hosts (defined in RFC4795)'"; + } + } else { + switch (ipv6[7]) { + case 1: + output += "\n保留的多播地址,用于 'All nodes'"; + break; + case 2: + output += "\n保留的多播地址,用于 'All routers'"; + break; + case 5: + output += "\n保留的多播地址,用于 'OSPFv3 - All OSPF routers'"; + break; + case 6: + output += "\n保留的多播地址,用于 'OSPFv3 - All Designated Routers'"; + break; + case 8: + output += "\n保留的多播地址,用于 'IS-IS for IPv6 Routers'"; + break; + case 9: + output += "\n保留的多播地址,用于 'RIP Routers'"; + break; + case 0xa: + output += "\n保留的多播地址,用于 'EIGRP Routers'"; + break; + case 0xc: + output += "\n保留的多播地址,用于 'Simple Service Discovery Protocol'"; + break; + case 0xd: + output += "\n保留的多播地址,用于 'PIM Routers'"; + break; + case 0x16: + output += "\n保留的多播地址,用于 'MLDv2 Reports (defined in RFC3810)'"; + break; + case 0x6b: + output += "\n保留的多播地址,用于 'Precision Time Protocol v2 Peer Delay Measurement Messages'"; + break; + case 0xfb: + output += "\n保留的多播地址,用于 'Multicast DNS'"; + break; + case 0x101: + output += "\n保留的多播地址,用于 'Network Time Protocol'"; + break; + case 0x108: + output += "\n保留的多播地址,用于 'Network Information Service'"; + break; + case 0x114: + output += "\n保留的多播地址,用于 'Experiments'"; + break; + case 0x181: + output += "\n保留的多播地址,用于 'Precision Time Protocol v2 Messages (exc. Peer Delay)'"; + break; + } + } + } + + + // Detect possible EUI-64 addresses + if (((ipv6[5] & 0xff) === 0xff) && (ipv6[6] >>> 8 === 0xfe)) { + output += "\n\n此IPv6地址包含修改过的EUI-64地址,由于第12个和第13个八位组是FF:FE。"; + + const intIdent = Utils.hex(ipv6[4] >>> 8) + ":" + Utils.hex(ipv6[4] & 0xff) + ":" + + Utils.hex(ipv6[5] >>> 8) + ":" + Utils.hex(ipv6[5] & 0xff) + ":" + + Utils.hex(ipv6[6] >>> 8) + ":" + Utils.hex(ipv6[6] & 0xff) + ":" + + Utils.hex(ipv6[7] >>> 8) + ":" + Utils.hex(ipv6[7] & 0xff), + mac = Utils.hex((ipv6[4] >>> 8) ^ 2) + ":" + Utils.hex(ipv6[4] & 0xff) + ":" + + Utils.hex(ipv6[5] >>> 8) + ":" + Utils.hex(ipv6[6] & 0xff) + ":" + + Utils.hex(ipv6[7] >>> 8) + ":" + Utils.hex(ipv6[7] & 0xff); + output += "\n接口标识符: " + intIdent + + "\nMAC地址: " + mac; + } + } else { + throw new OperationError("无效IPv6地址"); + } + return output; + } + +} + +export default ParseIPv6Address; diff --git a/plugins/srktoolbox/src/core/operations/ParseObjectIDTimestamp.mjs b/plugins/srktoolbox/src/core/operations/ParseObjectIDTimestamp.mjs new file mode 100644 index 00000000..b33430d7 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseObjectIDTimestamp.mjs @@ -0,0 +1,49 @@ +/** + * @author dmfj [dominic@dmfj.io] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import BSON from "bson"; + +/** + * Parse ObjectID timestamp operation + */ +class ParseObjectIDTimestamp extends Operation { + + /** + * ParseObjectIDTimestamp constructor + */ + constructor() { + super(); + + this.name = "解析ObjectID时间戳"; + this.module = "Serialise"; + this.description = "解析MongoDB/BSON ObjectID十六进制时间戳。"; + this.infoURL = "https://docs.mongodb.com/manual/reference/method/ObjectId.getTimestamp/"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + try { + const objectId = new BSON.ObjectID(input); + return objectId.getTimestamp().toISOString(); + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default ParseObjectIDTimestamp; diff --git a/plugins/srktoolbox/src/core/operations/ParseQRCode.mjs b/plugins/srktoolbox/src/core/operations/ParseQRCode.mjs new file mode 100644 index 00000000..3dbae00b --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseQRCode.mjs @@ -0,0 +1,64 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { parseQrCode } from "../lib/QRCode.mjs"; + +/** + * Parse QR Code operation + */ +class ParseQRCode extends Operation { + /** + * ParseQRCode constructor + */ + constructor() { + super(); + + this.name = "解析二维码"; + this.module = "Image"; + this.description = + "读取图像文件并尝试检测并读取其中Quick Response (QR)二维码的内容。

标准化图像
在尝试读取前先对图像进行标准化处理。"; + this.infoURL = "https://wikipedia.org/wiki/QR_code"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "标准化图像", + type: "boolean", + value: false, + }, + ]; + this.checks = [ + { + pattern: + "^(?:\\xff\\xd8\\xff|\\x89\\x50\\x4e\\x47|\\x47\\x49\\x46|.{8}\\x57\\x45\\x42\\x50|\\x42\\x4d)", + flags: "", + args: [false], + useful: true, + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const [normalise] = args; + + if (!isImage(input)) { + throw new OperationError("无效的文件类型。"); + } + return parseQrCode(input, normalise); + } +} + +export default ParseQRCode; diff --git a/plugins/srktoolbox/src/core/operations/ParseSSHHostKey.mjs b/plugins/srktoolbox/src/core/operations/ParseSSHHostKey.mjs new file mode 100644 index 00000000..0aec5be9 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseSSHHostKey.mjs @@ -0,0 +1,161 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { fromBase64 } from "../lib/Base64.mjs"; +import { fromHex, toHexFast } from "../lib/Hex.mjs"; + +/** + * Parse SSH Host Key operation + */ +class ParseSSHHostKey extends Operation { + + /** + * ParseSSHHostKey constructor + */ + constructor() { + super(); + + this.name = "解析SSH主机密钥"; + this.module = "Default"; + this.description = "解析SSH主机密钥(host key),提取其中字段。
支持的密钥类型:
  • ssh-rsa
  • ssh-dss
  • ecdsa-sha2
  • ssh-ed25519
密钥可以为十六进制或Base64格式"; + this.infoURL = "https://wikipedia.org/wiki/Secure_Shell"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "输入格式", + type: "option", + value: [ + "自动", + "Base64", + "十六进制" + ] + } + ]; + this.checks = [ + { + pattern: "^\\s*([A-F\\d]{2}[,;:]){15,}[A-F\\d]{2}\\s*$", + flags: "i", + args: ["十六进制"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [inputFormat] = args, + inputKey = this.convertKeyToBinary(input.trim(), inputFormat), + fields = this.parseKey(inputKey), + keyType = Utils.byteArrayToChars(fromHex(fields[0]), ""); + + let output = `密钥类型: ${keyType}`; + + if (keyType === "ssh-rsa") { + output += `\n指数: 0x${fields[1]}`; + output += `\n模数: 0x${fields[2]}`; + } else if (keyType === "ssh-dss") { + output += `\np: 0x${fields[1]}`; + output += `\nq: 0x${fields[2]}`; + output += `\ng: 0x${fields[3]}`; + output += `\ny: 0x${fields[4]}`; + } else if (keyType.startsWith("ecdsa-sha2")) { + output += `\n曲线: ${Utils.byteArrayToChars(fromHex(fields[1]))}`; + output += `\n点位: 0x${fields.slice(2)}`; + } else if (keyType === "ssh-ed25519") { + output += `\nx: 0x${fields[1]}`; + } else { + output += "\n不支持的密钥类型"; + output += `\n参数: ${fields.slice(1)}`; + } + + return output; + } + + /** + * Converts the key to binary format from either hex or base64 + * + * @param {string} inputKey + * @param {string} inputFormat + * @returns {byteArray} + */ + convertKeyToBinary(inputKey, inputFormat) { + const keyPattern = new RegExp(/^(?:ssh|ecdsa-sha2)\S+\s+(\S*)/), + keyMatch = inputKey.match(keyPattern); + + if (keyMatch) { + inputKey = keyMatch[1]; + } + + if (inputFormat === "自动") { + inputFormat = this.detectKeyFormat(inputKey); + } + if (inputFormat === "十六进制") { + return fromHex(inputKey); + } else if (inputFormat === "Base64") { + return fromBase64(inputKey, null, "byteArray"); + } else { + throw new OperationError("无效的输入格式"); + } + } + + + /** + * Detects if the key is base64 or hex encoded + * + * @param {string} inputKey + * @returns {string} + */ + detectKeyFormat(inputKey) { + const hexPattern = new RegExp(/^(?:[\dA-Fa-f]{2}[ ,;:]?)+$/); + const b64Pattern = new RegExp(/^\s*(?:[A-Za-z\d+/]{4})+(?:[A-Za-z\d+/]{2}==|[A-Za-z\d+/]{3}=)?\s*$/); + + if (hexPattern.test(inputKey)) { + return "十六进制"; + } else if (b64Pattern.test(inputKey)) { + return "Base64"; + } else { + throw new OperationError("无法检测密钥格式。"); + } + } + + + /** + * Parses fields from the key + * + * @param {byteArray} key + */ + parseKey(key) { + const fields = []; + while (key.length > 0) { + const lengthField = key.slice(0, 4); + let decodedLength = 0; + for (let i = 0; i < lengthField.length; i++) { + decodedLength += lengthField[i]; + decodedLength = decodedLength << 8; + } + decodedLength = decodedLength >> 8; + // Break if length wasn't decoded correctly + if (decodedLength <= 0) break; + + fields.push(toHexFast(key.slice(4, 4 + decodedLength))); + key = key.slice(4 + decodedLength); + } + + return fields; + } + +} + +export default ParseSSHHostKey; diff --git a/plugins/srktoolbox/src/core/operations/ParseTCP.mjs b/plugins/srktoolbox/src/core/operations/ParseTCP.mjs new file mode 100644 index 00000000..8f73842e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseTCP.mjs @@ -0,0 +1,247 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Stream from "../lib/Stream.mjs"; +import {toHexFast, fromHex} from "../lib/Hex.mjs"; +import {toBinary} from "../lib/Binary.mjs"; +import {objToTable, bytesToLargeNumber} from "../lib/Protocol.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import BigNumber from "bignumber.js"; + +/** + * Parse TCP operation + */ +class ParseTCP extends Operation { + + /** + * ParseTCP constructor + */ + constructor() { + super(); + + this.name = "解析TCP"; + this.module = "Default"; + this.description = "解析TCP标头和载荷(如果有)。"; + this.infoURL = "https://wikipedia.org/wiki/Transmission_Control_Protocol"; + this.inputType = "string"; + this.outputType = "json"; + this.presentType = "html"; + this.args = [ + { + name: "输入格式", + type: "option", + value: ["十六进制", "原始"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const format = args[0]; + + if (format === "十六进制") { + input = fromHex(input); + } else if (format === "原始") { + input = Utils.strToArrayBuffer(input); + } else { + throw new OperationError("未知的输入格式。"); + } + + const s = new Stream(new Uint8Array(input)); + if (s.length < 20) { + throw new OperationError("TCP标头需要至少20字节。"); + } + + // Parse Header + const TCPPacket = { + "来源连接端口": s.readInt(2), + "目的连接端口": s.readInt(2), + "序列号": bytesToLargeNumber(s.getBytes(4)), + "确认号": s.readInt(4), + "资料偏移": s.readBits(4), + "标志符": { + "保留": toBinary(s.readBits(3), "", 3), + "NS": s.readBits(1), + "CWR": s.readBits(1), + "ECE": s.readBits(1), + "URG": s.readBits(1), + "ACK": s.readBits(1), + "PSH": s.readBits(1), + "RST": s.readBits(1), + "SYN": s.readBits(1), + "FIN": s.readBits(1), + }, + "窗口大小": s.readInt(2), + "校验和": "0x" + toHexFast(s.getBytes(2)), + "紧急指针": "0x" + toHexFast(s.getBytes(2)) + }; + + // Parse options if present + let windowScaleShift = 0; + if (TCPPacket["资料偏移"] > 5) { + let remainingLength = TCPPacket["资料偏移"] * 4 - 20; + + const options = {}; + while (remainingLength > 0) { + const option = { + "Kind": s.readInt(1) + }; + + let opt = { name: "Reserved", length: true }; + if (Object.prototype.hasOwnProperty.call(TCP_OPTION_KIND_LOOKUP, option.Kind)) { + opt = TCP_OPTION_KIND_LOOKUP[option.Kind]; + } + + // Add Length and Value fields + if (opt.length) { + option.Length = s.readInt(1); + + if (option.Length > 2) { + if (Object.prototype.hasOwnProperty.call(opt, "parser")) { + option.Value = opt.parser(s.getBytes(option.Length - 2)); + } else { + option.Value = option.Length <= 6 ? + s.readInt(option.Length - 2): + "0x" + toHexFast(s.getBytes(option.Length - 2)); + } + + // Store Window Scale shift for later + if (option.Kind === 3 && option.Value) { + windowScaleShift = option.Value["移位偏移量"]; + } + } + } + options[opt.name] = option; + + const length = option.Length || 1; + remainingLength -= length; + } + TCPPacket.Options = options; + } + + if (s.hasMore()) { + TCPPacket.Data = "0x" + toHexFast(s.getBytes()); + } + + // Improve values + TCPPacket["资料偏移"] = `${TCPPacket["资料偏移"]} (${TCPPacket["资料偏移"] * 4} 字节)`; + const trueWndSize = BigNumber(TCPPacket["窗口大小"]).multipliedBy(BigNumber(2).pow(BigNumber(windowScaleShift))); + TCPPacket["窗口大小"] = `${TCPPacket["窗口大小"]} (扩大后: ${trueWndSize})`; + + return TCPPacket; + } + + /** + * Displays the TCP Packet in a tabular style + * @param {Object} data + * @returns {html} + */ + present(data) { + return objToTable(data); + } + +} + +// Taken from https://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml +// on 2022-05-30 +const TCP_OPTION_KIND_LOOKUP = { + 0: { name: "End of Option List", length: false }, + 1: { name: "No-Operation", length: false }, + 2: { name: "Maximum Segment Size", length: true }, + 3: { name: "Window Scale", length: true, parser: windowScaleParser }, + 4: { name: "SACK Permitted", length: true }, + 5: { name: "SACK", length: true }, + 6: { name: "Echo (obsoleted by option 8)", length: true }, + 7: { name: "Echo Reply (obsoleted by option 8)", length: true }, + 8: { name: "Timestamps", length: true, parser: tcpTimestampParser }, + 9: { name: "Partial Order Connection Permitted (obsolete)", length: true }, + 10: { name: "Partial Order Service Profile (obsolete)", length: true }, + 11: { name: "CC (obsolete)", length: true }, + 12: { name: "CC.NEW (obsolete)", length: true }, + 13: { name: "CC.ECHO (obsolete)", length: true }, + 14: { name: "TCP Alternate Checksum Request (obsolete)", length: true, parser: tcpAlternateChecksumParser }, + 15: { name: "TCP Alternate Checksum Data (obsolete)", length: true }, + 16: { name: "Skeeter", length: true }, + 17: { name: "Bubba", length: true }, + 18: { name: "Trailer Checksum Option", length: true }, + 19: { name: "MD5 Signature Option (obsoleted by option 29)", length: true }, + 20: { name: "SCPS Capabilities", length: true }, + 21: { name: "Selective Negative Acknowledgements", length: true }, + 22: { name: "Record Boundaries", length: true }, + 23: { name: "Corruption experienced", length: true }, + 24: { name: "SNAP", length: true }, + 25: { name: "Unassigned (released 2000-12-18)", length: true }, + 26: { name: "TCP Compression Filter", length: true }, + 27: { name: "Quick-Start Response", length: true }, + 28: { name: "User Timeout Option (also, other known unauthorized use)", length: true }, + 29: { name: "TCP Authentication Option (TCP-AO)", length: true }, + 30: { name: "Multipath TCP (MPTCP)", length: true }, + 69: { name: "Encryption Negotiation (TCP-ENO)", length: true }, + 70: { name: "Reserved (known unauthorized use without proper IANA assignment)", length: true }, + 76: { name: "Reserved (known unauthorized use without proper IANA assignment)", length: true }, + 77: { name: "Reserved (known unauthorized use without proper IANA assignment)", length: true }, + 78: { name: "Reserved (known unauthorized use without proper IANA assignment)", length: true }, + 253: { name: "RFC3692-style Experiment 1 (also improperly used for shipping products) ", length: true }, + 254: { name: "RFC3692-style Experiment 2 (also improperly used for shipping products) ", length: true } +}; + +/** + * Parses the TCP Alternate Checksum Request field + * @param {Uint8Array} data + */ +function tcpAlternateChecksumParser(data) { + const lookup = { + 0: "TCP Checksum", + 1: "8-bit Fletchers's algorithm", + 2: "16-bit Fletchers's algorithm", + 3: "Redundant Checksum Avoidance" + }[data[0]]; + + return `${lookup} (0x${toHexFast(data)})`; +} + +/** + * Parses the TCP Timestamp field + * @param {Uint8Array} data + */ +function tcpTimestampParser(data) { + const s = new Stream(data); + + if (s.length !== 8) + return `错误:时间戳字段必须为8个字节(接收到 0x${toHexFast(data)})`; + + const tsval = bytesToLargeNumber(s.getBytes(4)), + tsecr = bytesToLargeNumber(s.getBytes(4)); + + return { + "当前时间戳": tsval, + "应答回复": tsecr + }; +} + +/** + * Parses the Window Scale field + * @param {Uint8Array} data + */ +function windowScaleParser(data) { + if (data.length !== 1) + return `错误:窗口扩大值需要1个字节(接收到 0x${toHexFast(data)})`; + + return { + "移位偏移量": data[0], + "乘数": 1 << data[0] + }; +} + +export default ParseTCP; diff --git a/plugins/srktoolbox/src/core/operations/ParseTLSRecord.mjs b/plugins/srktoolbox/src/core/operations/ParseTLSRecord.mjs new file mode 100644 index 00000000..92e4a408 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseTLSRecord.mjs @@ -0,0 +1,886 @@ +/** + * @author c65722 [] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {toHexFast} from "../lib/Hex.mjs"; +import {objToTable} from "../lib/Protocol.mjs"; +import Stream from "../lib/Stream.mjs"; + +/** + * Parse TLS record operation. + */ +class ParseTLSRecord extends Operation { + + /** + * ParseTLSRecord constructor. + */ + constructor() { + super(); + + this.name = "解析TLS记录"; + this.module = "Default"; + this.description = "解析一个或多个TLS记录"; + this.infoURL = "https://wikipedia.org/wiki/Transport_Layer_Security"; + this.inputType = "ArrayBuffer"; + this.outputType = "json"; + this.presentType = "html"; + this.args = []; + this._handshakeParser = new HandshakeParser(); + this._contentTypes = new Map(); + + for (const key in ContentType) { + this._contentTypes[ContentType[key]] = key.toString().toLocaleLowerCase(); + } + } + + /** + * @param {ArrayBuffer} input - Stream, containing one or more raw TLS Records. + * @param {Object[]} args + * @returns {Object[]} Array of Object representations of TLS Records contained within input. + */ + run(input, args) { + const s = new Stream(new Uint8Array(input)); + + const output = []; + + while (s.hasMore()) { + const record = this._readRecord(s); + if (record) { + output.push(record); + } + } + + return output; + } + + /** + * Reads a TLS Record from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw TLS Record. + * @returns {Object} Object representation of TLS Record. + */ + _readRecord(input) { + const RECORD_HEADER_LEN = 5; + + if (input.position + RECORD_HEADER_LEN > input.length) { + input.moveTo(input.length); + + return null; + } + + const type = input.readInt(1); + const typeString = this._contentTypes[type] ?? type.toString(); + const version = "0x" + toHexFast(input.getBytes(2)); + const length = input.readInt(2); + const content = input.getBytes(length); + const truncated = content.length < length; + + const recordHeader = new RecordHeader(typeString, version, length, truncated); + + if (!content.length) { + return {...recordHeader}; + } + + if (type === ContentType.HANDSHAKE) { + return this._handshakeParser.parse(new Stream(content), recordHeader); + } + + const record = {...recordHeader}; + record.value = "0x" + toHexFast(content); + + return record; + } + + /** + * Displays the parsed TLS Records in a tabular style. + * + * @param {Object[]} data - Array of Object representations of the TLS Records. + * @returns {html} HTML representation of TLS Records contained within data. + */ + present(data) { + return data.map(r => objToTable(r)).join("\n\n"); + } +} + +export default ParseTLSRecord; + +/** + * Repesents the known values of type field of a TLS Record header. + */ +const ContentType = Object.freeze({ + CHANGE_CIPHER_SPEC: 20, + ALERT: 21, + HANDSHAKE: 22, + APPLICATION_DATA: 23, +}); + +/** + * Represents a TLS Record header + */ +class RecordHeader { + /** + * RecordHeader cosntructor. + * + * @param {string} type - String representation of TLS Record type field. + * @param {string} version - Hex representation of TLS Record version field. + * @param {int} length - Length of TLS Record. + * @param {bool} truncated - Is TLS Record truncated. + */ + constructor(type, version, length, truncated) { + this.type = type; + this.version = version; + this.length = length; + + if (truncated) { + this.truncated = true; + } + } +} + +/** + * Parses TLS Handshake messages. + */ +class HandshakeParser { + + /** + * HandshakeParser constructor. + */ + constructor() { + this._clientHelloParser = new ClientHelloParser(); + this._serverHelloParser = new ServerHelloParser(); + this._newSessionTicketParser = new NewSessionTicketParser(); + this._certificateParser = new CertificateParser(); + this._certificateRequestParser = new CertificateRequestParser(); + this._certificateVerifyParser = new CertificateVerifyParser(); + this._handshakeTypes = new Map(); + + for (const key in HandshakeType) { + this._handshakeTypes[HandshakeType[key]] = key.toString().toLowerCase(); + } + } + + /** + * Parses a single TLS handshake message. + * + * @param {Stream} input - Stream, containing a raw Handshake message. + * @param {RecordHeader} recordHeader - TLS Record header. + * @returns {Object} Object representation of Handshake. + */ + parse(input, recordHeader) { + const output = {...recordHeader}; + + if (!input.hasMore()) { + return output; + } + + const handshakeType = input.readInt(1); + output.handshakeType = this._handshakeTypes[handshakeType] ?? handshakeType.toString(); + + if (input.position + 3 > input.length) { + input.moveTo(input.length); + + return output; + } + + const handshakeLength = input.readInt(3); + + if (handshakeLength + 4 !== recordHeader.length) { + input.moveTo(0); + + output.handshakeType = this._handshakeTypes[HandshakeType.FINISHED]; + output.handshakeValue = "0x" + toHexFast(input.bytes); + + return output; + } + + const content = input.getBytes(handshakeLength); + if (!content.length) { + return output; + } + + switch (handshakeType) { + case HandshakeType.CLIENT_HELLO: + return {...output, ...this._clientHelloParser.parse(new Stream(content))}; + case HandshakeType.SERVER_HELLO: + return {...output, ...this._serverHelloParser.parse(new Stream(content))}; + case HandshakeType.NEW_SESSION_TICKET: + return {...output, ...this._newSessionTicketParser.parse(new Stream(content))}; + case HandshakeType.CERTIFICATE: + return {...output, ...this._certificateParser.parse(new Stream(content))}; + case HandshakeType.CERTIFICATE_REQUEST: + return {...output, ...this._certificateRequestParser.parse(new Stream(content))}; + case HandshakeType.CERTIFICATE_VERIFY: + return {...output, ...this._certificateVerifyParser.parse(new Stream(content))}; + default: + output.handshakeValue = "0x" + toHexFast(content); + } + + return output; + } +} + +/** + * Represents the known values of the msg_type field of a TLS Handshake message. + */ +const HandshakeType = Object.freeze({ + HELLO_REQUEST: 0, + CLIENT_HELLO: 1, + SERVER_HELLO: 2, + NEW_SESSION_TICKET: 4, + CERTIFICATE: 11, + SERVER_KEY_EXCHANGE: 12, + CERTIFICATE_REQUEST: 13, + SERVER_HELLO_DONE: 14, + CERTIFICATE_VERIFY: 15, + CLIENT_KEY_EXCHANGE: 16, + FINISHED: 20, +}); + +/** + * Parses TLS Handshake ClientHello messages. + */ +class ClientHelloParser { + + /** + * ClientHelloParser constructor. + */ + constructor() { + this._extensionsParser = new ExtensionsParser(); + } + + /** + * Parses a single TLS Handshake ClientHello message. + * + * @param {Stream} input - Stream, containing a raw ClientHello message. + * @returns {Object} Object representation of ClientHello. + */ + parse(input) { + const output = {}; + + output.clientVersion = this._readClientVersion(input); + output.random = this._readRandom(input); + + const sessionID = this._readSessionID(input); + if (sessionID) { + output.sessionID = sessionID; + } + + output.cipherSuites = this._readCipherSuites(input); + output.compressionMethods = this._readCompressionMethods(input); + output.extensions = this._readExtensions(input); + + return output; + } + + /** + * Reads the client_version field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw ClientHello message, with position before client_version field. + * @returns {string} Hex representation of client_version. + */ + _readClientVersion(input) { + return readBytesAsHex(input, 2); + } + + /** + * Reads the random field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw ClientHello message, with position before random field. + * @returns {string} Hex representation of random. + */ + _readRandom(input) { + return readBytesAsHex(input, 32); + } + + /** + * Reads the session_id field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw ClientHello message, with position before session_id length field. + * @returns {string} Hex representation of session_id, or empty string if session_id not present. + */ + _readSessionID(input) { + return readSizePrefixedBytesAsHex(input, 1); + } + + /** + * Reads the cipher_suites field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw ClientHello message, with position before cipher_suites length field. + * @returns {Object} Object represention of cipher_suites field. + */ + _readCipherSuites(input) { + const output = {}; + + output.length = input.readInt(2); + if (!output.length) { + return {}; + } + + const cipherSuites = new Stream(input.getBytes(output.length)); + if (cipherSuites.length < output.length) { + output.truncated = true; + } + + output.values = []; + + while (cipherSuites.hasMore()) { + const cipherSuite = readBytesAsHex(cipherSuites, 2); + if (cipherSuite) { + output.values.push(cipherSuite); + } + } + + return output; + } + + /** + * Reads the compression_methods field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw ClientHello message, with position before compression_methods length field. + * @returns {Object} Object representation of compression_methods field. + */ + _readCompressionMethods(input) { + const output = {}; + + output.length = input.readInt(1); + if (!output.length) { + return {}; + } + + const compressionMethods = new Stream(input.getBytes(output.length)); + if (compressionMethods.length < output.length) { + output.truncated = true; + } + + output.values = []; + + while (compressionMethods.hasMore()) { + const compressionMethod = readBytesAsHex(compressionMethods, 1); + if (compressionMethod) { + output.values.push(compressionMethod); + } + } + + return output; + } + + /** + * Reads the extensions field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw ClientHello message, with position before extensions length field. + * @returns {Object} Object representations of extensions field. + */ + _readExtensions(input) { + const output = {}; + + output.length = input.readInt(2); + if (!output.length) { + return {}; + } + + const extensions = new Stream(input.getBytes(output.length)); + if (extensions.length < output.length) { + output.truncated = true; + } + + output.values = this._extensionsParser.parse(extensions); + + return output; + } +} + +/** + * Parses TLS Handshake ServeHello messages. + */ +class ServerHelloParser { + + /** + * ServerHelloParser constructor. + */ + constructor() { + this._extensionsParser = new ExtensionsParser(); + } + + /** + * Parses a single TLS Handshake ServerHello message. + * + * @param {Stream} input - Stream, containing a raw ServerHello message. + * @return {Object} Object representation of ServerHello. + */ + parse(input) { + const output = {}; + + output.serverVersion = this._readServerVersion(input); + output.random = this._readRandom(input); + + const sessionID = this._readSessionID(input); + if (sessionID) { + output.sessionID = sessionID; + } + + output.cipherSuite = this._readCipherSuite(input); + output.compressionMethod = this._readCompressionMethod(input); + output.extensions = this._readExtensions(input); + + return output; + } + + /** + * Reads the server_version field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw ServerHello message, with position before server_version field. + * @returns {string} Hex representation of server_version. + */ + _readServerVersion(input) { + return readBytesAsHex(input, 2); + } + + /** + * Reads the random field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw ServerHello message, with position before random field. + * @returns {string} Hex representation of random. + */ + _readRandom(input) { + return readBytesAsHex(input, 32); + } + + /** + * Reads the session_id field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw ServertHello message, with position before session_id length field. + * @returns {string} Hex representation of session_id, or empty string if session_id not present. + */ + _readSessionID(input) { + return readSizePrefixedBytesAsHex(input, 1); + } + + /** + * Reads the cipher_suite field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw ServerHello message, with position before cipher_suite field. + * @returns {string} Hex represention of cipher_suite. + */ + _readCipherSuite(input) { + return readBytesAsHex(input, 2); + } + + /** + * Reads the compression_method field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw ServerHello message, with position before compression_method field. + * @returns {string} Hex represention of compression_method. + */ + _readCompressionMethod(input) { + return readBytesAsHex(input, 1); + } + + /** + * Reads the extensions field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw ServerHello message, with position before extensions length field. + * @returns {Object} Object representation of extensions field. + */ + _readExtensions(input) { + const output = {}; + + output.length = input.readInt(2); + if (!output.length) { + return {}; + } + + const extensions = new Stream(input.getBytes(output.length)); + if (extensions.length < output.length) { + output.truncated = true; + } + + output.values = this._extensionsParser.parse(extensions); + + return output; + } +} + +/** + * Parses TLS Handshake Hello Extensions. + */ +class ExtensionsParser { + + /** + * Parses a stream of TLS Handshake Hello Extensions. + * + * @param {Stream} input - Stream, containing multiple raw Extensions, with position before first extension length field. + * @returns {Object[]} Array of Object representations of Extensions contained within input. + */ + parse(input) { + const output = []; + + while (input.hasMore()) { + const extension = this._readExtension(input); + if (extension) { + output.push(extension); + } + } + + return output; + } + + /** + * Reads a single Extension from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a list of Extensions, with position before the length field of the next Extension. + * @returns {Object} Object representation of Extension. + */ + _readExtension(input) { + const output = {}; + + if (input.position + 4 > input.length) { + input.moveTo(input.length); + return null; + } + + output.type = "0x" + toHexFast(input.getBytes(2)); + output.length = input.readInt(2); + if (!output.length) { + return output; + } + + const value = input.getBytes(output.length); + if (!value || value.length !== output.length) { + output.truncated = true; + } + + if (value && value.length) { + output.value = "0x" + toHexFast(value); + } + + return output; + } +} + +/** + * Parses TLS Handshake NewSessionTicket messages. + */ +class NewSessionTicketParser { + + /** + * Parses a single TLS Handshake NewSessionTicket message. + * + * @param {Stream} input - Stream, containing a raw NewSessionTicket message. + * @returns {Object} Object representation of NewSessionTicket. + */ + parse(input) { + return { + ticketLifetimeHint: this._readTicketLifetimeHint(input), + ticket: this._readTicket(input), + }; + } + + /** + * Reads the ticket_lifetime_hint field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw NewSessionTicket message, with position before ticket_lifetime_hint field. + * @returns {string} Lifetime hint, in seconds. + */ + _readTicketLifetimeHint(input) { + if (input.position + 4 > input.length) { + input.moveTo(input.length); + return ""; + } + + return input.readInt(4) + "s"; + } + + /** + * Reads the ticket field fromt the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw NewSessionTicket message, with position before ticket length field. + * @returns {string} Hex representation of ticket. + */ + _readTicket(input) { + return readSizePrefixedBytesAsHex(input, 2); + } +} + +/** + * Parses TLS Handshake Certificate messages. + */ +class CertificateParser { + + /** + * Parses a single TLS Handshake Certificate message. + * + * @param {Stream} input - Stream, containing a raw Certificate message. + * @returns {Object} Object representation of Certificate. + */ + parse(input) { + const output = {}; + + output.certificateList = this._readCertificateList(input); + + return output; + } + + /** + * Reads the certificate_list field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw Certificate message, with position before certificate_list length field. + * @returns {string[]} Array of strings, each containing a hex representation of a value within the certificate_list field. + */ + _readCertificateList(input) { + const output = {}; + + if (input.position + 3 > input.length) { + input.moveTo(input.length); + return output; + } + + output.length = input.readInt(3); + if (!output.length) { + return output; + } + + const certificates = new Stream(input.getBytes(output.length)); + if (certificates.length < output.length) { + output.truncated = true; + } + + output.values = []; + + while (certificates.hasMore()) { + const certificate = this._readCertificate(certificates); + if (certificate) { + output.values.push(certificate); + } + } + + return output; + } + + /** + * Reads a single certificate from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a list of certificicates, with position before the length field of the next certificate. + * @returns {string} Hex representation of certificate. + */ + _readCertificate(input) { + return readSizePrefixedBytesAsHex(input, 3); + } +} + +/** + * Parses TLS Handshake CertificateRequest messages. + */ +class CertificateRequestParser { + + /** + * Parses a single TLS Handshake CertificateRequest message. + * + * @param {Stream} input - Stream, containing a raw CertificateRequest message. + * @return {Object} Object representation of CertificateRequest. + */ + parse(input) { + const output = {}; + + output.certificateTypes = this._readCertificateTypes(input); + output.supportedSignatureAlgorithms = this._readSupportedSignatureAlgorithms(input); + + const certificateAuthorities = this._readCertificateAuthorities(input); + if (certificateAuthorities.length) { + output.certificateAuthorities = certificateAuthorities; + } + + return output; + } + + /** + * Reads the certificate_types field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw CertificateRequest message, with position before certificate_types length field. + * @return {string[]} Array of strings, each containing a hex representation of a value within the certificate_types field. + */ + _readCertificateTypes(input) { + const output = {}; + + output.length = input.readInt(1); + if (!output.length) { + return {}; + } + + const certificateTypes = new Stream(input.getBytes(output.length)); + if (certificateTypes.length < output.length) { + output.truncated = true; + } + + output.values = []; + + while (certificateTypes.hasMore()) { + const certificateType = readBytesAsHex(certificateTypes, 1); + if (certificateType) { + output.values.push(certificateType); + } + } + + return output; + } + + /** + * Reads the supported_signature_algorithms field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw CertificateRequest message, with position before supported_signature_algorithms length field. + * @returns {string[]} Array of strings, each containing a hex representation of a value within the supported_signature_algorithms field. + */ + _readSupportedSignatureAlgorithms(input) { + const output = {}; + + output.length = input.readInt(2); + if (!output.length) { + return {}; + } + + const signatureAlgorithms = new Stream(input.getBytes(output.length)); + if (signatureAlgorithms.length < output.length) { + output.truncated = true; + } + + output.values = []; + + while (signatureAlgorithms.hasMore()) { + const signatureAlgorithm = readBytesAsHex(signatureAlgorithms, 2); + if (signatureAlgorithm) { + output.values.push(signatureAlgorithm); + } + } + + return output; + } + + /** + * Reads the certificate_authorities field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw CertificateRequest message, with position before certificate_authorities length field. + * @returns {string[]} Array of strings, each containing a hex representation of a value within the certificate_authorities field. + */ + _readCertificateAuthorities(input) { + const output = {}; + + output.length = input.readInt(2); + if (!output.length) { + return {}; + } + + const certificateAuthorities = new Stream(input.getBytes(output.length)); + if (certificateAuthorities.length < output.length) { + output.truncated = true; + } + + output.values = []; + + while (certificateAuthorities.hasMore()) { + const certificateAuthority = this._readCertificateAuthority(certificateAuthorities); + if (certificateAuthority) { + output.values.push(certificateAuthority); + } + } + + return output; + } + + /** + * Reads a single certificate authority from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a list of raw certificate authorities, with position before the length field of the next certificate authority. + * @returns {string} Hex representation of certificate authority. + */ + _readCertificateAuthority(input) { + return readSizePrefixedBytesAsHex(input, 2); + } +} + +/** + * Parses TLS Handshake CertificateVerify messages. + */ +class CertificateVerifyParser { + + /** + * Parses a single CertificateVerify Message. + * + * @param {Stream} input - Stream, containing a raw CertificateVerify message. + * @returns {Object} Object representation of CertificateVerify. + */ + parse(input) { + return { + algorithmHash: this._readAlgorithmHash(input), + algorithmSignature: this._readAlgorithmSignature(input), + signature: this._readSignature(input), + }; + } + + /** + * Reads the algorithm.hash field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw CertificateVerify message, with position before algorithm.hash field. + * @return {string} Hex representation of hash algorithm. + */ + _readAlgorithmHash(input) { + return readBytesAsHex(input, 1); + } + + /** + * Reads the algorithm.signature field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw CertificateVerify message, with position before algorithm.signature field. + * @return {string} Hex representation of signature algorithm. + */ + _readAlgorithmSignature(input) { + return readBytesAsHex(input, 1); + } + + /** + * Reads the signature field from the following bytes in the provided Stream. + * + * @param {Stream} input - Stream, containing a raw CertificateVerify message, with position before signature field. + * @return {string} Hex representation of signature. + */ + _readSignature(input) { + return readSizePrefixedBytesAsHex(input, 2); + } +} + +/** + * Read the following size prefixed bytes from the provided Stream, and reuturn as a hex string. + * + * @param {Stream} input - Stream to read from. + * @param {int} sizePrefixLength - Length of the size prefix field. + * @returns {string} Hex representation of bytes read from Stream, empty string is returned if + * field cannot be read in full. + */ +function readSizePrefixedBytesAsHex(input, sizePrefixLength) { + const length = input.readInt(sizePrefixLength); + if (!length) { + return ""; + } + + return readBytesAsHex(input, length); +} + +/** + * Read n bytes from the provided Stream, and return as a hex string. + * + * @param {Stream} input - Stream to read from. + * @param {int} n - Number of bytes to read. + * @returns {string} Hex representation of bytes read from Stream, or empty string if field cannot + * be read in full. + */ +function readBytesAsHex(input, n) { + const bytes = input.getBytes(n); + if (!bytes || bytes.length !== n) { + return ""; + } + + return "0x" + toHexFast(bytes); +} diff --git a/plugins/srktoolbox/src/core/operations/ParseTLV.mjs b/plugins/srktoolbox/src/core/operations/ParseTLV.mjs new file mode 100644 index 00000000..dbb89f7e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseTLV.mjs @@ -0,0 +1,79 @@ +/** + * @author gchq77703 [] + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import TLVParser from "../lib/TLVParser.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Parse TLV operation + */ +class ParseTLV extends Operation { + + /** + * ParseTLV constructor + */ + constructor() { + super(); + + this.name = "解析TLV"; + this.module = "Default"; + this.description = "把Type-Length-Value (TLV)编码的字符串转换为JSON对象。可选包含一个 Key / Type 字段。

标签: Key-Length-Value, KLV, Length-Value, LV"; + this.infoURL = "https://wikipedia.org/wiki/Type-length-value"; + this.inputType = "ArrayBuffer"; + this.outputType = "JSON"; + this.args = [ + { + name: "Type/Key大小", + type: "number", + value: 1 + }, + { + name: "Length大小", + type: "number", + value: 1 + }, + { + name: "使用BER", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [bytesInKey, bytesInLength, basicEncodingRules] = args; + input = new Uint8Array(input); + + if (bytesInKey <= 0 && bytesInLength <= 0) + throw new OperationError("Type或Length大小必须大于0"); + + const tlv = new TLVParser(input, { bytesInLength, basicEncodingRules }); + + const data = []; + + while (!tlv.atEnd()) { + const key = bytesInKey ? tlv.getValue(bytesInKey) : undefined; + const length = tlv.getLength(); + const value = tlv.getValue(length); + + data.push({ key, length, value }); + } + + return data; + } + +} + +export default ParseTLV; diff --git a/plugins/srktoolbox/src/core/operations/ParseUDP.mjs b/plugins/srktoolbox/src/core/operations/ParseUDP.mjs new file mode 100644 index 00000000..a80bf46d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseUDP.mjs @@ -0,0 +1,91 @@ +/** + * @author h345983745 [] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Stream from "../lib/Stream.mjs"; +import {toHexFast, fromHex} from "../lib/Hex.mjs"; +import {objToTable} from "../lib/Protocol.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Parse UDP operation + */ +class ParseUDP extends Operation { + + /** + * ParseUDP constructor + */ + constructor() { + super(); + + this.name = "解析UDP"; + this.module = "Default"; + this.description = "解析UDP标头和载荷(如果有)。"; + this.infoURL = "https://wikipedia.org/wiki/User_Datagram_Protocol"; + this.inputType = "string"; + this.outputType = "json"; + this.presentType = "html"; + this.args = [ + { + name: "输入格式", + type: "option", + value: ["十六进制", "原始"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {Object} + */ + run(input, args) { + const format = args[0]; + + if (format === "十六进制") { + input = fromHex(input); + } else if (format === "原始") { + input = Utils.strToArrayBuffer(input); + } else { + throw new OperationError("未知的输入格式"); + } + + const s = new Stream(new Uint8Array(input)); + if (s.length < 8) { + throw new OperationError("UDP标头需要至少8字节。"); + } + + // Parse Header + const UDPPacket = { + "来源连接端口": s.readInt(2), + "目的连接端口": s.readInt(2), + "长度": s.readInt(2), + "校验和": "0x" + toHexFast(s.getBytes(2)) + }; + // Parse data if present + if (s.hasMore()) { + UDPPacket.数据 = "0x" + toHexFast(s.getBytes(UDPPacket.长度 - 8)); + } + + return UDPPacket; + } + + /** + * Displays the UDP Packet in a tabular style + * @param {Object} data + * @returns {html} + */ + present(data) { + return objToTable(data); + } + +} + + +export default ParseUDP; diff --git a/plugins/srktoolbox/src/core/operations/ParseUNIXFilePermissions.mjs b/plugins/srktoolbox/src/core/operations/ParseUNIXFilePermissions.mjs new file mode 100644 index 00000000..11919965 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseUNIXFilePermissions.mjs @@ -0,0 +1,334 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Parse UNIX file permissions operation + */ +class ParseUNIXFilePermissions extends Operation { + + /** + * ParseUNIXFilePermissions constructor + */ + constructor() { + super(); + + this.name = "解析UNIX文件权限"; + this.module = "Default"; + this.description = "根据UNIX/Linux文件权限字符串(八进制或文本形式),解释具体什么权限赋给了谁。

输入必须为八进制(例如 755)或文本(例如 drwxr-xr-x)格式。"; + this.infoURL = "https://wikipedia.org/wiki/File_system_permissions#Traditional_Unix_permissions"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + this.checks = [ + { + pattern: "^\\s*d[rxw-]{9}\\s*$", + flags: "", + args: [] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const perms = { + d: false, // directory + sl: false, // symbolic link + np: false, // named pipe + s: false, // socket + cd: false, // character device + bd: false, // block device + dr: false, // door + sb: false, // sticky bit + su: false, // setuid + sg: false, // setgid + ru: false, // read user + wu: false, // write user + eu: false, // execute user + rg: false, // read group + wg: false, // write group + eg: false, // execute group + ro: false, // read other + wo: false, // write other + eo: false // execute other + }; + let d = 0, + u = 0, + g = 0, + o = 0, + output = "", + octal = null, + textual = null; + + if (input.search(/\s*[0-7]{1,4}\s*/i) === 0) { + // Input is octal + octal = input.match(/\s*([0-7]{1,4})\s*/i)[1]; + + if (octal.length === 4) { + d = parseInt(octal[0], 8); + u = parseInt(octal[1], 8); + g = parseInt(octal[2], 8); + o = parseInt(octal[3], 8); + } else { + if (octal.length > 0) u = parseInt(octal[0], 8); + if (octal.length > 1) g = parseInt(octal[1], 8); + if (octal.length > 2) o = parseInt(octal[2], 8); + } + + perms.su = d >> 2 & 0x1; + perms.sg = d >> 1 & 0x1; + perms.sb = d & 0x1; + + perms.ru = u >> 2 & 0x1; + perms.wu = u >> 1 & 0x1; + perms.eu = u & 0x1; + + perms.rg = g >> 2 & 0x1; + perms.wg = g >> 1 & 0x1; + perms.eg = g & 0x1; + + perms.ro = o >> 2 & 0x1; + perms.wo = o >> 1 & 0x1; + perms.eo = o & 0x1; + } else if (input.search(/\s*[dlpcbDrwxsStT-]{1,10}\s*/) === 0) { + // Input is textual + textual = input.match(/\s*([dlpcbDrwxsStT-]{1,10})\s*/)[1]; + + switch (textual[0]) { + case "d": + perms.d = true; + break; + case "l": + perms.sl = true; + break; + case "p": + perms.np = true; + break; + case "s": + perms.s = true; + break; + case "c": + perms.cd = true; + break; + case "b": + perms.bd = true; + break; + case "D": + perms.dr = true; + break; + } + + if (textual.length > 1) perms.ru = textual[1] === "r"; + if (textual.length > 2) perms.wu = textual[2] === "w"; + if (textual.length > 3) { + switch (textual[3]) { + case "x": + perms.eu = true; + break; + case "s": + perms.eu = true; + perms.su = true; + break; + case "S": + perms.su = true; + break; + } + } + + if (textual.length > 4) perms.rg = textual[4] === "r"; + if (textual.length > 5) perms.wg = textual[5] === "w"; + if (textual.length > 6) { + switch (textual[6]) { + case "x": + perms.eg = true; + break; + case "s": + perms.eg = true; + perms.sg = true; + break; + case "S": + perms.sg = true; + break; + } + } + + if (textual.length > 7) perms.ro = textual[7] === "r"; + if (textual.length > 8) perms.wo = textual[8] === "w"; + if (textual.length > 9) { + switch (textual[9]) { + case "x": + perms.eo = true; + break; + case "t": + perms.eo = true; + perms.sb = true; + break; + case "T": + perms.sb = true; + break; + } + } + } else { + throw new OperationError("无效的输入格式。\n请输入八进制形式(例如:755)或文本形式(例如:drwxr-xr-x)。"); + } + + output += "文本形式: " + permsToStr(perms); + output += "\n八进制形式: " + permsToOctal(perms); + + // File type + if (textual) { + output += "\n文件类型: " + ftFromPerms(perms); + } + + // setuid, setgid + if (perms.su) { + output += "\n设置了SUID(setuid)权限"; + } + if (perms.sg) { + output += "\n设置了SGID(setgid)权限"; + } + + // sticky bit + if (perms.sb) { + output += "\n设置了SBIT(sticky bit)权限"; + } + + // Permission matrix + output += ` + + +---------+-------+-------+-------+ + | | 用户 | 组 | 其它 | + +---------+-------+-------+-------+ + | 读 | ${perms.ru ? "X" : " "} | ${perms.rg ? "X" : " "} | ${perms.ro ? "X" : " "} | + +---------+-------+-------+-------+ + | 写 | ${perms.wu ? "X" : " "} | ${perms.wg ? "X" : " "} | ${perms.wo ? "X" : " "} | + +---------+-------+-------+-------+ + | 执行 | ${perms.eu ? "X" : " "} | ${perms.eg ? "X" : " "} | ${perms.eo ? "X" : " "} | + +---------+-------+-------+-------+`; + + return output; + } + +} + + +/** + * Given a permissions object dictionary, generates a textual permissions string. + * + * @param {Object} perms + * @returns {string} + */ +function permsToStr(perms) { + let str = "", + type = "-"; + + if (perms.d) type = "d"; + if (perms.sl) type = "l"; + if (perms.np) type = "p"; + if (perms.s) type = "s"; + if (perms.cd) type = "c"; + if (perms.bd) type = "b"; + if (perms.dr) type = "D"; + + str = type; + + str += perms.ru ? "r" : "-"; + str += perms.wu ? "w" : "-"; + if (perms.eu && perms.su) { + str += "s"; + } else if (perms.su) { + str += "S"; + } else if (perms.eu) { + str += "x"; + } else { + str += "-"; + } + + str += perms.rg ? "r" : "-"; + str += perms.wg ? "w" : "-"; + if (perms.eg && perms.sg) { + str += "s"; + } else if (perms.sg) { + str += "S"; + } else if (perms.eg) { + str += "x"; + } else { + str += "-"; + } + + str += perms.ro ? "r" : "-"; + str += perms.wo ? "w" : "-"; + if (perms.eo && perms.sb) { + str += "t"; + } else if (perms.sb) { + str += "T"; + } else if (perms.eo) { + str += "x"; + } else { + str += "-"; + } + + return str; +} + +/** + * Given a permissions object dictionary, generates an octal permissions string. + * + * @param {Object} perms + * @returns {string} + */ +function permsToOctal(perms) { + let d = 0, + u = 0, + g = 0, + o = 0; + + if (perms.su) d += 4; + if (perms.sg) d += 2; + if (perms.sb) d += 1; + + if (perms.ru) u += 4; + if (perms.wu) u += 2; + if (perms.eu) u += 1; + + if (perms.rg) g += 4; + if (perms.wg) g += 2; + if (perms.eg) g += 1; + + if (perms.ro) o += 4; + if (perms.wo) o += 2; + if (perms.eo) o += 1; + + return d.toString() + u.toString() + g.toString() + o.toString(); +} + + +/** + * Given a permissions object dictionary, returns the file type. + * + * @param {Object} perms + * @returns {string} + */ +function ftFromPerms(perms) { + if (perms.d) return "目录"; + if (perms.sl) return "符号链接"; + if (perms.np) return "管道"; + if (perms.s) return "套接字"; + if (perms.cd) return "字符设备"; + if (perms.bd) return "块设备"; + if (perms.dr) return "Door"; + return "普通文件"; +} + +export default ParseUNIXFilePermissions; diff --git a/plugins/srktoolbox/src/core/operations/ParseURI.mjs b/plugins/srktoolbox/src/core/operations/ParseURI.mjs new file mode 100644 index 00000000..ecc5f76d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseURI.mjs @@ -0,0 +1,72 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import url from "url"; + +/** + * Parse URI operation + */ +class ParseURI extends Operation { + + /** + * ParseURI constructor + */ + constructor() { + super(); + + this.name = "解析URI"; + this.module = "URL"; + this.description = "将复杂的Uniform Resource Identifier (URI)字符串解析成容易阅读的形式。可用于查看有较多参数的Uniform Resource Locator (URL)。"; + this.infoURL = "https://wikipedia.org/wiki/Uniform_Resource_Identifier"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const uri = url.parse(input, true); + + let output = ""; + + if (uri.protocol) output += "协议:\t" + uri.protocol + "\n"; + if (uri.auth) output += "鉴权:\t\t" + uri.auth + "\n"; + if (uri.hostname) output += "主机名称:\t" + uri.hostname + "\n"; + if (uri.port) output += "端口:\t\t" + uri.port + "\n"; + if (uri.pathname) output += "路径名称:\t" + uri.pathname + "\n"; + if (uri.query) { + const keys = Object.keys(uri.query); + let padding = 0; + + keys.forEach(k => { + padding = (k.length > padding) ? k.length : padding; + }); + + output += "参数:\n"; + for (const key in uri.query) { + output += "\t" + key.padEnd(padding, " "); + if (uri.query[key].length) { + output += " = " + uri.query[key] + "\n"; + } else { + output += "\n"; + } + } + } + if (uri.hash) output += "哈希值:\t\t" + uri.hash + "\n"; + + return output; + } + +} + +export default ParseURI; diff --git a/plugins/srktoolbox/src/core/operations/ParseUserAgent.mjs b/plugins/srktoolbox/src/core/operations/ParseUserAgent.mjs new file mode 100644 index 00000000..b676b55e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseUserAgent.mjs @@ -0,0 +1,65 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import UAParser from "ua-parser-js"; + +/** + * Parse User Agent operation + */ +class ParseUserAgent extends Operation { + + /** + * ParseUserAgent constructor + */ + constructor() { + super(); + + this.name = "解析User Agent"; + this.module = "UserAgent"; + this.description = "尝试对User-Agent字符串中的内容进行解析。"; + this.infoURL = "https://wikipedia.org/wiki/User_agent"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + this.checks = [ + { + pattern: "^(User-Agent:|Mozilla\\/)[^\\n\\r]+\\s*$", + flags: "i", + args: [] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const ua = UAParser(input); + return `浏览器 + 名称: ${ua.browser.name || "未知"} + 版本: ${ua.browser.version || "未知"} +设备 + 型号: ${ua.device.model || "未知"} + 类型: ${ua.device.type || "未知"} + 厂商: ${ua.device.vendor || "未知"} +内核 + 名称: ${ua.engine.name || "未知"} + 版本: ${ua.engine.version || "未知"} +操作系统 + 名称: ${ua.os.name || "未知"} + 版本: ${ua.os.version || "未知"} +CPU + 架构: ${ua.cpu.architecture || "未知"}`; + } + +} + +export default ParseUserAgent; diff --git a/plugins/srktoolbox/src/core/operations/ParseX509CRL.mjs b/plugins/srktoolbox/src/core/operations/ParseX509CRL.mjs new file mode 100644 index 00000000..c1431986 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseX509CRL.mjs @@ -0,0 +1,393 @@ +/** + * @author robinsandhu + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import r from "jsrsasign"; +import Operation from "../Operation.mjs"; +import { fromBase64 } from "../lib/Base64.mjs"; +import { toHex } from "../lib/Hex.mjs"; +import { formatDnObj } from "../lib/PublicKey.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Parse X.509 CRL operation + */ +class ParseX509CRL extends Operation { + + /** + * ParseX509CRL constructor + */ + constructor() { + super(); + + this.name = "解析X.509证书吊销列表"; + this.module = "PublicKey"; + this.description = "解析证书吊销列表(Certificate Revocation List,CRL)"; + this.infoURL = "https://wikipedia.org/wiki/Certificate_revocation_list"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "输入格式", + "type": "option", + "value": ["PEM", "DER十六进制", "Base64", "原始"] + } + ]; + this.checks = [ + { + "pattern": "^-+BEGIN X509 CRL-+\\r?\\n[\\da-z+/\\n\\r]+-+END X509 CRL-+\\r?\\n?$", + "flags": "i", + "args": ["PEM"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} Human-readable description of a Certificate Revocation List (CRL). + */ + run(input, args) { + if (!input.length) { + return "输入内容为空"; + } + + const inputFormat = args[0]; + + let undefinedInputFormat = false; + try { + switch (inputFormat) { + case "DER十六进制": + input = input.replace(/\s/g, "").toLowerCase(); + break; + case "PEM": + break; + case "Base64": + input = toHex(fromBase64(input, null, "byteArray"), ""); + break; + case "原始": + input = toHex(Utils.strToArrayBuffer(input), ""); + break; + default: + undefinedInputFormat = true; + } + } catch (e) { + throw "证书加载错误(请确保输入内容为证书)"; + } + if (undefinedInputFormat) throw "未知的输入格式"; + + const crl = new r.X509CRL(input); + + let out = `证书吊销列表 (CRL): + 版本: ${crl.getVersion() === null ? "1 (0x0)" : "2 (0x1)"} + 签名算法: ${crl.getSignatureAlgorithmField()} + 颁发者:\n${formatDnObj(crl.getIssuer(), 8)} + 最近更新: ${generalizedDateTimeToUTC(crl.getThisUpdate())} + 下次更新: ${generalizedDateTimeToUTC(crl.getNextUpdate())}\n`; + + if (crl.getParam().ext !== undefined) { + out += `\tCRL扩展:\n${formatCRLExtensions(crl.getParam().ext, 8)}\n`; + } + + out += `已吊销的证书:\n${formatRevokedCertificates(crl.getRevCertArray(), 4)} +签名值:\n${formatCRLSignature(crl.getSignatureValueHex(), 8)}`; + + return out; + } +} + +/** + * Generalized date time string to UTC. + * @param {string} datetime + * @returns UTC datetime string. + */ +function generalizedDateTimeToUTC(datetime) { + // Ensure the string is in the correct format + if (!/^\d{12,14}Z$/.test(datetime)) { + throw new OperationError(`datetime字符串 ${datetime} 构造失败`); + } + + // Extract components + let centuary = "20"; + if (datetime.length === 15) { + centuary = datetime.substring(0, 2); + datetime = datetime.slice(2); + } + const year = centuary + datetime.substring(0, 2); + const month = datetime.substring(2, 4); + const day = datetime.substring(4, 6); + const hour = datetime.substring(6, 8); + const minute = datetime.substring(8, 10); + const second = datetime.substring(10, 12); + + // Construct ISO 8601 format string + const isoString = `${year}-${month}-${day}T${hour}:${minute}:${second}Z`; + + // Parse using standard Date object + const isoDateTime = new Date(isoString); + + return isoDateTime.toUTCString(); +} + +/** + * Format CRL extensions. + * @param {r.ExtParam[] | undefined} extensions + * @param {Number} indent + * @returns Formatted string detailing CRL extensions. + */ +function formatCRLExtensions(extensions, indent) { + if (Array.isArray(extensions) === false || extensions.length === 0) { + return indentString(`无CRL扩展。`, indent); + } + + let out = ``; + + extensions.sort((a, b) => { + if (!Object.hasOwn(a, "extname") || !Object.hasOwn(b, "extname")) { + return 0; + } + if (a.extname < b.extname) { + return -1; + } else if (a.extname === b.extname) { + return 0; + } else { + return 1; + } + }); + + extensions.forEach((ext) => { + if (!Object.hasOwn(ext, "extname")) { + throw new OperationError(`CRL条目扩展对象缺少'extname'键: ${ext}`); + } + switch (ext.extname) { + case "authorityKeyIdentifier": + out += `X509v3 颁发机构密钥标识符:\n`; + if (Object.hasOwn(ext, "kid")) { + out += `\tkeyid:${colonDelimitedHexFormatString(ext.kid.hex.toUpperCase())}\n`; + } + if (Object.hasOwn(ext, "issuer")) { + out += `\tDirName:${ext.issuer.str}\n`; + } + if (Object.hasOwn(ext, "sn")) { + out += `\tserial:${colonDelimitedHexFormatString(ext.sn.hex.toUpperCase())}\n`; + } + break; + case "cRLDistributionPoints": + out += `X509v3 CRL分发点:\n`; + ext.array.forEach((distPoint) => { + const fullName = `全名:\n${formatGeneralNames(distPoint.dpname.full, 4)}`; + out += indentString(fullName, 4) + "\n"; + }); + break; + case "cRLNumber": + if (!Object.hasOwn(ext, "num")) { + throw new OperationError(`'cRLNumber' CRL条目扩展缺少'num'键: ${ext}`); + } + out += `X509v3 CRL号码:\n\t${ext.num.hex.toUpperCase()}\n`; + break; + case "issuerAltName": + out += `X509v3 颁发者别名:\n${formatGeneralNames(ext.array, 4)}\n`; + break; + default: + out += `${ext.extname}:\n`; + out += `\t不支持的CRL扩展。试试Openssl命令行。\n`; + break; + } + }); + + return indentString(chop(out), indent); +} + +/** + * Format general names array. + * @param {Object[]} names + * @returns Multi-line formatted string describing all supported general name types. + */ +function formatGeneralNames(names, indent) { + let out = ``; + + names.forEach((name) => { + const key = Object.keys(name)[0]; + + switch (key) { + case "ip": + out += `IP:${name.ip}\n`; + break; + case "dns": + out += `DNS:${name.dns}\n`; + break; + case "uri": + out += `URI:${name.uri}\n`; + break; + case "rfc822": + out += `EMAIL:${name.rfc822}\n`; + break; + case "dn": + out += `DIR:${name.dn.str}\n`; + break; + case "other": + out += `OtherName:${name.other.oid}::${Object.values(name.other.value)[0].str}\n`; + break; + default: + out += `${key}: 不支持的通用名称类型`; + break; + } + }); + + return indentString(chop(out), indent); +} + +/** + * Colon-delimited hex formatted output. + * @param {string} hexString Hex String + * @returns String representing input hex string with colon delimiter. + */ +function colonDelimitedHexFormatString(hexString) { + if (hexString.length % 2 !== 0) { + hexString = "0" + hexString; + } + + return chop(hexString.replace(/(..)/g, "$&:")); +} + +/** + * Format revoked certificates array + * @param {r.RevokedCertificate[] | null} revokedCertificates + * @param {Number} indent + * @returns Multi-line formatted string output of revoked certificates array + */ +function formatRevokedCertificates(revokedCertificates, indent) { + if (Array.isArray(revokedCertificates) === false || revokedCertificates.length === 0) { + return indentString("没有被吊销的证书。", indent); + } + + let out=``; + + revokedCertificates.forEach((revCert) => { + if (!Object.hasOwn(revCert, "sn") || !Object.hasOwn(revCert, "date")) { + throw new OperationError("无效的吊销证书对象,缺少序列号或日期。"); + } + + out += `序列号: ${revCert.sn.hex.toUpperCase()} + 吊销日期: ${generalizedDateTimeToUTC(revCert.date)}\n`; + if (Object.hasOwn(revCert, "ext") && Array.isArray(revCert.ext) && revCert.ext.length !== 0) { + out += `\tCRL条目扩展:\n${indentString(formatCRLEntryExtensions(revCert.ext), 2*indent)}\n`; + } + }); + + return indentString(chop(out), indent); +} + +/** + * Format CRL entry extensions. + * @param {Object[]} exts + * @returns Formatted multi-line string describing CRL entry extensions. + */ +function formatCRLEntryExtensions(exts) { + let out = ``; + + const crlReasonCodeToReasonMessage = { + 0: "Unspecified", + 1: "Key Compromise", + 2: "CA Compromise", + 3: "Affiliation Changed", + 4: "Superseded", + 5: "Cessation Of Operation", + 6: "Certificate Hold", + 8: "Remove From CRL", + 9: "Privilege Withdrawn", + 10: "AA Compromise", + }; + + const holdInstructionOIDToName = { + "1.2.840.10040.2.1": "Hold Instruction None", + "1.2.840.10040.2.2": "Hold Instruction Call Issuer", + "1.2.840.10040.2.3": "Hold Instruction Reject", + }; + + exts.forEach((ext) => { + if (!Object.hasOwn(ext, "extname")) { + throw new OperationError(`CRL条目扩展对象缺少'extname'键: ${ext}`); + } + switch (ext.extname) { + case "cRLReason": + if (!Object.hasOwn(ext, "code")) { + throw new OperationError(`'cRLReason' CRL条目扩展对象缺少'code'键: ${ext}`); + } + out += `X509v3 CRL原因编码: + ${Object.hasOwn(crlReasonCodeToReasonMessage, ext.code) ? crlReasonCodeToReasonMessage[ext.code] : `无效的原因编码: ${ext.code}`}\n`; + break; + case "2.5.29.23": // Hold instruction + out += `持有指令代码:\n\t${Object.hasOwn(holdInstructionOIDToName, ext.extn.oid) ? holdInstructionOIDToName[ext.extn.oid] : `${ext.extn.oid}: 未知的持有指令OID`}\n`; + break; + case "2.5.29.24": // Invalidity Date + out += `失效日期:\n\t${generalizedDateTimeToUTC(ext.extn.gentime.str)}\n`; + break; + default: + out += `${ext.extname}:\n`; + out += `\t不支持的CRL扩展。试试Openssl命令行。\n`; + break; + } + }); + + return chop(out); +} + +/** + * Format CRL signature. + * @param {String} sigHex + * @param {Number} indent + * @returns String representing hex signature value formatted on multiple lines. + */ +function formatCRLSignature(sigHex, indent) { + if (sigHex.length % 2 !== 0) { + sigHex = "0" + sigHex; + } + + return indentString(formatMultiLine(chop(sigHex.replace(/(..)/g, "$&:"))), indent); +} + +/** + * Format string onto multiple lines. + * @param {string} longStr + * @returns String as a multi-line string. + */ +function formatMultiLine(longStr) { + const lines = []; + + for (let remain = longStr ; remain !== "" ; remain = remain.substring(54)) { + lines.push(remain.substring(0, 54)); + } + + return lines.join("\n"); +} + +/** + * Indent a multi-line string by n spaces. + * @param {string} input String + * @param {number} spaces How many leading spaces + * @returns Indented string. + */ +function indentString(input, spaces) { + const indent = " ".repeat(spaces); + return input.replace(/^/gm, indent); +} + +/** + * Remove last character from a string. + * @param {string} s String + * @returns Chopped string. + */ +function chop(s) { + if (s.length < 1) { + return s; + } + return s.substring(0, s.length - 1); +} + +export default ParseX509CRL; diff --git a/plugins/srktoolbox/src/core/operations/ParseX509Certificate.mjs b/plugins/srktoolbox/src/core/operations/ParseX509Certificate.mjs new file mode 100644 index 00000000..8c7a1386 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ParseX509Certificate.mjs @@ -0,0 +1,233 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import r from "jsrsasign"; +import { fromBase64 } from "../lib/Base64.mjs"; +import { runHash } from "../lib/Hash.mjs"; +import { fromHex, toHex } from "../lib/Hex.mjs"; +import { formatByteStr, formatDnObj } from "../lib/PublicKey.mjs"; +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Parse X.509 certificate operation + */ +class ParseX509Certificate extends Operation { + + /** + * ParseX509Certificate constructor + */ + constructor() { + super(); + + this.name = "解析X.509证书"; + this.module = "PublicKey"; + this.description = "X.509是密码学里公钥证书的格式标准。X.509证书已应用在包括TLS/SSL在内的众多网络协议里,同时它也用在很多非在线应用场景里,比如电子签名服务。

此操作把证书内容显示为人类可读的形式,和openssl命令行的效果类似。

标签: X509, server hello, handshake"; + this.infoURL = "https://wikipedia.org/wiki/X.509"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "输入格式", + "type": "option", + "value": ["PEM", "DER十六进制", "Base64", "原始"] + } + ]; + this.checks = [ + { + "pattern": "^-+BEGIN CERTIFICATE-+\\r?\\n[\\da-z+/\\n\\r]+-+END CERTIFICATE-+\\r?\\n?$", + "flags": "i", + "args": ["PEM"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (!input.length) { + return "输入为空"; + } + + const cert = new r.X509(), + inputFormat = args[0]; + + let undefinedInputFormat = false; + try { + switch (inputFormat) { + case "DER十六进制": + input = input.replace(/\s/g, "").toLowerCase(); + cert.readCertHex(input); + break; + case "PEM": + cert.readCertPEM(input); + break; + case "Base64": + cert.readCertHex(toHex(fromBase64(input, null, "byteArray"), "")); + break; + case "原始": + cert.readCertHex(toHex(Utils.strToArrayBuffer(input), "")); + break; + default: + undefinedInputFormat = true; + } + } catch (e) { + throw "证书读取错误(输入内容有误?)"; + } + if (undefinedInputFormat) throw "无效输入格式"; + + const hex = Utils.strToArrayBuffer(Utils.byteArrayToChars(fromHex(cert.hex))), + sn = cert.getSerialNumberHex(), + issuer = cert.getIssuer(), + subject = cert.getSubject(), + pk = cert.getPublicKey(), + pkFields = [], + sig = cert.getSignatureValueHex(); + + let pkStr = "", + sigStr = "", + extensions = ""; + + // Public Key fields + pkFields.push({ + key: "Algorithm", + value: pk.type + }); + + if (pk.type === "EC") { // ECDSA + pkFields.push({ + key: "Curve Name", + value: pk.curveName + }); + pkFields.push({ + key: "Length", + value: (((new r.BigInteger(pk.pubKeyHex, 16)).bitLength()-3) /2) + " bits" + }); + pkFields.push({ + key: "pub", + value: formatByteStr(pk.pubKeyHex, 16, 18) + }); + } else if (pk.type === "DSA") { // DSA + pkFields.push({ + key: "pub", + value: formatByteStr(pk.y.toString(16), 16, 18) + }); + pkFields.push({ + key: "P", + value: formatByteStr(pk.p.toString(16), 16, 18) + }); + pkFields.push({ + key: "Q", + value: formatByteStr(pk.q.toString(16), 16, 18) + }); + pkFields.push({ + key: "G", + value: formatByteStr(pk.g.toString(16), 16, 18) + }); + } else if (pk.e) { // RSA + pkFields.push({ + key: "Length", + value: pk.n.bitLength() + " bits" + }); + pkFields.push({ + key: "Modulus", + value: formatByteStr(pk.n.toString(16), 16, 18) + }); + pkFields.push({ + key: "Exponent", + value: pk.e + " (0x" + pk.e.toString(16) + ")" + }); + } else { + pkFields.push({ + key: "Error", + value: "未知的公钥类型" + }); + } + + // Format Public Key fields + for (let i = 0; i < pkFields.length; i++) { + pkStr += ` ${pkFields[i].key}:${(pkFields[i].value + "\n").padStart( + 18 - (pkFields[i].key.length + 3) + pkFields[i].value.length + 1, + " " + )}`; + } + + // Signature fields + let breakoutSig = false; + try { + breakoutSig = r.ASN1HEX.dump(sig).indexOf("SEQUENCE") === 0; + } catch (err) { + // Error processing signature, output without further breakout + } + + if (breakoutSig) { // DSA or ECDSA + sigStr = ` r: ${formatByteStr(r.ASN1HEX.getV(sig, 4), 16, 18)} + s: ${formatByteStr(r.ASN1HEX.getV(sig, 48), 16, 18)}`; + } else { // RSA or unknown + sigStr = ` 签名: ${formatByteStr(sig, 16, 18)}`; + } + + // Extensions + try { + extensions = cert.getInfo().split("X509v3 Extensions:\n")[1].split("signature")[0]; + } catch (err) {} + + const issuerStr = formatDnObj(issuer, 2), + nbDate = formatDate(cert.getNotBefore()), + naDate = formatDate(cert.getNotAfter()), + subjectStr = formatDnObj(subject, 2); + + return ` +版本: ${cert.version} (0x${Utils.hex(cert.version - 1)}) +序列号: ${new r.BigInteger(sn, 16).toString()} (0x${sn}) +算法ID: ${cert.getSignatureAlgorithmField()} +有效期: + 从: ${nbDate} (dd-mm-yyyy hh:mm:ss) (${cert.getNotBefore()}) + 到: ${naDate} (dd-mm-yyyy hh:mm:ss) (${cert.getNotAfter()}) +颁发者: +${issuerStr} +使用者: +${subjectStr} +指纹信息: + MD5: ${runHash("md5", hex)} + SHA1: ${runHash("sha1", hex)} + SHA256: ${runHash("sha256", hex)} +公钥: +${pkStr.slice(0, -1)} +证书签名: + 算法: ${cert.getSignatureAlgorithmName()} +${sigStr} + +扩展: +${extensions}`; + } + +} + +/** + * Formats dates. + * + * @param {string} dateStr + * @returns {string} + */ +function formatDate (dateStr) { + if (dateStr.length === 13) { // UTC Time + dateStr = (dateStr[0] < "5" ? "20" : "19") + dateStr; + } + return dateStr[6] + dateStr[7] + "/" + + dateStr[4] + dateStr[5] + "/" + + dateStr[0] + dateStr[1] + dateStr[2] + dateStr[3] + " " + + dateStr[8] + dateStr[9] + ":" + + dateStr[10] + dateStr[11] + ":" + + dateStr[12] + dateStr[13]; +} + +export default ParseX509Certificate; diff --git a/plugins/srktoolbox/src/core/operations/PlayMedia.mjs b/plugins/srktoolbox/src/core/operations/PlayMedia.mjs new file mode 100644 index 00000000..46c426e8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PlayMedia.mjs @@ -0,0 +1,103 @@ +/** + * @author anthony-arnold [anthony.arnold@uqconnect.edu.au] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import { fromBase64, toBase64 } from "../lib/Base64.mjs"; +import { fromHex } from "../lib/Hex.mjs"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { isType, detectFileType } from "../lib/FileType.mjs"; + +/** + * PlayMedia operation + */ +class PlayMedia extends Operation { + + /** + * PlayMedia constructor + */ + constructor() { + super(); + + this.name = "播放媒体文件"; + this.module = "Default"; + this.description = "将输入按照音频或视频文件进行播放。

标签: sound, movie, mp3, mp4, mov, webm, wav, ogg"; + this.infoURL = ""; + this.inputType = "string"; + this.outputType = "byteArray"; + this.presentType = "html"; + this.args = [ + { + "name": "输入格式", + "type": "option", + "value": ["原始", "Base64", "十六进制"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} The multimedia data as bytes. + */ + run(input, args) { + const [inputFormat] = args; + + if (!input.length) return []; + + // Convert input to raw bytes + switch (inputFormat) { + case "十六进制": + input = fromHex(input); + break; + case "Base64": + // Don't trust the Base64 entered by the user. + // Unwrap it first, then re-encode later. + input = fromBase64(input, undefined, "byteArray"); + break; + case "原始": + default: + input = Utils.strToByteArray(input); + break; + } + + + // Determine file type + if (!isType(/^(audio|video)/, input)) { + throw new OperationError("无效或不支持的文件类型"); + } + + return input; + } + + /** + * Displays an audio or video element that may be able to play the media + * file. + * + * @param {byteArray} data Data containing an audio or video file. + * @returns {string} Markup to display a media player. + */ + async present(data) { + if (!data.length) return ""; + + const types = detectFileType(data); + const matches = /^audio|video/.exec(types[0].mime); + if (!matches) { + throw new OperationError("无效的文件类型"); + } + const dataURI = `data:${types[0].mime};base64,${toBase64(data)}`; + const element = matches[0]; + + let html = `<${element} src='${dataURI}' type='${types[0].mime}' controls>`; + html += "

不支持的媒体格式。

"; + html += ``; + return html; + } +} + +export default PlayMedia; diff --git a/plugins/srktoolbox/src/core/operations/PowerSet.mjs b/plugins/srktoolbox/src/core/operations/PowerSet.mjs new file mode 100644 index 00000000..b6b00038 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PowerSet.mjs @@ -0,0 +1,95 @@ +/** + * @author d98762625 [d98762625@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Power Set operation + */ +class PowerSet extends Operation { + + /** + * Power set constructor + */ + constructor() { + super(); + + this.name = "幂集"; + this.module = "Default"; + this.description = "计算集合的所有子集"; + this.infoURL = "https://wikipedia.org/wiki/Power_set"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "元素分隔符", + type: "binaryString", + value: "," + }, + ]; + } + + /** + * Generate the power set + * + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + [this.itemDelimiter] = args; + // Split and filter empty strings + const inputArray = input.split(this.itemDelimiter).filter(a => a); + + if (inputArray.length) { + return this.runPowerSet(inputArray); + } + + return ""; + } + + /** + * Return the power set of the inputted set. + * + * @param {Object[]} a + * @returns {Object[]} + */ + runPowerSet(a) { + // empty array items getting picked up + a = a.filter(i => i.length); + if (!a.length) { + return []; + } + + /** + * Decimal to binary function + * @param {*} dec + */ + const toBinary = (dec) => (dec >>> 0).toString(2); + const result = new Set(); + // Get the decimal number to make a binary as long as the input + const maxBinaryValue = parseInt(Number(a.map(i => "1").reduce((p, c) => p + c)), 2); + // Make an array of each binary number from 0 to maximum + const binaries = [...Array(maxBinaryValue + 1).keys()] + .map(toBinary) + .map(i => i.padStart(toBinary(maxBinaryValue).length, "0")); + + // XOR the input with each binary to get each unique permutation + binaries.forEach((binary) => { + const split = binary.split(""); + result.add(a.filter((item, index) => split[index] === "1")); + }); + + // map for formatting & put in length order. + return [...result] + .map(r => r.join(this.itemDelimiter)).sort((a, b) => a.length - b.length) + .map(i => `${i}\n`).join(""); + } +} + +export default PowerSet; diff --git a/plugins/srktoolbox/src/core/operations/ProtobufDecode.mjs b/plugins/srktoolbox/src/core/operations/ProtobufDecode.mjs new file mode 100644 index 00000000..2db1e8c4 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ProtobufDecode.mjs @@ -0,0 +1,67 @@ +/** + * @author GCHQ Contributor [3] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Protobuf from "../lib/Protobuf.mjs"; + +/** + * Protobuf Decode operation + */ +class ProtobufDecode extends Operation { + + /** + * ProtobufDecode constructor + */ + constructor() { + super(); + + this.name = "Protobuf解码"; + this.module = "Protobuf"; + this.description = "将Protobuf编码的数据解码为JSON表示,使用字段数值作为字段key。

如果指定了.proto模式文件,数据将会引用模式文件内容进行解码。只会解码一个消息实例。

显示未知字段
当指定了模式文件时,如果输入数据在模式文件中没有定义,勾选此选项强行显示这些数据。

显示类型
在字段名称旁边显示其类型。对于未定义的字段,显示其Wire Type和示例类型。"; + this.infoURL = "https://wikipedia.org/wiki/Protocol_Buffers"; + this.inputType = "ArrayBuffer"; + this.outputType = "JSON"; + this.args = [ + { + name: "模式文件(Schema,.proto文本)", + type: "text", + value: "", + rows: 8, + hint: "可以直接拖放文件到此位置" + }, + { + name: "显示未知字段", + type: "boolean", + value: false + }, + { + name: "显示类型", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {JSON} + */ + run(input, args) { + input = new Uint8Array(input); + try { + return Protobuf.decode(input, args); + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default ProtobufDecode; diff --git a/plugins/srktoolbox/src/core/operations/ProtobufEncode.mjs b/plugins/srktoolbox/src/core/operations/ProtobufEncode.mjs new file mode 100644 index 00000000..6076ab71 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ProtobufEncode.mjs @@ -0,0 +1,56 @@ +/** + * @author GCHQ Contributor [3] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Protobuf from "../lib/Protobuf.mjs"; + +/** + * Protobuf Encode operation + */ +class ProtobufEncode extends Operation { + + /** + * ProtobufEncode constructor + */ + constructor() { + super(); + + this.name = "Protobuf编码"; + this.module = "Protobuf"; + this.description = "使用.proto模式文件把有效的JSON object编码成protobuf字节数组。"; + this.infoURL = "https://developers.google.com/protocol-buffers/docs/encoding"; + this.inputType = "JSON"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + name: "模式文件(Schema,.proto文本)", + type: "text", + value: "", + rows: 8, + hint: "可以直接拖放文件到此位置" + } + ]; + } + + /** + * @param {Object} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + try { + return Protobuf.encode(input, args); + } catch (error) { + throw new OperationError(error); + } + } + +} + +export default ProtobufEncode; diff --git a/plugins/srktoolbox/src/core/operations/PseudoRandomNumberGenerator.mjs b/plugins/srktoolbox/src/core/operations/PseudoRandomNumberGenerator.mjs new file mode 100644 index 00000000..13dbd31a --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PseudoRandomNumberGenerator.mjs @@ -0,0 +1,88 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import forge from "node-forge"; +import BigNumber from "bignumber.js"; +import { isWorkerEnvironment } from "../Utils.mjs"; + +/** + * Pseudo-Random Number Generator operation + */ +class PseudoRandomNumberGenerator extends Operation { + + /** + * PseudoRandomNumberGenerator constructor + */ + constructor() { + super(); + + this.name = "伪随机数生成器"; + this.module = "Ciphers"; + this.description = "密码学安全伪随机数生成器(CSPRNG)。

这个操作使用浏览器内置的 crypto.getRandomValues() 方法。如果不可用,则回退到基于Fortuna的随机数算法。"; + this.infoURL = "https://wikipedia.org/wiki/Pseudorandom_number_generator"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "字节数", + "type": "number", + "value": 32 + }, + { + "name": "输出", + "type": "option", + "value": ["十六进制", "整型", "字节数组", "原始"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [numBytes, outputAs] = args; + + let bytes; + + if (isWorkerEnvironment() && self.crypto) { + bytes = new ArrayBuffer(numBytes); + const CHUNK_SIZE = 65536; + for (let i = 0; i < numBytes; i += CHUNK_SIZE) { + self.crypto.getRandomValues(new Uint8Array(bytes, i, Math.min(numBytes - i, CHUNK_SIZE))); + } + bytes = Utils.arrayBufferToStr(bytes); + } else { + bytes = forge.random.getBytesSync(numBytes); + } + + let value = new BigNumber(0), + i; + + switch (outputAs) { + case "十六进制": + return forge.util.bytesToHex(bytes); + case "整型": + for (i = bytes.length - 1; i >= 0; i--) { + value = value.times(256).plus(bytes.charCodeAt(i)); + } + return value.toFixed(); + case "字节数组": + return JSON.stringify(Utils.strToCharcode(bytes)); + case "原始": + default: + return bytes; + } + } + +} + +export default PseudoRandomNumberGenerator; diff --git a/plugins/srktoolbox/src/core/operations/PubKeyFromCert.mjs b/plugins/srktoolbox/src/core/operations/PubKeyFromCert.mjs new file mode 100644 index 00000000..7637753d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PubKeyFromCert.mjs @@ -0,0 +1,70 @@ +/** + * @author cplussharp + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import r from "jsrsasign"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Public Key from Certificate operation + */ +class PubKeyFromCert extends Operation { + + /** + * PubKeyFromCert constructor + */ + constructor() { + super(); + + this.name = "从证书提取公钥"; + this.module = "PublicKey"; + this.description = "从证书中提取公钥。"; + this.infoURL = "https://en.wikipedia.org/wiki/X.509"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + this.checks = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let output = ""; + let match; + const regex = /-----BEGIN CERTIFICATE-----/g; + while ((match = regex.exec(input)) !== null) { + // find corresponding end tag + const indexBase64 = match.index + match[0].length; + const footer = "-----END CERTIFICATE-----"; + const indexFooter = input.indexOf(footer, indexBase64); + if (indexFooter === -1) { + throw new OperationError(`未找到PEM footer '${footer}'`); + } + + const certPem = input.substring(match.index, indexFooter + footer.length); + const cert = new r.X509(); + cert.readCertPEM(certPem); + let pubKey; + try { + pubKey = cert.getPublicKey(); + } catch { + throw new OperationError("不支持的公钥类型"); + } + const pubKeyPem = r.KEYUTIL.getPEM(pubKey); + + // PEM ends with '\n', so a new key always starts on a new line + output += pubKeyPem; + } + return output; + } +} + +export default PubKeyFromCert; diff --git a/plugins/srktoolbox/src/core/operations/PubKeyFromPrivKey.mjs b/plugins/srktoolbox/src/core/operations/PubKeyFromPrivKey.mjs new file mode 100644 index 00000000..723e7d70 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/PubKeyFromPrivKey.mjs @@ -0,0 +1,84 @@ +/** + * @author cplussharp + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import r from "jsrsasign"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Public Key from Private Key operation + */ +class PubKeyFromPrivKey extends Operation { + + /** + * PubKeyFromPrivKey constructor + */ + constructor() { + super(); + + this.name = "从私钥提取公钥"; + this.module = "PublicKey"; + this.description = "从私钥中提取公钥。"; + this.infoURL = "https://en.wikipedia.org/wiki/PKCS_8"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + this.checks = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let output = ""; + let match; + const regex = /-----BEGIN ((RSA |EC |DSA )?PRIVATE KEY)-----/g; + while ((match = regex.exec(input)) !== null) { + // find corresponding end tag + const indexBase64 = match.index + match[0].length; + const footer = `-----END ${match[1]}-----`; + const indexFooter = input.indexOf(footer, indexBase64); + if (indexFooter === -1) { + throw new OperationError(`未找到PEM footer '${footer}'`); + } + + const privKeyPem = input.substring(match.index, indexFooter + footer.length); + let privKey; + try { + privKey = r.KEYUTIL.getKey(privKeyPem); + } catch (err) { + throw new OperationError(`不支持的密钥类型:${err}`); + } + let pubKey; + if (privKey.type && privKey.type === "EC") { + pubKey = new r.KJUR.crypto.ECDSA({ curve: privKey.curve }); + pubKey.setPublicKeyHex(privKey.generatePublicKeyHex()); + } else if (privKey.type && privKey.type === "DSA") { + if (!privKey.y) { + throw new OperationError(`不支持PKCS#8格式DSA私钥`); + } + pubKey = new r.KJUR.crypto.DSA(); + pubKey.setPublic(privKey.p, privKey.q, privKey.g, privKey.y); + } else if (privKey.n && privKey.e) { + pubKey = new r.RSAKey(); + pubKey.setPublic(privKey.n, privKey.e); + } else { + throw new OperationError(`不支持的密钥类型`); + } + const pubKeyPem = r.KEYUTIL.getPEM(pubKey); + + // PEM ends with '\n', so a new key always starts on a new line + output += pubKeyPem; + } + return output; + } +} + +export default PubKeyFromPrivKey; diff --git a/plugins/srktoolbox/src/core/operations/RAKE.mjs b/plugins/srktoolbox/src/core/operations/RAKE.mjs new file mode 100644 index 00000000..2ce076cd --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RAKE.mjs @@ -0,0 +1,146 @@ +/** + * @author sw5678 + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * RAKE operation + */ +class RAKE extends Operation { + + /** + * RAKE constructor + */ + constructor() { + super(); + + this.name = "RAKE"; + this.module = "Default"; + this.description = [ + "快速自动关键词提取(Rapid Automatic Keyword Extraction,RAKE)", + "

", + "RAKE是自然语言处理(NLP)中的一种领域无关的关键词提取算法。", + "

", + "终止词(Stop words)的列表来自NLTK Python包。", + ].join("\n"); + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "词分隔符(正则)", + type: "text", + value: "\\s" + }, + { + name: "句分隔符(正则)", + type: "text", + value: "\\.\\s|\\n" + }, + { + name: "终止词(Stop Words)", + type: "text", + value: "i,me,my,myself,we,our,ours,ourselves,you,you're,you've,you'll,you'd,your,yours,yourself,yourselves,he,him,his,himself,she,she's,her,hers,herself,it,it's,its,itsef,they,them,their,theirs,themselves,what,which,who,whom,this,that,that'll,these,those,am,is,are,was,were,be,been,being,have,has,had,having,do,does',did,doing,a,an,the,and,but,if,or,because,as,until,while,of,at,by,for,with,about,against,between,into,through,during,before,after,above,below,to,from,up,down,in,out,on,off,over,under,again,further,then,once,here,there,when,where,why,how,all,any,both,each,few,more,most,other,some,such,no,nor,not,only,own,same,so,than,too,very,s,t,can,will,just,don,don't,should,should've,now,d,ll,m,o,re,ve,y,ain,aren,aren't,couldn,couldn't,didn,didn't,doesn,doesn't,hadn,hadn't,hasn,hasn't,haven,haven't,isn,isn't,ma,mightn,mightn't,mustn,mustn't,needn,needn't,shan,shan't,shouldn,shouldn't,wasn,wasn't,weren,weren't,won,won't,wouldn,wouldn't" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + + // Get delimiter regexs + const wordDelim = new RegExp(args[0], "g"); + const sentDelim = new RegExp(args[1], "g"); + + // Deduplicate the stop words and add the empty string + const stopWords = args[2].toLowerCase().replace(/ /g, "").split(",").unique(); + stopWords.push(""); + + // Lower case input and remove start and ending whitespace + input = input.toLowerCase().trim(); + + // Get tokens, token count, and phrases + const tokens = []; + const wordFrequencies = []; + let phrases = []; + + // Build up list of phrases and token counts + const sentences = input.split(sentDelim); + for (const sent of sentences) { + + // Split sentence into words + const splitSent = sent.split(wordDelim); + let startIndex = 0; + + for (let i = 0; i < splitSent.length; i++) { + const token = splitSent[i]; + if (stopWords.includes(token)) { + // If token is stop word then split to create phrase + phrases.push(splitSent.slice(startIndex, i)); + startIndex = i + 1; + } else { + // If token is not a stop word add to the count of the list of words + if (tokens.includes(token)) { + wordFrequencies[tokens.indexOf(token)]+=1; + } else { + tokens.push(token); + wordFrequencies.push(1); + } + } + } + phrases.push(splitSent.slice(startIndex)); + } + + // remove empty phrases + phrases = phrases.filter(subArray => subArray.length > 0); + + // Remove duplicate phrases + phrases = phrases.unique(); + + // Generate word_degree_matrix and populate + const wordDegreeMatrix = Array(tokens.length).fill().map(() => Array(tokens.length).fill(0)); + for (const phrase of phrases) { + for (const word1 of phrase) { + for (const word2 of phrase) { + wordDegreeMatrix[tokens.indexOf(word1)][tokens.indexOf(word2)]++; + } + } + } + + // Calculate degree score for each token + const degreeScores = Array(tokens.length).fill(0); + for (let i=0; i b[0] - a[0]); + scores.unshift(new Array("评分:", "关键词:")); + + // Output works with the 'To Table' functionality already built into CC + return scores.map(function (score) { + return score.join(", "); + }).join("\n"); + } +} + +export default RAKE; diff --git a/plugins/srktoolbox/src/core/operations/RC2Decrypt.mjs b/plugins/srktoolbox/src/core/operations/RC2Decrypt.mjs new file mode 100644 index 00000000..9b901745 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RC2Decrypt.mjs @@ -0,0 +1,78 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import forge from "node-forge"; + +/** + * RC2 Decrypt operation + */ +class RC2Decrypt extends Operation { + + /** + * RC2Decrypt constructor + */ + constructor() { + super(); + + this.name = "RC2解密"; + this.module = "Ciphers"; + this.description = "RC2(又叫ARC2)是Ron Rivest在1987年发明的对称加密算法。“RC”是“Rivest Cipher”的缩写。

Key: RC2使用变长的key。

你可以通过密钥派生操作来生成基于密码的key。

IV:CBC模式的初始化向量必须是8字节,如果IV留空则会使用ECB模式。

填充:CBC和ECB模式下会使用PKCS#7填充。"; + this.infoURL = "https://wikipedia.org/wiki/RC2"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Key", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + "name": "IV", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + "name": "Input", + "type": "option", + "value": ["十六进制", "原始内容"] + }, + { + "name": "Output", + "type": "option", + "value": ["原始内容", "十六进制"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const key = Utils.convertToByteString(args[0].string, args[0].option), + iv = Utils.convertToByteString(args[1].string, args[1].option), + [,, inputType, outputType] = args, + decipher = forge.rc2.createDecryptionCipher(key); + + input = Utils.convertToByteString(input, inputType); + + decipher.start(iv || null); + decipher.update(forge.util.createBuffer(input)); + decipher.finish(); + + return outputType === "十六进制" ? decipher.output.toHex() : decipher.output.getBytes(); + } + +} + +export default RC2Decrypt; diff --git a/plugins/srktoolbox/src/core/operations/RC2Encrypt.mjs b/plugins/srktoolbox/src/core/operations/RC2Encrypt.mjs new file mode 100644 index 00000000..42752d9d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RC2Encrypt.mjs @@ -0,0 +1,79 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import forge from "node-forge"; + + +/** + * RC2 Encrypt operation + */ +class RC2Encrypt extends Operation { + + /** + * RC2Encrypt constructor + */ + constructor() { + super(); + + this.name = "RC2加密"; + this.module = "Ciphers"; + this.description = "RC2(又叫ARC2)是Ron Rivest在1987年发明的对称加密算法。“RC”是“Rivest Cipher”的缩写。

Key: RC2使用变长的key。

你可以通过密钥派生操作来生成基于密码的key。

IV:CBC模式的初始化向量必须是8字节,如果IV留空则会使用ECB模式。

填充:CBC和ECB模式下会使用PKCS#7填充。"; + this.infoURL = "https://wikipedia.org/wiki/RC2"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Key", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + "name": "IV", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + "name": "Input", + "type": "option", + "value": ["原始内容", "十六进制"] + }, + { + "name": "Output", + "type": "option", + "value": ["十六进制", "原始内容"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const key = Utils.convertToByteString(args[0].string, args[0].option), + iv = Utils.convertToByteString(args[1].string, args[1].option), + [,, inputType, outputType] = args, + cipher = forge.rc2.createEncryptionCipher(key); + + input = Utils.convertToByteString(input, inputType); + + cipher.start(iv || null); + cipher.update(forge.util.createBuffer(input)); + cipher.finish(); + + return outputType === "十六进制" ? cipher.output.toHex() : cipher.output.getBytes(); + } + +} + +export default RC2Encrypt; diff --git a/plugins/srktoolbox/src/core/operations/RC4.mjs b/plugins/srktoolbox/src/core/operations/RC4.mjs new file mode 100644 index 00000000..15e30e8f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RC4.mjs @@ -0,0 +1,91 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import CryptoJS from "crypto-js"; +import { format } from "../lib/Ciphers.mjs"; + +/** + * RC4 operation + */ +class RC4 extends Operation { + + /** + * RC4 constructor + */ + constructor() { + super(); + + this.name = "RC4"; + this.module = "Ciphers"; + this.description = "RC4(又叫ARC4)是一种广泛使用的流加密算法,由Ron Rivest设计。在很多流行协议中均有应用,如SSL和WEP。RC4加密方法简洁高效,但安全性没有保障。"; + this.infoURL = "https://wikipedia.org/wiki/RC4"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "加密密码", + "type": "toggleString", + "value": "", + "toggleValues": ["UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1", "十六进制", "Base64"] + }, + { + "name": "输入格式", + "type": "option", + "value": ["Latin1", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "十六进制", "Base64"] + }, + { + "name": "输出格式", + "type": "option", + "value": ["Latin1", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "十六进制", "Base64"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const message = format[args[1]].parse(input), + passphrase = format[args[0].option].parse(args[0].string), + encrypted = CryptoJS.RC4.encrypt(message, passphrase); + + return encrypted.ciphertext.toString(format[args[2]]); + } + + /** + * Highlight RC4 + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight RC4 in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default RC4; diff --git a/plugins/srktoolbox/src/core/operations/RC4Drop.mjs b/plugins/srktoolbox/src/core/operations/RC4Drop.mjs new file mode 100644 index 00000000..58030bba --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RC4Drop.mjs @@ -0,0 +1,97 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { format } from "../lib/Ciphers.mjs"; +import CryptoJS from "crypto-js"; + +/** + * RC4 Drop operation + */ +class RC4Drop extends Operation { + + /** + * RC4Drop constructor + */ + constructor() { + super(); + + this.name = "RC4 Drop"; + this.module = "Ciphers"; + this.description = "由于RC4加密流前部的数个字节随机性不足且泄露关于key的信息,因此丢弃前部数据能提高加密安全性。通常这种优化后的算法称作RC4-drop。"; + this.infoURL = "https://wikipedia.org/wiki/RC4#Fluhrer,_Mantin_and_Shamir_attack"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "加密密码", + "type": "toggleString", + "value": "", + "toggleValues": ["UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1", "十六进制", "Base64"] + }, + { + "name": "输入格式", + "type": "option", + "value": ["Latin1", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "十六进制", "Base64"] + }, + { + "name": "输出格式", + "type": "option", + "value": ["Latin1", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "十六进制", "Base64"] + }, + { + "name": "Number of dwords to drop", + "type": "number", + "value": 192 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const message = format[args[1]].parse(input), + passphrase = format[args[0].option].parse(args[0].string), + drop = args[3], + encrypted = CryptoJS.RC4Drop.encrypt(message, passphrase, { drop: drop }); + + return encrypted.ciphertext.toString(format[args[2]]); + } + + /** + * Highlight RC4 Drop + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight RC4 Drop in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default RC4Drop; diff --git a/plugins/srktoolbox/src/core/operations/RIPEMD.mjs b/plugins/srktoolbox/src/core/operations/RIPEMD.mjs new file mode 100644 index 00000000..299c9e9c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RIPEMD.mjs @@ -0,0 +1,50 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * RIPEMD operation + */ +class RIPEMD extends Operation { + + /** + * RIPEMD constructor + */ + constructor() { + super(); + + this.name = "RIPEMD"; + this.module = "Crypto"; + this.description = "RIPEMD(RACE原始完整性校验讯息摘要)是一种加密哈希函数,由 鲁汶大学 Hans Dobbertin,Antoon Bosselaers 和 Bart Prenee组成的COSIC 研究小组发布于1996年。

RIPEMD是以MD4为基础原则所设计的 ,而且其表现与更有名的SHA-1类似。"; + this.infoURL = "https://wikipedia.org/wiki/RIPEMD"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "长度", + "type": "option", + "value": ["320", "256", "160", "128"] + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const size = args[0]; + return runHash("ripemd" + size, input); + } + +} + +export default RIPEMD; diff --git a/plugins/srktoolbox/src/core/operations/ROT13.mjs b/plugins/srktoolbox/src/core/operations/ROT13.mjs new file mode 100644 index 00000000..be2e5c2e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ROT13.mjs @@ -0,0 +1,116 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + + +/** + * ROT13 operation. + */ +class ROT13 extends Operation { + + /** + * ROT13 constructor + */ + constructor() { + super(); + + this.name = "ROT13"; + this.module = "Default"; + this.description = "一个简单的凯撒密码,默认情况下把字母偏移13个位置。"; + this.infoURL = "https://wikipedia.org/wiki/ROT13"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "偏移小写字母", + type: "boolean", + value: true + }, + { + name: "偏移大写字母", + type: "boolean", + value: true + }, + { + name: "偏移数字", + type: "boolean", + value: false + }, + { + name: "偏移数量", + type: "number", + value: 13 + }, + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const output = input, + rot13Lowercase = args[0], + rot13Upperacse = args[1], + rotNumbers = args[2]; + let amount = args[3], + amountNumbers = args[3]; + + if (amount) { + if (amount < 0) { + amount = 26 - (Math.abs(amount) % 26); + amountNumbers = 10 - (Math.abs(amountNumbers) % 10); + } + + for (let i = 0; i < input.length; i++) { + let chr = input[i]; + if (rot13Upperacse && chr >= 65 && chr <= 90) { // Upper case + chr = (chr - 65 + amount) % 26; + output[i] = chr + 65; + } else if (rot13Lowercase && chr >= 97 && chr <= 122) { // Lower case + chr = (chr - 97 + amount) % 26; + output[i] = chr + 97; + } else if (rotNumbers && chr >= 48 && chr <= 57) { // Numbers + chr = (chr - 48 + amountNumbers) % 10; + output[i] = chr + 48; + } + } + } + return output; + } + + /** + * Highlight ROT13 + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight ROT13 in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } +} + +export default ROT13; diff --git a/plugins/srktoolbox/src/core/operations/ROT13BruteForce.mjs b/plugins/srktoolbox/src/core/operations/ROT13BruteForce.mjs new file mode 100644 index 00000000..ea7a1b22 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ROT13BruteForce.mjs @@ -0,0 +1,104 @@ +/** + * @author MikeCAT + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * ROT13 Brute Force operation. + */ +class ROT13BruteForce extends Operation { + + /** + * ROT13BruteForce constructor + */ + constructor() { + super(); + + this.name = "ROT13暴力破解"; + this.module = "Default"; + this.description = "尝试ROT13所有可能的偏移量。

你可以输入已知的明文部分(Crib)来筛选结果。"; + this.infoURL = "https://wikipedia.org/wiki/ROT13"; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = [ + { + name: "偏移小写字母", + type: "boolean", + value: true + }, + { + name: "偏移大写字母", + type: "boolean", + value: true + }, + { + name: "偏移数字", + type: "boolean", + value: false + }, + { + name: "取样长度", + type: "number", + value: 100 + }, + { + name: "取样偏移", + type: "number", + value: 0 + }, + { + name: "输出偏移量", + type: "boolean", + value: true + }, + { + name: "Crib (已知明文)", + type: "string", + value: "" + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [rotateLower, rotateUpper, rotateNum, sampleLength, sampleOffset, printAmount, crib] = args; + const sample = input.slice(sampleOffset, sampleOffset + sampleLength); + const cribLower = crib.toLowerCase(); + const lowerStart = "a".charCodeAt(0), upperStart = "A".charCodeAt(0), numStart = "0".charCodeAt(0); + const result = []; + for (let amount = 1; amount < 26; amount++) { + const rotated = sample.slice(); + for (let i = 0; i < rotated.length; i++) { + if (rotateLower && lowerStart <= rotated[i] && rotated[i] < lowerStart + 26) { + rotated[i] = (rotated[i] - lowerStart + amount) % 26 + lowerStart; + } else if (rotateUpper && upperStart <= rotated[i] && rotated[i] < upperStart + 26) { + rotated[i] = (rotated[i] - upperStart + amount) % 26 + upperStart; + } else if (rotateNum && numStart <= rotated[i] && rotated[i] < numStart + 10) { + rotated[i] = (rotated[i] - numStart + amount) % 10 + numStart; + } + } + const rotatedString = Utils.byteArrayToUtf8(rotated); + if (rotatedString.toLowerCase().indexOf(cribLower) >= 0) { + const rotatedStringEscaped = Utils.escapeWhitespace(rotatedString); + if (printAmount) { + const amountStr = "偏移量 = " + (" " + amount).slice(-2) + ": "; + result.push(amountStr + rotatedStringEscaped); + } else { + result.push(rotatedStringEscaped); + } + } + } + return result.join("\n"); + } +} + +export default ROT13BruteForce; diff --git a/plugins/srktoolbox/src/core/operations/ROT47.mjs b/plugins/srktoolbox/src/core/operations/ROT47.mjs new file mode 100644 index 00000000..b9b4343e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ROT47.mjs @@ -0,0 +1,91 @@ +/** + * @author Matt C [matt@artemisbot.uk] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + + +/** + * ROT47 operation. + */ +class ROT47 extends Operation { + + /** + * ROT47 constructor + */ + constructor() { + super(); + + this.name = "ROT47"; + this.module = "Default"; + this.description = "稍微复杂点的凯撒密码,使用了ASCII里从 33 '!' 到 126 '~'的字符。默认的偏移数量是47。"; + this.infoURL = "https://wikipedia.org/wiki/ROT13#Variants"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "偏移数量", + type: "number", + value: 47 + }, + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const output = input; + let amount = args[0], + chr; + + if (amount) { + if (amount < 0) { + amount = 94 - (Math.abs(amount) % 94); + } + + for (let i = 0; i < input.length; i++) { + chr = input[i]; + if (chr >= 33 && chr <= 126) { + chr = (chr - 33 + amount) % 94; + output[i] = chr + 33; + } + } + } + return output; + } + + /** + * Highlight ROT47 + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight ROT47 in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } +} + +export default ROT47; diff --git a/plugins/srktoolbox/src/core/operations/ROT47BruteForce.mjs b/plugins/srktoolbox/src/core/operations/ROT47BruteForce.mjs new file mode 100644 index 00000000..3836c415 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ROT47BruteForce.mjs @@ -0,0 +1,84 @@ +/** + * @author MikeCAT + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * ROT47 Brute Force operation. + */ +class ROT47BruteForce extends Operation { + + /** + * ROT47BruteForce constructor + */ + constructor() { + super(); + + this.name = "ROT47暴力破解"; + this.module = "Default"; + this.description = "尝试ROT47所有可能的偏移量。

你可以输入已知的明文部分(Crib)来筛选结果。"; + this.infoURL = "https://wikipedia.org/wiki/ROT13#Variants"; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = [ + { + name: "取样长度", + type: "number", + value: 100 + }, + { + name: "取样偏移", + type: "number", + value: 0 + }, + { + name: "输出偏移量", + type: "boolean", + value: true + }, + { + name: "Crib (已知明文)", + type: "string", + value: "" + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [sampleLength, sampleOffset, printAmount, crib] = args; + const sample = input.slice(sampleOffset, sampleOffset + sampleLength); + const cribLower = crib.toLowerCase(); + const result = []; + for (let amount = 1; amount < 94; amount++) { + const rotated = sample.slice(); + for (let i = 0; i < rotated.length; i++) { + if (33 <= rotated[i] && rotated[i] <= 126) { + rotated[i] = (rotated[i] - 33 + amount) % 94 + 33; + } + } + const rotatedString = Utils.byteArrayToUtf8(rotated); + if (rotatedString.toLowerCase().indexOf(cribLower) >= 0) { + const rotatedStringEscaped = Utils.escapeWhitespace(rotatedString); + if (printAmount) { + const amountStr = "偏移量 = " + (" " + amount).slice(-2) + ": "; + result.push(amountStr + rotatedStringEscaped); + } else { + result.push(rotatedStringEscaped); + } + } + } + return result.join("\n"); + } +} + +export default ROT47BruteForce; diff --git a/plugins/srktoolbox/src/core/operations/ROT8000.mjs b/plugins/srktoolbox/src/core/operations/ROT8000.mjs new file mode 100644 index 00000000..2b482c61 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ROT8000.mjs @@ -0,0 +1,125 @@ +/** + * @author Daniel Temkin [http://danieltemkin.com] + * @author Thomas Leplus [https://www.leplus.org] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * ROT8000 operation. + */ +class ROT8000 extends Operation { + + /** + * ROT8000 constructor + */ + constructor() { + super(); + this.name = "ROT8000"; + this.module = "Default"; + this.description = "简单的凯撒密码,把Unicode字符替换成之前或之后的第0x8000个字符。"; + this.infoURL = "https://rot8000.com/info"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + // Inspired from https://github.com/rottytooth/rot8000/blob/main/rot8000.js + // these come from the valid-code-point-transitions.json file generated from the c# proj + // this is done bc: 1) don't trust JS's understanging of surrogate pairs and 2) consistency with original rot8000 + const validCodePoints = { + "33": true, + "127": false, + "161": true, + "5760": false, + "5761": true, + "8192": false, + "8203": true, + "8232": false, + "8234": true, + "8239": false, + "8240": true, + "8287": false, + "8288": true, + "12288": false, + "12289": true, + "55296": false, + "57344": true + }; + const bmpSize = 0x10000; + const rotList = {}; // the mapping of char to rotated char + const hiddenBlocks = []; + let startBlock = 0; + for (const key in validCodePoints) { + if (Object.prototype.hasOwnProperty.call(validCodePoints, key)) { + if (validCodePoints[key] === true) + hiddenBlocks.push({ start: startBlock, end: parseInt(key, 10) - 1 }); + else + startBlock = parseInt(key, 10); + } + } + const validIntList = []; // list of all valid chars + let currValid = false; + for (let i = 0; i < bmpSize; i++) { + if (validCodePoints[i] !== undefined) { + currValid = validCodePoints[i]; + } + if (currValid) validIntList.push(i); + } + const rotateNum = Object.keys(validIntList).length / 2; + // go through every valid char and find its match + for (let i = 0; i < validIntList.length; i++) { + rotList[String.fromCharCode(validIntList[i])] = + String.fromCharCode(validIntList[(i + rotateNum) % (rotateNum * 2)]); + } + let output = ""; + for (let count = 0; count < input.length; count++) { + // if it is not in the mappings list, just add it directly (no rotation) + if (rotList[input[count]] === undefined) { + output += input[count]; + continue; + } + // otherwise, rotate it and add it to the string + output += rotList[input[count]]; + } + return output; + } + + /** + * Highlight ROT8000 + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight ROT8000 in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } +} + +export default ROT8000; diff --git a/plugins/srktoolbox/src/core/operations/RSADecrypt.mjs b/plugins/srktoolbox/src/core/operations/RSADecrypt.mjs new file mode 100644 index 00000000..254520ff --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RSADecrypt.mjs @@ -0,0 +1,88 @@ +/** + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import forge from "node-forge"; +import { MD_ALGORITHMS } from "../lib/RSA.mjs"; + +/** + * RSA Decrypt operation + */ +class RSADecrypt extends Operation { + + /** + * RSADecrypt constructor + */ + constructor() { + super(); + + this.name = "RSA解密"; + this.module = "Ciphers"; + this.description = "使用PEM格式的RSA私钥解密消息。"; + this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "RSA私钥 (PEM)", + type: "text", + value: "-----BEGIN RSA PRIVATE KEY-----" + }, + { + name: "密码", + type: "text", + value: "" + }, + { + name: "加密方式", + type: "argSelector", + value: [ + { + name: "RSA-OAEP", + on: [3] + }, + { + name: "RSAES-PKCS1-V1_5", + off: [3] + }, + { + name: "RAW", + off: [3] + }] + }, + { + name: "消息摘要算法", + type: "option", + value: Object.keys(MD_ALGORITHMS) + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [pemKey, password, scheme, md] = args; + if (pemKey.replace("-----BEGIN RSA PRIVATE KEY-----", "").length === 0) { + throw new OperationError("请输入私钥。"); + } + try { + const privKey = forge.pki.decryptRsaPrivateKey(pemKey, password); + const dMsg = privKey.decrypt(input, scheme, {md: MD_ALGORITHMS[md].create()}); + return forge.util.decodeUtf8(dMsg); + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default RSADecrypt; diff --git a/plugins/srktoolbox/src/core/operations/RSAEncrypt.mjs b/plugins/srktoolbox/src/core/operations/RSAEncrypt.mjs new file mode 100644 index 00000000..efd1bd82 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RSAEncrypt.mjs @@ -0,0 +1,91 @@ +/** + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import forge from "node-forge"; +import { MD_ALGORITHMS } from "../lib/RSA.mjs"; + +/** + * RSA Encrypt operation + */ +class RSAEncrypt extends Operation { + + /** + * RSAEncrypt constructor + */ + constructor() { + super(); + + this.name = "RSA加密"; + this.module = "Ciphers"; + this.description = "使用PEM格式RSA公钥加密消息。"; + this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "RSA公钥 (PEM)", + type: "text", + value: "-----BEGIN RSA PUBLIC KEY-----" + }, + { + name: "加密方式", + type: "argSelector", + value: [ + { + name: "RSA-OAEP", + on: [2] + }, + { + name: "RSAES-PKCS1-V1_5", + off: [2] + }, + { + name: "RAW", + off: [2] + }] + }, + { + name: "消息摘要算法", + type: "option", + value: Object.keys(MD_ALGORITHMS) + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [pemKey, scheme, md] = args; + + if (pemKey.replace("-----BEGIN RSA PUBLIC KEY-----", "").length === 0) { + throw new OperationError("请输入公钥。"); + } + try { + // Load public key + const pubKey = forge.pki.publicKeyFromPem(pemKey); + // https://github.com/digitalbazaar/forge/issues/465#issuecomment-271097600 + const plaintextBytes = forge.util.encodeUtf8(input); + // Encrypt message + const eMsg = pubKey.encrypt(plaintextBytes, scheme, {md: MD_ALGORITHMS[md].create()}); + return eMsg; + } catch (err) { + if (err.message === "RSAES-OAEP input message length is too long.") { + throw new OperationError(`RSAES-OAEP 输入消息长度 (${err.length}) 超过最大长度 (${err.maxLength})。`); + } + throw new OperationError(err); + } + } + +} + +export default RSAEncrypt; diff --git a/plugins/srktoolbox/src/core/operations/RSASign.mjs b/plugins/srktoolbox/src/core/operations/RSASign.mjs new file mode 100644 index 00000000..3d26da1a --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RSASign.mjs @@ -0,0 +1,76 @@ +/** + * @author Matt C [me@mitt.dev] + * @author gchq77703 [] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import forge from "node-forge"; +import { MD_ALGORITHMS } from "../lib/RSA.mjs"; + +/** + * RSA Sign operation + */ +class RSASign extends Operation { + + /** + * RSASign constructor + */ + constructor() { + super(); + + this.name = "RSA签名"; + this.module = "Ciphers"; + this.description = "使用PEM编码的RSA密钥签名文本信息。"; + this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "RSA私钥 (PEM)", + type: "text", + value: "-----BEGIN RSA PRIVATE KEY-----" + }, + { + name: "密码", + type: "text", + value: "" + }, + { + name: "消息摘要算法", + type: "option", + value: Object.keys(MD_ALGORITHMS) + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [key, password, mdAlgo] = args; + if (key.replace("-----BEGIN RSA PRIVATE KEY-----", "").length === 0) { + throw new OperationError("请输入私钥"); + } + try { + const privateKey = forge.pki.decryptRsaPrivateKey(key, password); + // Generate message hash + const md = MD_ALGORITHMS[mdAlgo].create(); + md.update(input, "raw"); + // Sign message hash + const sig = privateKey.sign(md); + return sig; + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default RSASign; diff --git a/plugins/srktoolbox/src/core/operations/RSAVerify.mjs b/plugins/srktoolbox/src/core/operations/RSAVerify.mjs new file mode 100644 index 00000000..c0c6f429 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RSAVerify.mjs @@ -0,0 +1,86 @@ +/** + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import forge from "node-forge"; +import { MD_ALGORITHMS } from "../lib/RSA.mjs"; +import Utils from "../Utils.mjs"; + +/** + * RSA Verify operation + */ +class RSAVerify extends Operation { + + /** + * RSAVerify constructor + */ + constructor() { + super(); + + this.name = "RSA验证"; + this.module = "Ciphers"; + this.description = "使用PEM编码的RSA公钥和签名验证文本消息。"; + this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "RSA公钥 (PEM)", + type: "text", + value: "-----BEGIN RSA PUBLIC KEY-----" + }, + { + name: "消息", + type: "text", + value: "" + }, + { + name: "消息格式", + type: "option", + value: ["原始字节", "十六进制", "Base64"] + }, + { + name: "消息摘要算法", + type: "option", + value: Object.keys(MD_ALGORITHMS) + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [pemKey, message, format, mdAlgo] = args; + if (pemKey.replace("-----BEGIN RSA PUBLIC KEY-----", "").length === 0) { + throw new OperationError("请输入公钥。"); + } + try { + // Load public key + const pubKey = forge.pki.publicKeyFromPem(pemKey); + // Generate message digest + const md = MD_ALGORITHMS[mdAlgo].create(); + const messageStr = Utils.convertToByteString(message, format); + md.update(messageStr, "raw"); + // Compare signed message digest and generated message digest + const result = pubKey.verify(md.digest().bytes(), input); + return result ? "验证成功" : "验证失败"; + } catch (err) { + if (err.message === "Encrypted message length is invalid.") { + throw new OperationError(`签名长度 (${err.length}) 与密钥长度 (${err.expected}) 的期待值不符。`); + } + throw new OperationError(err); + } + } + +} + +export default RSAVerify; diff --git a/plugins/srktoolbox/src/core/operations/Rabbit.mjs b/plugins/srktoolbox/src/core/operations/Rabbit.mjs new file mode 100644 index 00000000..dea0e7f4 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Rabbit.mjs @@ -0,0 +1,249 @@ +/** + * @author mikecat + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import { toHexFast } from "../lib/Hex.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Rabbit operation + */ +class Rabbit extends Operation { + + /** + * Rabbit constructor + */ + constructor() { + super(); + + this.name = "Rabbit"; + this.module = "Ciphers"; + this.description = "Rabbit算法是高速的流密码算法,于2003年发布并在RFC 4503中定义。

加密算法使用128位长度的key和可选的64位初始化向量(IV).

大端序:根据RFC4503和RFC3447的定义
小端序:和Crypto++兼容"; + this.infoURL = "https://wikipedia.org/wiki/Rabbit_(cipher)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Key", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + "name": "IV", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + "name": "端序", + "type": "option", + "value": ["大端序", "小端序"] + }, + { + "name": "输入", + "type": "option", + "value": ["原始", "十六进制"] + }, + { + "name": "输出", + "type": "option", + "value": ["原始", "十六进制"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const key = Utils.convertToByteArray(args[0].string, args[0].option), + iv = Utils.convertToByteArray(args[1].string, args[1].option), + endianness = args[2], + inputType = args[3], + outputType = args[4]; + + const littleEndian = endianness === "小端序"; + + if (key.length !== 16) { + throw new OperationError(`无效的key长度:${key.length} 字节(正确值:16)`); + } + if (iv.length !== 0 && iv.length !== 8) { + throw new OperationError(`无效的IV长度:${iv.length} 字节(正确值:0或8)`); + } + + // Inner State + const X = new Uint32Array(8), C = new Uint32Array(8); + let b = 0; + + // Counter System + const A = [ + 0x4d34d34d, 0xd34d34d3, 0x34d34d34, 0x4d34d34d, + 0xd34d34d3, 0x34d34d34, 0x4d34d34d, 0xd34d34d3 + ]; + const counterUpdate = function() { + for (let j = 0; j < 8; j++) { + const temp = C[j] + A[j] + b; + b = (temp / ((1 << 30) * 4)) >>> 0; + C[j] = temp; + } + }; + + // Next-State Function + const g = function(u, v) { + const uv = (u + v) >>> 0; + const upper = uv >>> 16, lower = uv & 0xffff; + const upperUpper = upper * upper; + const upperLower2 = 2 * upper * lower; + const lowerLower = lower * lower; + const mswTemp = upperUpper + ((upperLower2 / (1 << 16)) >>> 0); + const lswTemp = lowerLower + (upperLower2 & 0xffff) * (1 << 16); + const msw = mswTemp + ((lswTemp / ((1 << 30) * 4)) >>> 0); + const lsw = lswTemp >>> 0; + return lsw ^ msw; + }; + const leftRotate = function(value, width) { + return (value << width) | (value >>> (32 - width)); + }; + const nextStateHelper1 = function(v0, v1, v2) { + return v0 + leftRotate(v1, 16) + leftRotate(v2, 16); + }; + const nextStateHelper2 = function(v0, v1, v2) { + return v0 + leftRotate(v1, 8) + v2; + }; + const G = new Uint32Array(8); + const nextState = function() { + for (let j = 0; j < 8; j++) { + G[j] = g(X[j], C[j]); + } + X[0] = nextStateHelper1(G[0], G[7], G[6]); + X[1] = nextStateHelper2(G[1], G[0], G[7]); + X[2] = nextStateHelper1(G[2], G[1], G[0]); + X[3] = nextStateHelper2(G[3], G[2], G[1]); + X[4] = nextStateHelper1(G[4], G[3], G[2]); + X[5] = nextStateHelper2(G[5], G[4], G[3]); + X[6] = nextStateHelper1(G[6], G[5], G[4]); + X[7] = nextStateHelper2(G[7], G[6], G[5]); + }; + + // Key Setup Scheme + const K = new Uint16Array(8); + if (littleEndian) { + for (let i = 0; i < 8; i++) { + K[i] = (key[1 + 2 * i] << 8) | key[2 * i]; + } + } else { + for (let i = 0; i < 8; i++) { + K[i] = (key[14 - 2 * i] << 8) | key[15 - 2 * i]; + } + } + for (let j = 0; j < 8; j++) { + if (j % 2 === 0) { + X[j] = (K[(j + 1) % 8] << 16) | K[j]; + C[j] = (K[(j + 4) % 8] << 16) | K[(j + 5) % 8]; + } else { + X[j] = (K[(j + 5) % 8] << 16) | K[(j + 4) % 8]; + C[j] = (K[j] << 16) | K[(j + 1) % 8]; + } + } + for (let i = 0; i < 4; i++) { + counterUpdate(); + nextState(); + } + for (let j = 0; j < 8; j++) { + C[j] = C[j] ^ X[(j + 4) % 8]; + } + + // IV Setup Scheme + if (iv.length === 8) { + const getIVValue = function(a, b, c, d) { + if (littleEndian) { + return (iv[a] << 24) | (iv[b] << 16) | + (iv[c] << 8) | iv[d]; + } else { + return (iv[7 - a] << 24) | (iv[7 - b] << 16) | + (iv[7 - c] << 8) | iv[7 - d]; + } + }; + C[0] = C[0] ^ getIVValue(3, 2, 1, 0); + C[1] = C[1] ^ getIVValue(7, 6, 3, 2); + C[2] = C[2] ^ getIVValue(7, 6, 5, 4); + C[3] = C[3] ^ getIVValue(5, 4, 1, 0); + C[4] = C[4] ^ getIVValue(3, 2, 1, 0); + C[5] = C[5] ^ getIVValue(7, 6, 3, 2); + C[6] = C[6] ^ getIVValue(7, 6, 5, 4); + C[7] = C[7] ^ getIVValue(5, 4, 1, 0); + for (let i = 0; i < 4; i++) { + counterUpdate(); + nextState(); + } + } + + // Extraction Scheme + const S = new Uint8Array(16); + const extract = function() { + let pos = 0; + const addPart = function(value) { + S[pos++] = value >>> 8; + S[pos++] = value & 0xff; + }; + counterUpdate(); + nextState(); + addPart((X[6] >>> 16) ^ (X[1] & 0xffff)); + addPart((X[6] & 0xffff) ^ (X[3] >>> 16)); + addPart((X[4] >>> 16) ^ (X[7] & 0xffff)); + addPart((X[4] & 0xffff) ^ (X[1] >>> 16)); + addPart((X[2] >>> 16) ^ (X[5] & 0xffff)); + addPart((X[2] & 0xffff) ^ (X[7] >>> 16)); + addPart((X[0] >>> 16) ^ (X[3] & 0xffff)); + addPart((X[0] & 0xffff) ^ (X[5] >>> 16)); + if (littleEndian) { + for (let i = 0, j = S.length - 1; i < j;) { + const temp = S[i]; + S[i] = S[j]; + S[j] = temp; + i++; + j--; + } + } + }; + + const data = Utils.convertToByteString(input, inputType); + const result = new Uint8Array(data.length); + for (let i = 0; i <= data.length - 16; i += 16) { + extract(); + for (let j = 0; j < 16; j++) { + result[i + j] = data.charCodeAt(i + j) ^ S[j]; + } + } + if (data.length % 16 !== 0) { + const offset = data.length - data.length % 16; + const length = data.length - offset; + extract(); + if (littleEndian) { + for (let j = 0; j < length; j++) { + result[offset + j] = data.charCodeAt(offset + j) ^ S[j]; + } + } else { + for (let j = 0; j < length; j++) { + result[offset + j] = data.charCodeAt(offset + j) ^ S[16 - length + j]; + } + } + } + if (outputType === "十六进制") { + return toHexFast(result); + } + return Utils.byteArrayToChars(result); + } + +} + +export default Rabbit; diff --git a/plugins/srktoolbox/src/core/operations/RailFenceCipherDecode.mjs b/plugins/srktoolbox/src/core/operations/RailFenceCipherDecode.mjs new file mode 100644 index 00000000..5e308b34 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RailFenceCipherDecode.mjs @@ -0,0 +1,83 @@ +/** + * @author Flavio Diez [flaviofdiez+cyberchef@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Rail Fence Cipher Decode operation + */ +class RailFenceCipherDecode extends Operation { + + /** + * RailFenceCipherDecode constructor + */ + constructor() { + super(); + + this.name = "篱笆密码解密"; + this.module = "Ciphers"; + this.description = "根据提供的篱笆数量和偏移量进行篱笆密码(Rail fence Cipher)解密。"; + this.infoURL = "https://wikipedia.org/wiki/Rail_fence_cipher"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "篱笆数量", + type: "number", + value: 2 + }, + { + name: "偏移量", + type: "number", + value: 0 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [key, offset] = args; + + const cipher = input; + + if (key < 2) { + throw new OperationError("篱笆数量不少于2"); + } else if (key > cipher.length) { + throw new OperationError("篱笆数量不能超过明文长度"); + } + + if (offset < 0) { + throw new OperationError("偏移量必须为正整数"); + } + + const cycle = (key - 1) * 2; + const plaintext = new Array(cipher.length); + + let j = 0; + let x, y; + + for (y = 0; y < key; y++) { + for (x = 0; x < cipher.length; x++) { + if ((y + x + offset) % cycle === 0 || (y - x - offset) % cycle === 0) { + plaintext[x] = cipher[j++]; + } + } + } + + return plaintext.join(""); + } + +} + + +export default RailFenceCipherDecode; diff --git a/plugins/srktoolbox/src/core/operations/RailFenceCipherEncode.mjs b/plugins/srktoolbox/src/core/operations/RailFenceCipherEncode.mjs new file mode 100644 index 00000000..34318065 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RailFenceCipherEncode.mjs @@ -0,0 +1,76 @@ +/** + * @author Flavio Diez [flaviofdiez+cyberchef@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Rail Fence Cipher Encode operation + */ +class RailFenceCipherEncode extends Operation { + + /** + * RailFenceCipherEncode constructor + */ + constructor() { + super(); + + this.name = "篱笆密码加密"; + this.module = "Ciphers"; + this.description = "根据提供的篱笆数量和偏移量进行篱笆密码(Rail fence Cipher)加密。"; + this.infoURL = "https://wikipedia.org/wiki/Rail_fence_cipher"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "篱笆数量", + type: "number", + value: 2 + }, + { + name: "偏移量", + type: "number", + value: 0 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [key, offset] = args; + + const plaintext = input; + if (key < 2) { + throw new OperationError("篱笆数量不能少于2"); + } else if (key > plaintext.length) { + throw new OperationError("篱笆数量不能超过明文长度"); + } + + if (offset < 0) { + throw new OperationError("偏移量必须为正整数"); + } + + const cycle = (key - 1) * 2; + const rows = new Array(key).fill(""); + + for (let pos = 0; pos < plaintext.length; pos++) { + const rowIdx = key - 1 - Math.abs(cycle / 2 - (pos + offset) % cycle); + + rows[rowIdx] += plaintext[pos]; + } + + return rows.join(""); + } + +} + +export default RailFenceCipherEncode; diff --git a/plugins/srktoolbox/src/core/operations/RandomizeColourPalette.mjs b/plugins/srktoolbox/src/core/operations/RandomizeColourPalette.mjs new file mode 100644 index 00000000..a3d06872 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RandomizeColourPalette.mjs @@ -0,0 +1,85 @@ +/** + * @author Ge0rg3 [georgeomnet+cyberchef@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { runHash } from "../lib/Hash.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { Jimp } from "jimp"; + +/** + * Randomize Colour Palette operation + */ +class RandomizeColourPalette extends Operation { + /** + * RandomizeColourPalette constructor + */ + constructor() { + super(); + + this.name = "色板随机化"; + this.module = "Image"; + this.description = + "将给定图片中的每种颜色单独进行随机化处理。通常用于显示使用非常相近颜色隐写的文字或符号。"; + this.infoURL = "https://wikipedia.org/wiki/Indexed_color"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = [ + { + name: "随机数种子", + type: "string", + value: "", + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + async run(input, args) { + if (!isImage(input)) + throw new OperationError("请输入合法的图像文件。"); + + const seed = args[0] || Math.random().toString().substr(2), + parsedImage = await Jimp.read(input), + width = parsedImage.bitmap.width, + height = parsedImage.bitmap.height; + + let rgbString, rgbHash, rgbHex; + + parsedImage.scan(0, 0, width, height, function (x, y, idx) { + rgbString = this.bitmap.data.slice(idx, idx + 3).join("."); + rgbHash = runHash("md5", Utils.strToArrayBuffer(seed + rgbString)); + rgbHex = rgbHash.substr(0, 6) + "ff"; + parsedImage.setPixelColor(parseInt(rgbHex, 16), x, y); + }); + + const imageBuffer = await parsedImage.getBuffer(parsedImage.mime); + + return new Uint8Array(imageBuffer).buffer; + } + + /** + * Displays the extracted data as an image for web apps. + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const type = isImage(data); + + return ``; + } +} + +export default RandomizeColourPalette; diff --git a/plugins/srktoolbox/src/core/operations/RawDeflate.mjs b/plugins/srktoolbox/src/core/operations/RawDeflate.mjs new file mode 100644 index 00000000..84865ae6 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RawDeflate.mjs @@ -0,0 +1,61 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {COMPRESSION_TYPE} from "../lib/Zlib.mjs"; +import rawdeflate from "zlibjs/bin/rawdeflate.min.js"; + +const Zlib = rawdeflate.Zlib; + +const RAW_COMPRESSION_TYPE_LOOKUP = { + "静态霍夫曼压缩": Zlib.RawDeflate.CompressionType.FIXED, + "动态霍夫曼压缩": Zlib.RawDeflate.CompressionType.DYNAMIC, + "无压缩 (Store)": Zlib.RawDeflate.CompressionType.NONE, +}; + +/** + * Raw Deflate operation + */ +class RawDeflate extends Operation { + + /** + * RawDeflate constructor + */ + constructor() { + super(); + + this.name = "Raw Deflate"; + this.module = "Compression"; + this.description = "使用不带标头的deflate算法压缩数据。"; + this.infoURL = "https://wikipedia.org/wiki/DEFLATE"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + name: "压缩类型", + type: "option", + value: COMPRESSION_TYPE + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const deflate = new Zlib.RawDeflate(new Uint8Array(input), { + compressionType: RAW_COMPRESSION_TYPE_LOOKUP[args[0]] + }); + return new Uint8Array(deflate.compress()).buffer; + } + +} + +export default RawDeflate; diff --git a/plugins/srktoolbox/src/core/operations/RawInflate.mjs b/plugins/srktoolbox/src/core/operations/RawInflate.mjs new file mode 100644 index 00000000..05e4847d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RawInflate.mjs @@ -0,0 +1,92 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {INFLATE_BUFFER_TYPE} from "../lib/Zlib.mjs"; +import rawinflate from "zlibjs/bin/rawinflate.min.js"; + +const Zlib = rawinflate.Zlib; + +const RAW_BUFFER_TYPE_LOOKUP = { + "自适应": Zlib.RawInflate.BufferType.ADAPTIVE, + "块": Zlib.RawInflate.BufferType.BLOCK, +}; + +/** + * Raw Inflate operation + */ +class RawInflate extends Operation { + + /** + * RawInflate constructor + */ + constructor() { + super(); + + this.name = "Raw Inflate"; + this.module = "Compression"; + this.description = "解压缩使用无标头deflate算法压缩的数据。"; + this.infoURL = "https://wikipedia.org/wiki/DEFLATE"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + name: "起始索引", + type: "number", + value: 0 + }, + { + name: "起始输出缓冲区尺寸", + type: "number", + value: 0 + }, + { + name: "缓冲区扩展类型", + type: "option", + value: INFLATE_BUFFER_TYPE + }, + { + name: "解压缩后重置缓冲区尺寸", + type: "boolean", + value: false + }, + { + name: "验证结果", + type: "boolean", + value: false + } + ]; + this.checks = [ + { + entropyRange: [7.5, 8], + args: [0, 0, INFLATE_BUFFER_TYPE, false, false] + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const inflate = new Zlib.RawInflate(new Uint8Array(input), { + index: args[0], + bufferSize: args[1], + bufferType: RAW_BUFFER_TYPE_LOOKUP[args[2]], + resize: args[3], + verify: args[4] + }), + result = new Uint8Array(inflate.decompress()); + + return result.buffer; + } + +} + +export default RawInflate; diff --git a/plugins/srktoolbox/src/core/operations/Register.mjs b/plugins/srktoolbox/src/core/operations/Register.mjs new file mode 100644 index 00000000..4903b190 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Register.mjs @@ -0,0 +1,122 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Dish from "../Dish.mjs"; +import XRegExp from "xregexp"; +import { isWorkerEnvironment } from "../Utils.mjs"; + +/** + * Register operation + */ +class Register extends Operation { + + /** + * Register constructor + */ + constructor() { + super(); + + this.name = "Register"; + this.flowControl = true; + this.module = "Regex"; + this.description = "从输入中提取数据并存储在“寄存器(Register)”中,用于作为变量传递到下面的操作参数中。使用正则表达式捕获组来选择需要提取的数据。

在其它操作的参数中使用$Rn(n是寄存器编号,从0开始)来访问存储的值。

例如:
输入:Test
提取规则:(.*)
参数:$R0就代表Test

寄存器语法可以用反斜线来转义。例如:\\$R0代表字符$R0而不是Test。"; + this.infoURL = "https://wikipedia.org/wiki/Regular_expression#Syntax"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "提取规则", + "type": "binaryString", + "value": "([\\s\\S]*)" + }, + { + "name": "大小写不敏感(i)", + "type": "boolean", + "value": true + }, + { + "name": "多行匹配(m)", + "type": "boolean", + "value": false + }, + { + "name": "点允许匹配换行符(s)", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on. + * @param {Operation[]} state.opList - The list of operations in the recipe. + * @returns {Object} The updated state of the recipe. + */ + async run(state) { + const ings = state.opList[state.progress].ingValues; + const [extractorStr, i, m, s] = ings; + + let modifiers = ""; + if (i) modifiers += "i"; + if (m) modifiers += "m"; + if (s) modifiers += "s"; + + const extractor = new XRegExp(extractorStr, modifiers), + input = await state.dish.get(Dish.STRING), + registers = input.match(extractor); + + if (!registers) return state; + + if (isWorkerEnvironment()) { + self.setRegisters(state.forkOffset + state.progress, state.numRegisters, registers.slice(1)); + } + + /** + * Replaces references to registers (e.g. $R0) with the contents of those registers. + * + * @param {string} str + * @returns {string} + */ + function replaceRegister(str) { + // Replace references to registers ($Rn) with contents of registers + return str.replace(/(\\*)\$R(\d{1,2})/g, (match, slashes, regNum) => { + const index = parseInt(regNum, 10) + 1; + if (index <= state.numRegisters || index >= state.numRegisters + registers.length) + return match; + if (slashes.length % 2 !== 0) return match.slice(1); // Remove escape + return slashes + registers[index - state.numRegisters]; + }); + } + + // Step through all subsequent ops and replace registers in args with extracted content + for (let i = state.progress + 1; i < state.opList.length; i++) { + if (state.opList[i].disabled) continue; + + let args = state.opList[i].ingValues; + args = args.map(arg => { + if (typeof arg !== "string" && typeof arg !== "object") return arg; + + if (typeof arg === "object" && Object.prototype.hasOwnProperty.call(arg, "string")) { + arg.string = replaceRegister(arg.string); + return arg; + } + return replaceRegister(arg); + }); + state.opList[i].ingValues = args; + } + + state.numRegisters += registers.length - 1; + return state; + } + +} + +export default Register; diff --git a/plugins/srktoolbox/src/core/operations/RegularExpression.mjs b/plugins/srktoolbox/src/core/operations/RegularExpression.mjs new file mode 100644 index 00000000..613f4122 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RegularExpression.mjs @@ -0,0 +1,274 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import XRegExp from "xregexp"; +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Regular expression operation + */ +class RegularExpression extends Operation { + + /** + * RegularExpression constructor + */ + constructor() { + super(); + + this.name = "正则表达式"; + this.module = "Regex"; + this.description = "用自定义的正则表达式(regex)在输入内容中执行查找。也可以在内置的正则表达式模板中选择一个。

支持扩展正则语法,如“点(.)匹配所有字符”、命名匹配组,完整Unicode支持(包括 \\p{} 类别以及Astral平面字符)和递归匹配。"; + this.infoURL = "https://wikipedia.org/wiki/Regular_expression"; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + "name": "内置正则", + "type": "populateOption", + "value": [ + { + name: "自定义", + value: "" + }, + { + name: "IPv4地址", + value: "(?:(?:\\d|[01]?\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d|\\d)(?:\\/\\d{1,2})?" + }, + { + name: "IPv6地址", + value: "((?=.*::)(?!.*::.+::)(::)?([\\dA-Fa-f]{1,4}:(:|\\b)|){5}|([\\dA-Fa-f]{1,4}:){6})((([\\dA-Fa-f]{1,4}((?!\\3)::|:\\b|(?![\\dA-Fa-f])))|(?!\\2\\3)){2}|(((2[0-4]|1\\d|[1-9])?\\d|25[0-5])\\.?\\b){4})" + }, + { + name: "Email地址", + value: "(?:[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9](?:[\\u00A0-\\uD7FF\\uE000-\\uFFFF-a-z0-9-]*[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9])?\\.)+[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9](?:[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9-]*[\\u00A0-\\uD7FF\\uE000-\\uFFFFa-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}\\])" + }, + { + name: "URL", + value: "([A-Za-z]+://)([-\\w]+(?:\\.\\w[-\\w]*)+)(:\\d+)?(/[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]*(?:[.!,?]+[^.!,?\"<>\\[\\]{}\\s\\x7F-\\xFF]+)*)?" + }, + { + name: "域名", + value: "\\b((?=[a-z0-9-]{1,63}\\.)(xn--)?[a-z0-9]+(-[a-z0-9]+)*\\.)+[a-z]{2,63}\\b" + }, + { + name: "Windows文件路径", + value: "([A-Za-z]):\\\\((?:[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)~]{0,61}\\\\?)*[A-Za-z\\d][A-Za-z\\d\\- \\x27_\\(\\)]{0,61})(\\.[A-Za-z\\d]{1,6})?" + }, + { + name: "UNIX文件路径", + value: "(?:/[A-Za-z\\d.][A-Za-z\\d\\-.]{0,61})+" + }, + { + name: "MAC地址", + value: "[A-Fa-f\\d]{2}(?:[:-][A-Fa-f\\d]{2}){5}" + }, + { + name: "UUID", + value: "[0-9a-fA-F]{8}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{4}\\b-[0-9a-fA-F]{12}" + }, + { + name: "日期 (yyyy-mm-dd)", + value: "((?:19|20)\\d\\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])" + }, + { + name: "日期 (dd/mm/yyyy)", + value: "(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.]((?:19|20)\\d\\d)" + }, + { + name: "日期 (mm/dd/yyyy)", + value: "(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.]((?:19|20)\\d\\d)" + }, + { + name: "字符串", + value: "[A-Za-z\\d/\\-:.,_$%\\x27\"()<>= !\\[\\]{}@]{4,}" + }, + ], + "target": 1 + }, + { + "name": "正则", + "type": "text", + "value": "" + }, + { + "name": "忽略大小写", + "type": "boolean", + "value": true + }, + { + "name": "^ 和 $ 按行匹配", + "type": "boolean", + "value": true + }, + { + "name": "点(.)匹配所有字符", + "type": "boolean", + "value": false + }, + { + "name": "Unicode支持", + "type": "boolean", + "value": false + }, + { + "name": "Astral支持", + "type": "boolean", + "value": false + }, + { + "name": "显示匹配总数", + "type": "boolean", + "value": false + }, + { + "name": "输出格式", + "type": "option", + "value": ["高亮匹配", "列出匹配", "列出匹配组", "列出匹配和对应匹配组"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const [, + userRegex, + i, m, s, u, a, + displayTotal, + outputFormat + ] = args; + let modifiers = "g"; + + if (i) modifiers += "i"; + if (m) modifiers += "m"; + if (s) modifiers += "s"; + if (u) modifiers += "u"; + if (a) modifiers += "A"; + + if (userRegex && userRegex !== "^" && userRegex !== "$") { + try { + const regex = new XRegExp(userRegex, modifiers); + + switch (outputFormat) { + case "高亮匹配": + return regexHighlight(input, regex, displayTotal); + case "列出匹配": + return Utils.escapeHtml(regexList(input, regex, displayTotal, true, false)); + case "列出匹配组": + return Utils.escapeHtml(regexList(input, regex, displayTotal, false, true)); + case "列出匹配和对应匹配组": + return Utils.escapeHtml(regexList(input, regex, displayTotal, true, true)); + default: + throw new OperationError("错误:无效输出格式"); + } + } catch (err) { + throw new OperationError("无效的正则表达式: " + err.message); + } + } else { + return Utils.escapeHtml(input); + } + } + +} + +/** + * Creates a string listing the matches within a string. + * + * @param {string} input + * @param {RegExp} regex + * @param {boolean} displayTotal + * @param {boolean} matches - Display full match + * @param {boolean} captureGroups - Display each of the capture groups separately + * @returns {string} + */ +function regexList(input, regex, displayTotal, matches, captureGroups) { + let output = "", + total = 0, + match; + + while ((match = regex.exec(input))) { + // Moves pointer when an empty string is matched (prevents infinite loop) + if (match.index === regex.lastIndex) { + regex.lastIndex++; + } + + total++; + if (matches) { + output += match[0] + "\n"; + } + if (captureGroups) { + for (let i = 1; i < match.length; i++) { + if (matches) { + output += " 组 " + i + ": "; + } + output += match[i] + "\n"; + } + } + } + + if (displayTotal) + output = "总计查找到: " + total + "\n\n" + output; + + return output.slice(0, -1); +} + +/** + * Adds HTML highlights to matches within a string. + * + * @private + * @param {string} input + * @param {RegExp} regex + * @param {boolean} displayTotal + * @returns {string} + */ +function regexHighlight(input, regex, displayTotal) { + let output = "", + title = "", + hl = 1, + total = 0; + const captureGroups = []; + + output = input.replace(regex, (match, ...args) => { + args.pop(); // Throw away full string + const offset = args.pop(), + groups = args; + + title = `偏移: ${offset}\n`; + if (groups.length) { + title += "匹配组:\n"; + for (let i = 0; i < groups.length; i++) { + title += `\t${i+1}: ${Utils.escapeHtml(groups[i] || "")}\n`; + } + } + + // Switch highlight + hl = hl === 1 ? 2 : 1; + + // Store highlighted match and replace with a placeholder + captureGroups.push(`${Utils.escapeHtml(match)}`); + return `[cc_capture_group_${total++}]`; + }); + + // Safely escape all remaining text, then replace placeholders + output = Utils.escapeHtml(output); + output = output.replace(/\[cc_capture_group_(\d+)\]/g, (_, i) => { + return captureGroups[i]; + }); + + if (displayTotal) + output = "总计查找到: " + total + "\n\n" + output; + + return output; +} + +export default RegularExpression; diff --git a/plugins/srktoolbox/src/core/operations/RemoveDiacritics.mjs b/plugins/srktoolbox/src/core/operations/RemoveDiacritics.mjs new file mode 100644 index 00000000..972c183e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RemoveDiacritics.mjs @@ -0,0 +1,43 @@ +/** + * @author Klaxon [klaxon@veyr.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Remove Diacritics operation + */ +class RemoveDiacritics extends Operation { + + /** + * RemoveDiacritics constructor + */ + constructor() { + super(); + + this.name = "移除变音符号"; + this.module = "Default"; + this.description = "将带有变音符号的字符转换为对应不带变音符号的拉丁字母。带有变音符号的字符原理上是使用了Unicode结合字符,所以相同原理的下划线和删除线也会一并被移除。"; + this.infoURL = "https://wikipedia.org/wiki/Diacritic"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + // reference: https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript/37511463 + return input.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); + } + +} + +export default RemoveDiacritics; diff --git a/plugins/srktoolbox/src/core/operations/RemoveEXIF.mjs b/plugins/srktoolbox/src/core/operations/RemoveEXIF.mjs new file mode 100644 index 00000000..3fa2b90e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RemoveEXIF.mjs @@ -0,0 +1,58 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import { removeEXIF } from "../vendor/remove-exif.mjs"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Remove EXIF operation + */ +class RemoveEXIF extends Operation { + + /** + * RemoveEXIF constructor + */ + constructor() { + super(); + + this.name = "移除EXIF"; + this.module = "Image"; + this.description = [ + "从JPEG图片移除EXIF数据。", + "

", + "照片的EXIF数据通常包括图像本身以及拍摄设备的信息。", + ].join("\n"); + this.infoURL = "https://wikipedia.org/wiki/Exif"; + this.inputType = "ArrayBuffer"; + this.outputType = "byteArray"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + input = new Uint8Array(input); + // Do nothing if input is empty + if (input.length === 0) return input; + + try { + return removeEXIF(input); + } catch (err) { + // Simply return input if no EXIF data is found + if (err === "Exif not found.") return input; + throw new OperationError(`无法从图像中移除EXIF数据: ${err}`); + } + } + +} + +export default RemoveEXIF; diff --git a/plugins/srktoolbox/src/core/operations/RemoveLineNumbers.mjs b/plugins/srktoolbox/src/core/operations/RemoveLineNumbers.mjs new file mode 100644 index 00000000..2ae8b2b6 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RemoveLineNumbers.mjs @@ -0,0 +1,41 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Remove line numbers operation + */ +class RemoveLineNumbers extends Operation { + + /** + * RemoveLineNumbers constructor + */ + constructor() { + super(); + + this.name = "移除行号"; + this.module = "Default"; + this.description = "在输出内容中移除行号(仅限很容易被检测到的格式)。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return input.replace(/^[ \t]{0,5}\d+[\s:|\-,.)\]]/gm, ""); + } + +} + +export default RemoveLineNumbers; diff --git a/plugins/srktoolbox/src/core/operations/RemoveNullBytes.mjs b/plugins/srktoolbox/src/core/operations/RemoveNullBytes.mjs new file mode 100644 index 00000000..04656fa9 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RemoveNullBytes.mjs @@ -0,0 +1,46 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Remove null bytes operation + */ +class RemoveNullBytes extends Operation { + + /** + * RemoveNullBytes constructor + */ + constructor() { + super(); + + this.name = "移除空字节"; + this.module = "Default"; + this.description = "从输入内容中移除所有的空字节(0x00)。"; + this.inputType = "ArrayBuffer"; + this.outputType = "byteArray"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + input = new Uint8Array(input); + const output = []; + for (let i = 0; i < input.length; i++) { + if (input[i] !== 0) output.push(input[i]); + } + return output; + } + +} + +export default RemoveNullBytes; diff --git a/plugins/srktoolbox/src/core/operations/RemoveWhitespace.mjs b/plugins/srktoolbox/src/core/operations/RemoveWhitespace.mjs new file mode 100644 index 00000000..9113f2e6 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RemoveWhitespace.mjs @@ -0,0 +1,88 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Remove whitespace operation + */ +class RemoveWhitespace extends Operation { + + /** + * RemoveWhitespace constructor + */ + constructor() { + super(); + + this.name = "移除空白字符"; + this.module = "Default"; + this.description = "从输入文本中移除空格、回车(CR)、换行(LF)、制表符(Tab)和换页(FF)。

此操作也支持移除英文句点(.),因为有时句点用于表示ASCII中无法显示的字符。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "空格", + "type": "boolean", + "value": true + }, + { + "name": "回车(CR,\\r)", + "type": "boolean", + "value": true + }, + { + "name": "换行(LF,\\n)", + "type": "boolean", + "value": true + }, + { + "name": "制表符(Tab,\\t)", + "type": "boolean", + "value": true + }, + { + "name": "换页符(FF,\\f)", + "type": "boolean", + "value": true + }, + { + "name": "英文句点(.)", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [ + removeSpaces, + removeCarriageReturns, + removeLineFeeds, + removeTabs, + removeFormFeeds, + removeFullStops + ] = args; + let data = input; + + if (removeSpaces) data = data.replace(/ /g, ""); + if (removeCarriageReturns) data = data.replace(/\r/g, ""); + if (removeLineFeeds) data = data.replace(/\n/g, ""); + if (removeTabs) data = data.replace(/\t/g, ""); + if (removeFormFeeds) data = data.replace(/\f/g, ""); + if (removeFullStops) data = data.replace(/\./g, ""); + return data; + } + +} + +export default RemoveWhitespace; diff --git a/plugins/srktoolbox/src/core/operations/RenderImage.mjs b/plugins/srktoolbox/src/core/operations/RenderImage.mjs new file mode 100644 index 00000000..59113711 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RenderImage.mjs @@ -0,0 +1,114 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import { fromBase64, toBase64 } from "../lib/Base64.mjs"; +import { fromHex } from "../lib/Hex.mjs"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import {isImage} from "../lib/FileType.mjs"; + +/** + * Render Image operation + */ +class RenderImage extends Operation { + + /** + * RenderImage constructor + */ + constructor() { + super(); + + this.name = "渲染图像"; + this.module = "Image"; + this.description = "将输入内容显示成图像。支持以下格式:

  • jpg/jpeg
  • png
  • gif
  • webp
  • bmp
  • ico
"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.presentType = "html"; + this.args = [ + { + "name": "输入格式", + "type": "option", + "value": ["原始", "Base64", "十六进制"] + } + ]; + this.checks = [ + { + pattern: "^(?:\\xff\\xd8\\xff|\\x89\\x50\\x4e\\x47|\\x47\\x49\\x46|.{8}\\x57\\x45\\x42\\x50|\\x42\\x4d)", + flags: "", + args: ["原始"], + useful: true, + output: { + mime: "image" + } + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const inputFormat = args[0]; + + if (!input.length) return []; + + // Convert input to raw bytes + switch (inputFormat) { + case "十六进制": + input = fromHex(input); + break; + case "Base64": + // Don't trust the Base64 entered by the user. + // Unwrap it first, then re-encode later. + input = fromBase64(input, undefined, "byteArray"); + break; + case "原始": + default: + input = Utils.strToByteArray(input); + break; + } + + // Determine file type + if (!isImage(input)) { + throw new OperationError("无效的文件类型"); + } + + return input; + } + + /** + * Displays the image using HTML for web apps. + * + * @param {byteArray} data + * @returns {html} + */ + async present(data) { + if (!data.length) return ""; + + let dataURI = "data:"; + + // Determine file type + const mime = isImage(data); + if (mime) { + dataURI += mime + ";"; + } else { + throw new OperationError("无效的文件类型"); + } + + // Add image data to URI + dataURI += "base64," + toBase64(data); + + return ""; + } + +} + +export default RenderImage; diff --git a/plugins/srktoolbox/src/core/operations/RenderMarkdown.mjs b/plugins/srktoolbox/src/core/operations/RenderMarkdown.mjs new file mode 100644 index 00000000..d1b3a5f9 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RenderMarkdown.mjs @@ -0,0 +1,71 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import MarkdownIt from "markdown-it"; +import hljs from "highlight.js"; + +/** + * Render Markdown operation + */ +class RenderMarkdown extends Operation { + + /** + * RenderMarkdown constructor + */ + constructor() { + super(); + + this.name = "渲染Markdown"; + this.module = "Code"; + this.description = "将输入的Markdown渲染为HTML。HTML不会直接被渲染,防止XSS攻击。"; + this.infoURL = "https://wikipedia.org/wiki/Markdown"; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + name: "自动将URL转换为链接", + type: "boolean", + value: false + }, + { + name: "开启语法高亮", + type: "boolean", + value: true + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const [convertLinks, enableHighlighting] = args, + md = new MarkdownIt({ + linkify: convertLinks, + html: false, // Explicitly disable HTML rendering + highlight: function(str, lang) { + if (lang && hljs.getLanguage(lang) && enableHighlighting) { + try { + return hljs.highlight(lang, str).value; + } catch (__) {} + } + + return ""; + } + }), + rendered = md.render(input); + + return `
${rendered}
`; + } + +} + +export default RenderMarkdown; diff --git a/plugins/srktoolbox/src/core/operations/ResizeImage.mjs b/plugins/srktoolbox/src/core/operations/ResizeImage.mjs new file mode 100644 index 00000000..a562310d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ResizeImage.mjs @@ -0,0 +1,154 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; +import { Jimp, JimpMime, ResizeStrategy } from "jimp"; + +/** + * Resize Image operation + */ +class ResizeImage extends Operation { + /** + * ResizeImage constructor + */ + constructor() { + super(); + + this.name = "图像尺寸修改"; + this.module = "Image"; + this.description = + "将图像尺寸变更为给定的高和宽。"; + this.infoURL = "https://wikipedia.org/wiki/Image_scaling"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = [ + { + name: "宽度", + type: "number", + value: 100, + min: 1, + }, + { + name: "高度", + type: "number", + value: 100, + min: 1, + }, + { + name: "单位", + type: "option", + value: ["像素", "百分比"], + }, + { + name: "保持长宽比", + type: "boolean", + value: false, + }, + { + name: "缩放插值算法", + type: "option", + value: [ + "临近", + "双线性", + "双三次", + "Hermite", + "Bezier", + ], + defaultIndex: 1, + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + async run(input, args) { + let width = args[0], + height = args[1]; + const unit = args[2], + aspect = args[3], + resizeAlg = args[4]; + + const resizeMap = { + "临近": ResizeStrategy.NEAREST_NEIGHBOR, + 双线性: ResizeStrategy.BILINEAR, + 双三次: ResizeStrategy.BICUBIC, + Hermite: ResizeStrategy.HERMITE, + Bezier: ResizeStrategy.BEZIER, + }; + + if (!isImage(input)) { + throw new OperationError("无效的文件类型。"); + } + + let image; + try { + image = await Jimp.read(input); + } catch (err) { + throw new OperationError(`载入图片错误:(${err})`); + } + try { + if (unit === "百分比") { + width = image.width * (width / 100); + height = image.height * (height / 100); + } + + if (isWorkerEnvironment()) + self.sendStatusMessage("缩放图像……"); + if (aspect) { + image.scaleToFit({ + w: width, + h: height, + mode: resizeMap[resizeAlg], + }); + } else { + image.resize({ + w: width, + h: height, + mode: resizeMap[resizeAlg], + }); + } + + let imageBuffer; + if (image.mime === "image/gif") { + imageBuffer = await image.getBuffer(JimpMime.png); + } else { + imageBuffer = await image.getBuffer(image.mime); + } + return imageBuffer.buffer; + } catch (err) { + throw new OperationError(`缩放图像出错:(${err})`); + } + } + + /** + * Displays the resized image using HTML for web apps + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const dataArray = new Uint8Array(data); + + const type = isImage(dataArray); + if (!type) { + throw new OperationError("无效的文件类型"); + } + + return ``; + } +} + +export default ResizeImage; diff --git a/plugins/srktoolbox/src/core/operations/Return.mjs b/plugins/srktoolbox/src/core/operations/Return.mjs new file mode 100644 index 00000000..07c1e497 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Return.mjs @@ -0,0 +1,45 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Return operation + */ +class Return extends Operation { + + /** + * Return constructor + */ + constructor() { + super(); + + this.name = "Return"; + this.flowControl = true; + this.module = "Default"; + this.description = "结束此流程的操作运行。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on. + * @param {Operation[]} state.opList - The list of operations in the recipe. + * @returns {Object} The updated state of the recipe. + */ + run(state) { + state.progress = state.opList.length; + return state; + } + +} + +export default Return; diff --git a/plugins/srktoolbox/src/core/operations/Reverse.mjs b/plugins/srktoolbox/src/core/operations/Reverse.mjs new file mode 100644 index 00000000..27e006b9 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Reverse.mjs @@ -0,0 +1,89 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Reverse operation + */ +class Reverse extends Operation { + + /** + * Reverse constructor + */ + constructor() { + super(); + + this.name = "反转"; + this.module = "Default"; + this.description = "反转字符串。"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "粒度", + "type": "option", + "value": ["字节", "字符", "行"], + "defaultIndex": 1 + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + let i; + if (args[0] === "行") { + const lines = []; + let line = [], + result = []; + for (i = 0; i < input.length; i++) { + if (input[i] === 0x0a) { + lines.push(line); + line = []; + } else { + line.push(input[i]); + } + } + lines.push(line); + lines.reverse(); + for (i = 0; i < lines.length; i++) { + result = result.concat(lines[i]); + result.push(0x0a); + } + return result.slice(0, input.length); + } else if (args[0] === "字符") { + const inputString = Utils.byteArrayToUtf8(input); + let result = ""; + for (let i = inputString.length - 1; i >= 0; i--) { + const c = inputString.charCodeAt(i); + if (i > 0 && 0xdc00 <= c && c <= 0xdfff) { + const c2 = inputString.charCodeAt(i - 1); + if (0xd800 <= c2 && c2 <= 0xdbff) { + // surrogates + result += inputString.charAt(i - 1); + result += inputString.charAt(i); + i--; + continue; + } + } + result += inputString.charAt(i); + } + return Utils.strToUtf8ByteArray(result); + } else { + return input.reverse(); + } + } + +} + +export default Reverse; diff --git a/plugins/srktoolbox/src/core/operations/RisonDecode.mjs b/plugins/srktoolbox/src/core/operations/RisonDecode.mjs new file mode 100644 index 00000000..229c9231 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RisonDecode.mjs @@ -0,0 +1,59 @@ +/** + * @author sg5506844 [sg5506844@gmail.com] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import rison from "rison"; + +/** + * Rison Decode operation + */ +class RisonDecode extends Operation { + + /** + * RisonDecode constructor + */ + constructor() { + super(); + + this.name = "Rison解码"; + this.module = "Encodings"; + this.description = "Rison是一种紧凑的数据序列化格式,专门为能在URI中使用进行了优化。Rison在JSON的基础上进行了少量改进,使得序列化数据在URI编码后看起来十分直观。Rison表示的数据结构和JSON是一致的,因此数据可以在两种格式间无损互转。"; + this.infoURL = "https://github.com/Nanonid/rison"; + this.inputType = "string"; + this.outputType = "Object"; + this.args = [ + { + name: "解码选项", + type: "Option", + value: ["普通解码", "解码为对象(O-Rison)", "解码为数组(A-Rison)"] + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {Object} + */ + run(input, args) { + const [decodeOption] = args; + switch (decodeOption) { + case "普通解码": + return rison.decode(input); + case "解码为对象(O-Rison)": + return rison.decode_object(input); + case "解码为数组(A-Rison)": + return rison.decode_array(input); + default: + throw new OperationError("无效的解码选项"); + } + } +} + +export default RisonDecode; diff --git a/plugins/srktoolbox/src/core/operations/RisonEncode.mjs b/plugins/srktoolbox/src/core/operations/RisonEncode.mjs new file mode 100644 index 00000000..56b14491 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RisonEncode.mjs @@ -0,0 +1,61 @@ +/** + * @author sg5506844 [sg5506844@gmail.com] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import rison from "rison"; + +/** + * Rison Encode operation + */ +class RisonEncode extends Operation { + + /** + * RisonEncode constructor + */ + constructor() { + super(); + + this.name = "Rison编码"; + this.module = "Encodings"; + this.description = "Rison是一种紧凑的数据序列化格式,专门为能在URI中使用进行了优化。Rison在JSON的基础上进行了少量改进,使得序列化数据在URI编码后看起来十分直观。Rison表示的数据结构和JSON是一致的,因此数据可以在两种格式间无损互转。"; + this.infoURL = "https://github.com/Nanonid/rison"; + this.inputType = "Object"; + this.outputType = "string"; + this.args = [ + { + name: "编码选项", + type: "Option", + value: ["普通编码", "编码为对象(O-Rison)", "编码为数组(A-Rison)", "编码为URI"] + }, + ]; + } + + /** + * @param {Object} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [encodeOption] = args; + switch (encodeOption) { + case "普通编码": + return rison.encode(input); + case "编码为对象(O-Rison)": + return rison.encode_object(input); + case "编码为数组(A-Rison)": + return rison.encode_array(input); + case "编码为URI": + return rison.encode_uri(input); + default: + throw new OperationError("无效的编码选项"); + } + } +} + +export default RisonEncode; diff --git a/plugins/srktoolbox/src/core/operations/RoarCipherDecode.mjs b/plugins/srktoolbox/src/core/operations/RoarCipherDecode.mjs new file mode 100644 index 00000000..2ac50a75 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RoarCipherDecode.mjs @@ -0,0 +1,87 @@ +/** + * @author Raka-loah [i@lotc.cc] + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Roar Cipher Decode operation + */ +class RoarCipherDecode extends Operation { + + /** + * RoarCipherDecode constructor + */ + constructor() { + super(); + + this.name = "兽音译者解密"; + this.module = "Default"; + this.description = "把各种“嗷呜啊”解密为原始文本,支持自定义字典。"; + this.infoURL = ""; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "字典(4个字符)", + type: "editableOption", + value: [ + { + name: "默认", + value: "嗷呜啊~" + }, + { + name: "自定义", + value: "" + } + ] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [alphabet] = args; + + if (alphabet.length !== 4) { + throw new OperationError("错误:字典长度必须为4个字符!"); + } + + if (input.length <= 5) { + throw new OperationError("错误:密文长度必须大于5个字符!"); + } + + const alphaList = alphabet.split(""); + const roarChunks = input.substring(3, input.length - 1).match(/.{2}/g); + + const rawHex = roarChunks.reduce(function (rawStr, roarChunk, currentIndex) { + const roarValue1 = alphaList.indexOf(roarChunk[0]); + const roarValue2 = alphaList.indexOf(roarChunk[1]); + + if (roarValue1 === -1 || roarValue2 === -1) { + throw new OperationError("错误:密文中包含不在字典中的字符!"); + } + + let temp = roarValue1 * 4 + roarValue2 - currentIndex % 0x10; + if (temp < 0) { + temp += 0x10; + } + + rawStr += temp.toString(16); + + return rawStr; + }, ""); + + const raw = rawHex.match(/.{4}/g).reduce((rawStr, hexChunk) => rawStr + String.fromCharCode(parseInt("0x" + hexChunk, 16)), ""); + return raw; + } +} + +export default RoarCipherDecode; diff --git a/plugins/srktoolbox/src/core/operations/RoarCipherEncode.mjs b/plugins/srktoolbox/src/core/operations/RoarCipherEncode.mjs new file mode 100644 index 00000000..61ced1d2 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RoarCipherEncode.mjs @@ -0,0 +1,78 @@ +/** + * @author Raka-loah [i@lotc.cc] + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Roar Cipher Encode operation + */ +class RoarCipherEncode extends Operation { + + /** + * RoarCipherEncode constructor + */ + constructor() { + super(); + + this.name = "兽音译者加密"; + this.module = "Default"; + this.description = "把输入的文本加密为各种“嗷呜啊”,支持自定义字典。"; + this.infoURL = ""; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "字典(4个字符)", + type: "editableOption", + value: [ + { + name: "默认", + value: "嗷呜啊~" + }, + { + name: "自定义", + value: "" + } + ] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [alphabet] = args; + + if (alphabet.length !== 4) { + throw new OperationError("错误:字典长度必须为4个字符!"); + } + + if (input.length === 0) { + return ""; + } + + const alphaList = alphabet.split(""); + const hexInput = input.split("").map(character => character.charCodeAt(0).toString(16).padStart(4, "0")).join(""); + const roar = hexInput.split("").reduce(function (roarStr, hexStr, currentIndex) { + let temp = 0; + temp = parseInt("0x" + hexStr, 16) + currentIndex % 0x10; + if (temp >= 0x10) { + temp -= 0x10; + } + roarStr += alphaList[parseInt(temp / 4, 10)] + alphaList[temp % 4]; + return roarStr; + }, ""); + + return alphaList[3] + alphaList[1] + alphaList[0] + roar + alphaList[2]; + } + +} + +export default RoarCipherEncode; diff --git a/plugins/srktoolbox/src/core/operations/RotateImage.mjs b/plugins/srktoolbox/src/core/operations/RotateImage.mjs new file mode 100644 index 00000000..6529a39a --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RotateImage.mjs @@ -0,0 +1,96 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; +import { Jimp, JimpMime } from "jimp"; + +/** + * Rotate Image operation + */ +class RotateImage extends Operation { + /** + * RotateImage constructor + */ + constructor() { + super(); + + this.name = "旋转图像"; + this.module = "Image"; + this.description = + "按给定的角度旋转图像。"; + this.infoURL = ""; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = [ + { + name: "旋转角度", + type: "number", + value: 90, + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + async run(input, args) { + const [degrees] = args; + + if (!isImage(input)) { + throw new OperationError("无效的文件类型。"); + } + + let image; + try { + image = await Jimp.read(input); + } catch (err) { + throw new OperationError(`载入图像出错:(${err})`); + } + try { + if (isWorkerEnvironment()) + self.sendStatusMessage("旋转图像……"); + image.rotate(degrees); + + let imageBuffer; + if (image.mime === "image/gif") { + imageBuffer = await image.getBuffer(JimpMime.png); + } else { + imageBuffer = await image.getBuffer(image.mime); + } + return imageBuffer.buffer; + } catch (err) { + throw new OperationError(`旋转图像出错:(${err})`); + } + } + + /** + * Displays the rotated image using HTML for web apps + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const dataArray = new Uint8Array(data); + + const type = isImage(dataArray); + if (!type) { + throw new OperationError("无效的文件类型。"); + } + + return ``; + } +} + +export default RotateImage; diff --git a/plugins/srktoolbox/src/core/operations/RotateLeft.mjs b/plugins/srktoolbox/src/core/operations/RotateLeft.mjs new file mode 100644 index 00000000..e874b754 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RotateLeft.mjs @@ -0,0 +1,84 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {rot, rotl, rotlCarry} from "../lib/Rotate.mjs"; + + +/** + * Rotate left operation. + */ +class RotateLeft extends Operation { + + /** + * RotateLeft constructor + */ + constructor() { + super(); + + this.name = "循环左移"; + this.module = "Default"; + this.description = "将每个字节按照给定的偏移量循环左移,可选择是否进位。当前只支持8位数值。"; + this.infoURL = "https://wikipedia.org/wiki/Bitwise_operation#Bit_shifts"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "偏移量", + type: "number", + value: 1 + }, + { + name: "进位", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + if (args[1]) { + return rotlCarry(input, args[0]); + } else { + return rot(input, args[0], rotl); + } + } + + /** + * Highlight rotate left + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight rotate left in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } +} + +export default RotateLeft; diff --git a/plugins/srktoolbox/src/core/operations/RotateRight.mjs b/plugins/srktoolbox/src/core/operations/RotateRight.mjs new file mode 100644 index 00000000..13bdf80e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/RotateRight.mjs @@ -0,0 +1,84 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {rot, rotr, rotrCarry} from "../lib/Rotate.mjs"; + + +/** + * Rotate right operation. + */ +class RotateRight extends Operation { + + /** + * RotateRight constructor + */ + constructor() { + super(); + + this.name = "循环右移"; + this.module = "Default"; + this.description = "将每个字节按照给定的偏移量循环右移,可选择是否进位。当前只支持8位数值。"; + this.infoURL = "https://wikipedia.org/wiki/Bitwise_operation#Bit_shifts"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "偏移量", + type: "number", + value: 1 + }, + { + name: "进位", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + if (args[1]) { + return rotrCarry(input, args[0]); + } else { + return rot(input, args[0], rotr); + } + } + + /** + * Highlight rotate right + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight rotate right in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } +} + +export default RotateRight; diff --git a/plugins/srktoolbox/src/core/operations/SHA0.mjs b/plugins/srktoolbox/src/core/operations/SHA0.mjs new file mode 100644 index 00000000..66b6d32f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SHA0.mjs @@ -0,0 +1,50 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * SHA0 operation + */ +class SHA0 extends Operation { + + /** + * SHA0 constructor + */ + constructor() { + super(); + + this.name = "SHA0"; + this.module = "Crypto"; + this.description = "SHA最初载明的算法于1993年发布,称做安全散列标准(Secure Hash Standard),FIPS PUB 180。这个版本现在常被称为SHA-0。它在发布之后很快就被NSA撤回,并且由1995年发布的修订版本FIPS PUB 180-1(通常称为SHA-1)取代。此算法默认进行80轮运算。"; + this.infoURL = "https://wikipedia.org/wiki/SHA-1#SHA-0"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "轮数", + type: "number", + value: 80, + min: 16 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return runHash("sha0", input, {rounds: args[0]}); + } + +} + +export default SHA0; diff --git a/plugins/srktoolbox/src/core/operations/SHA1.mjs b/plugins/srktoolbox/src/core/operations/SHA1.mjs new file mode 100644 index 00000000..ae5880c1 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SHA1.mjs @@ -0,0 +1,50 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * SHA1 operation + */ +class SHA1 extends Operation { + + /** + * SHA1 constructor + */ + constructor() { + super(); + + this.name = "SHA1"; + this.module = "Crypto"; + this.description = "SHA-1(英语:Secure Hash Algorithm 1,中文名:安全散列算法1)是一种密码散列函数,美国国家安全局设计,并由美国国家标准技术研究所(NIST)发布为联邦资料处理标准(FIPS)。SHA-1是SHA系列算法中最常见的一种,广泛用于安全应用与协议中。

2020年,针对SHA-1的选择前缀冲突攻击已经实际可行。此算法默认进行80轮运算。"; + this.infoURL = "https://wikipedia.org/wiki/SHA-1"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "轮数", + type: "number", + value: 80, + min: 16 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return runHash("sha1", input, {rounds: args[0]}); + } + +} + +export default SHA1; diff --git a/plugins/srktoolbox/src/core/operations/SHA2.mjs b/plugins/srktoolbox/src/core/operations/SHA2.mjs new file mode 100644 index 00000000..b4abb49b --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SHA2.mjs @@ -0,0 +1,94 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * SHA2 operation + */ +class SHA2 extends Operation { + + /** + * SHA2 constructor + */ + constructor() { + super(); + + this.name = "SHA2"; + this.module = "Crypto"; + this.description = "SHA-2,名称来自于安全散列算法2(英语:Secure Hash Algorithm 2)的缩写,一种密码散列函数算法标准,由美国国家安全局研发[3],由美国国家标准与技术研究院(NIST)在2001年发布。属于SHA算法之一,是SHA-1的后继者。其下又可再分为六个不同的算法标准,包括了:SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。

  • SHA-512操作于64位字长。
  • SHA-256操作于32位字长。
  • SHA-384和SHA-512基本相同,但截断到了384字节。
  • SHA-224和SHA-256基本相同,但截断到了224字节。
  • SHA-512/224和SHA-512/256是SHA-512的截断版本,但初始值使用记载于Federal Information Processing Standards (FIPS)的PUB 180-4文档中的方法计算。
此算法对于SHA256系列默认进行64轮运算,对SHA512系列默认160轮。"; + this.infoURL = "https://wikipedia.org/wiki/SHA-2"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "长度", + type: "argSelector", + value: [ + { + name: "512", + on: [2], + off: [1] + }, + { + name: "384", + on: [2], + off: [1] + }, + { + name: "256", + on: [1], + off: [2] + }, + { + name: "224", + on: [1], + off: [2] + }, + { + name: "512/256", + on: [2], + off: [1] + }, + { + name: "512/224", + on: [2], + off: [1] + } + ] + }, + { + name: "轮数", // For SHA256 variants + type: "number", + value: 64, + min: 16 + }, + { + name: "轮数", // For SHA512 variants + type: "number", + value: 160, + min: 32 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const size = args[0]; + const rounds = (size === "256" || size === "224") ? args[1] : args[2]; + return runHash("sha" + size, input, {rounds: rounds}); + } + +} + +export default SHA2; diff --git a/plugins/srktoolbox/src/core/operations/SHA3.mjs b/plugins/srktoolbox/src/core/operations/SHA3.mjs new file mode 100644 index 00000000..bb36f173 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SHA3.mjs @@ -0,0 +1,70 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import JSSHA3 from "js-sha3"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * SHA3 operation + */ +class SHA3 extends Operation { + + /** + * SHA3 constructor + */ + constructor() { + super(); + + this.name = "SHA3"; + this.module = "Crypto"; + this.description = "SHA-3第三代安全散列算法(Secure Hash Algorithm 3)在2015年8月5日由 NIST 通过 FIPS 202 正式发表。

SHA-3是Keccak系列算法的子集。Keccak是由 Guido Bertoni,Joan Daemen,Michaël Peeters,以及Gilles Van Assche在RadioGatún上设计的哈希算法。"; + this.infoURL = "https://wikipedia.org/wiki/SHA-3"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "长度", + "type": "option", + "value": ["512", "384", "256", "224"] + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const size = parseInt(args[0], 10); + let algo; + + switch (size) { + case 224: + algo = JSSHA3.sha3_224; + break; + case 384: + algo = JSSHA3.sha3_384; + break; + case 256: + algo = JSSHA3.sha3_256; + break; + case 512: + algo = JSSHA3.sha3_512; + break; + default: + throw new OperationError("无效长度"); + } + + return algo(input); + } + +} + +export default SHA3; diff --git a/plugins/srktoolbox/src/core/operations/SIGABA.mjs b/plugins/srktoolbox/src/core/operations/SIGABA.mjs new file mode 100644 index 00000000..e3a9b82e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SIGABA.mjs @@ -0,0 +1,287 @@ +/** + * Emulation of the SIGABA machine. + * + * @author hettysymes + * @copyright hettysymes 2020 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import {LETTERS} from "../lib/Enigma.mjs"; +import {NUMBERS, CR_ROTORS, I_ROTORS, SigabaMachine, CRRotor, IRotor} from "../lib/SIGABA.mjs"; + +/** + * Sigaba operation + */ +class Sigaba extends Operation { + + /** + * Sigaba constructor + */ + constructor() { + super(); + + this.name = "SIGABA"; + this.module = "Bletchley"; + this.description = "Encipher/decipher with the WW2 SIGABA machine.

SIGABA, otherwise known as ECM Mark II, was used by the United States for message encryption during WW2 up to the 1950s. It was developed in the 1930s by the US Army and Navy, and has up to this day never been broken. Consisting of 15 rotors: 5 cipher rotors and 10 rotors (5 control rotors and 5 index rotors) controlling the stepping of the cipher rotors, the rotor stepping for SIGABA is much more complex than other rotor machines of its time, such as Enigma. All example rotor wirings are random example sets.

To configure rotor wirings, for the cipher and control rotors enter a string of letters which map from A to Z, and for the index rotors enter a sequence of numbers which map from 0 to 9. Note that encryption is not the same as decryption, so first choose the desired mode.

Note: Whilst this has been tested against other software emulators, it has not been tested against hardware."; + this.infoURL = "https://wikipedia.org/wiki/SIGABA"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "1st (left-hand) cipher rotor", + type: "editableOption", + value: CR_ROTORS, + defaultIndex: 0 + }, + { + name: "1st cipher rotor reversed", + type: "boolean", + value: false + }, + { + name: "1st cipher rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "2nd cipher rotor", + type: "editableOption", + value: CR_ROTORS, + defaultIndex: 0 + }, + { + name: "2nd cipher rotor reversed", + type: "boolean", + value: false + }, + { + name: "2nd cipher rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "3rd (middle) cipher rotor", + type: "editableOption", + value: CR_ROTORS, + defaultIndex: 0 + }, + { + name: "3rd cipher rotor reversed", + type: "boolean", + value: false + }, + { + name: "3rd cipher rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "4th cipher rotor", + type: "editableOption", + value: CR_ROTORS, + defaultIndex: 0 + }, + { + name: "4th cipher rotor reversed", + type: "boolean", + value: false + }, + { + name: "4th cipher rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "5th (right-hand) cipher rotor", + type: "editableOption", + value: CR_ROTORS, + defaultIndex: 0 + }, + { + name: "5th cipher rotor reversed", + type: "boolean", + value: false + }, + { + name: "5th cipher rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "1st (left-hand) control rotor", + type: "editableOption", + value: CR_ROTORS, + defaultIndex: 0 + }, + { + name: "1st control rotor reversed", + type: "boolean", + value: false + }, + { + name: "1st control rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "2nd control rotor", + type: "editableOption", + value: CR_ROTORS, + defaultIndex: 0 + }, + { + name: "2nd control rotor reversed", + type: "boolean", + value: false + }, + { + name: "2nd control rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "3rd (middle) control rotor", + type: "editableOption", + value: CR_ROTORS, + defaultIndex: 0 + }, + { + name: "3rd control rotor reversed", + type: "boolean", + value: false + }, + { + name: "3rd control rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "4th control rotor", + type: "editableOption", + value: CR_ROTORS, + defaultIndex: 0 + }, + { + name: "4th control rotor reversed", + type: "boolean", + value: false + }, + { + name: "4th control rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "5th (right-hand) control rotor", + type: "editableOption", + value: CR_ROTORS, + defaultIndex: 0 + }, + { + name: "5th control rotor reversed", + type: "boolean", + value: false + }, + { + name: "5th control rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "1st (left-hand) index rotor", + type: "editableOption", + value: I_ROTORS, + defaultIndex: 0 + }, + { + name: "1st index rotor initial value", + type: "option", + value: NUMBERS + }, + { + name: "2nd index rotor", + type: "editableOption", + value: I_ROTORS, + defaultIndex: 0 + }, + { + name: "2nd index rotor initial value", + type: "option", + value: NUMBERS + }, + { + name: "3rd (middle) index rotor", + type: "editableOption", + value: I_ROTORS, + defaultIndex: 0 + }, + { + name: "3rd index rotor initial value", + type: "option", + value: NUMBERS + }, + { + name: "4th index rotor", + type: "editableOption", + value: I_ROTORS, + defaultIndex: 0 + }, + { + name: "4th index rotor initial value", + type: "option", + value: NUMBERS + }, + { + name: "5th (right-hand) index rotor", + type: "editableOption", + value: I_ROTORS, + defaultIndex: 0 + }, + { + name: "5th index rotor initial value", + type: "option", + value: NUMBERS + }, + { + name: "SIGABA mode", + type: "option", + value: ["Encrypt", "Decrypt"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const sigabaSwitch = args[40]; + const cipherRotors = []; + const controlRotors = []; + const indexRotors = []; + for (let i=0; i<5; i++) { + const rotorWiring = args[i*3]; + cipherRotors.push(new CRRotor(rotorWiring, args[i*3+2], args[i*3+1])); + } + for (let i=5; i<10; i++) { + const rotorWiring = args[i*3]; + controlRotors.push(new CRRotor(rotorWiring, args[i*3+2], args[i*3+1])); + } + for (let i=15; i<20; i++) { + const rotorWiring = args[i*2]; + indexRotors.push(new IRotor(rotorWiring, args[i*2+1])); + } + const sigaba = new SigabaMachine(cipherRotors, controlRotors, indexRotors); + let result; + if (sigabaSwitch === "Encrypt") { + result = sigaba.encrypt(input); + } else if (sigabaSwitch === "Decrypt") { + result = sigaba.decrypt(input); + } + return result; + } + +} +export default Sigaba; diff --git a/plugins/srktoolbox/src/core/operations/SM2Decrypt.mjs b/plugins/srktoolbox/src/core/operations/SM2Decrypt.mjs new file mode 100644 index 00000000..46ac631b --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SM2Decrypt.mjs @@ -0,0 +1,73 @@ +/** + * @author flakjacket95 [dflack95@gmail.com] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import OperationError from "../errors/OperationError.mjs"; +import Operation from "../Operation.mjs"; + +import { SM2 } from "../lib/SM2.mjs"; + +/** + * SM2Decrypt operation + */ +class SM2Decrypt extends Operation { + + /** + * SM2Decrypt constructor + */ + constructor() { + super(); + + this.name = "SM2解密"; + this.module = "Crypto"; + this.description = "解密使用SM2标准编码的消息。"; + this.infoURL = "https://zh.wikipedia.org/wiki/SM2"; + this.inputType = "string"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + name: "私钥", + type: "string", + value: "DEADBEEF" + }, + { + "name": "输入格式", + "type": "option", + "value": ["C1C3C2", "C1C2C3"], + "defaultIndex": 0 + }, + { + name: "曲线", + type: "option", + "value": ["sm2p256v1"], + "defaultIndex": 0 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const [privateKey, inputFormat, curveName] = args; + + if (privateKey.length !== 64) { + throw new OperationError("输入的私钥必须为32字节长度的十六进制"); + } + + const sm2 = new SM2(curveName, inputFormat); + sm2.setPrivateKey(privateKey); + + const result = sm2.decrypt(input); + return result; + } + +} + +export default SM2Decrypt; diff --git a/plugins/srktoolbox/src/core/operations/SM2Encrypt.mjs b/plugins/srktoolbox/src/core/operations/SM2Encrypt.mjs new file mode 100644 index 00000000..70a5b7f2 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SM2Encrypt.mjs @@ -0,0 +1,79 @@ +/** + * @author flakjacket95 [dflack95@gmail.com] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import OperationError from "../errors/OperationError.mjs"; +import Operation from "../Operation.mjs"; + +import { SM2 } from "../lib/SM2.mjs"; + +/** + * SM2 Encrypt operation + */ +class SM2Encrypt extends Operation { + + /** + * SM2Encrypt constructor + */ + constructor() { + super(); + + this.name = "SM2加密"; + this.module = "Crypto"; + this.description = "使用SM2标准加密消息"; + this.infoURL = "https://zh.wikipedia.org/wiki/SM2"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + + this.args = [ + { + name: "公钥X", + type: "string", + value: "DEADBEEF" + }, + { + name: "公钥Y", + type: "string", + value: "DEADBEEF" + }, + { + "name": "输出格式", + "type": "option", + "value": ["C1C3C2", "C1C2C3"], + "defaultIndex": 0 + }, + { + name: "曲线", + type: "option", + "value": ["sm2p256v1"], + "defaultIndex": 0 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const [publicKeyX, publicKeyY, outputFormat, curveName] = args; + this.outputFormat = outputFormat; + + if (publicKeyX.length !== 64 || publicKeyY.length !== 64) { + throw new OperationError("无效的公钥 - 确保每个公钥都是32字节长度的十六进制"); + } + + const sm2 = new SM2(curveName, outputFormat); + sm2.setPublicKey(publicKeyX, publicKeyY); + + const result = sm2.encrypt(new Uint8Array(input)); + return result; + } +} + +export default SM2Encrypt; diff --git a/plugins/srktoolbox/src/core/operations/SM3.mjs b/plugins/srktoolbox/src/core/operations/SM3.mjs new file mode 100644 index 00000000..0d4bd762 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SM3.mjs @@ -0,0 +1,59 @@ +/** + * @author n1073645 [n1073645@gmail.com] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import Sm3 from "crypto-api/src/hasher/sm3.mjs"; +import {toHex} from "crypto-api/src/encoder/hex.mjs"; + +/** + * SM3 operation + */ +class SM3 extends Operation { + + /** + * SM3 constructor + */ + constructor() { + super(); + + this.name = "SM3"; + this.module = "Crypto"; + this.description = "SM3是中华人民共和国政府采用的一种密码散列函数标准,前身为SCH4杂凑算法,由国家密码管理局于2010年12月17日发布,相关标准为“GM/T 0004-2012 《SM3密码杂凑算法》”。2016年,成为中国国家密码标准(GB/T 32905-2016)。此算法默认进行64轮运算,长度256位。"; + this.infoURL = "https://wikipedia.org/wiki/SM3_(hash_function)"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "长度", + type: "number", + value: 256 + }, + { + name: "轮数", + type: "number", + value: 64, + min: 16 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const msg = Utils.arrayBufferToStr(input, false); + const hasher = new Sm3({length: args[0], rounds: args[1]}); + hasher.update(msg); + return toHex(hasher.finalize()); + } +} + +export default SM3; diff --git a/plugins/srktoolbox/src/core/operations/SM4Decrypt.mjs b/plugins/srktoolbox/src/core/operations/SM4Decrypt.mjs new file mode 100644 index 00000000..85e0acb5 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SM4Decrypt.mjs @@ -0,0 +1,90 @@ +/** + * @author swesven + * @copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { toHex } from "../lib/Hex.mjs"; +import { decryptSM4 } from "../lib/SM4.mjs"; + +/** + * SM4 Decrypt operation + */ +class SM4Decrypt extends Operation { + + /** + * SM4Encrypt constructor + */ + constructor() { + super(); + + this.name = "SM4解密"; + this.module = "Ciphers"; + this.description = "SM4是128位的分组密码,2016年8月,成为中国国家密码标准(GB/T 32907-2016)。"; + this.infoURL = "https://wikipedia.org/wiki/SM4_(cipher)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Key", + "type": "toggleString", + "value": "", + "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"] + }, + { + "name": "IV", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + "name": "模式", + "type": "option", + "value": ["CBC", "CFB", "OFB", "CTR", "ECB", "CBC/NoPadding", "ECB/NoPadding"] + }, + { + "name": "输入", + "type": "option", + "value": ["原始", "十六进制"] + }, + { + "name": "输出", + "type": "option", + "value": ["原始", "十六进制"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const key = Utils.convertToByteArray(args[0].string, args[0].option), + iv = Utils.convertToByteArray(args[1].string, args[1].option), + [,, mode, inputType, outputType] = args; + + if (key.length !== 16) + throw new OperationError(`无效的key长度: ${key.length} 字节 + +SM4使用16字节(128位)长度的key。`); + if (iv.length !== 16 && !mode.startsWith("ECB")) + throw new OperationError(`无效的IV长度: ${iv.length} 字节 + +SM4使用16字节(128位)长度的IV。 +请确认选择了正确的格式 (例如十六进制或UTF8)。`); + + input = Utils.convertToByteArray(input, inputType); + const output = decryptSM4(input, key, iv, mode.substring(0, 3), mode.endsWith("NoPadding")); + return outputType === "十六进制" ? toHex(output) : Utils.byteArrayToUtf8(output); + } + +} + +export default SM4Decrypt; diff --git a/plugins/srktoolbox/src/core/operations/SM4Encrypt.mjs b/plugins/srktoolbox/src/core/operations/SM4Encrypt.mjs new file mode 100644 index 00000000..667d8129 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SM4Encrypt.mjs @@ -0,0 +1,90 @@ +/** + * @author swesven + * @copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { toHex } from "../lib/Hex.mjs"; +import { encryptSM4 } from "../lib/SM4.mjs"; + +/** + * SM4 Encrypt operation + */ +class SM4Encrypt extends Operation { + + /** + * SM4Encrypt constructor + */ + constructor() { + super(); + + this.name = "SM4加密"; + this.module = "Ciphers"; + this.description = "SM4是128位的分组密码,2016年8月,成为中国国家密码标准(GB/T 32907-2016)。支持多种加密模式。当使用CBC或ECB模式时,使用PKCS#7填充。"; + this.infoURL = "https://wikipedia.org/wiki/SM4_(cipher)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Key", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + "name": "IV", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + "name": "模式", + "type": "option", + "value": ["CBC", "CFB", "OFB", "CTR", "ECB"] + }, + { + "name": "输入", + "type": "option", + "value": ["原始", "十六进制"] + }, + { + "name": "输出", + "type": "option", + "value": ["十六进制", "原始"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const key = Utils.convertToByteArray(args[0].string, args[0].option), + iv = Utils.convertToByteArray(args[1].string, args[1].option), + [,, mode, inputType, outputType] = args; + + if (key.length !== 16) + throw new OperationError(`无效的key长度: ${key.length} 字节 + +SM4使用16字节(128位)长度的key。`); + if (iv.length !== 16 && !mode.startsWith("ECB")) + throw new OperationError(`无效的IV长度: ${iv.length} 字节 + +SM4使用16字节(128位)长度的IV。 +请确认选择了正确的格式 (例如十六进制或UTF8)。`); + + input = Utils.convertToByteArray(input, inputType); + const output = encryptSM4(input, key, iv, mode.substring(0, 3), mode.endsWith("NoPadding")); + return outputType === "十六进制" ? toHex(output) : Utils.byteArrayToUtf8(output); + } + +} + +export default SM4Encrypt; diff --git a/plugins/srktoolbox/src/core/operations/SQLBeautify.mjs b/plugins/srktoolbox/src/core/operations/SQLBeautify.mjs new file mode 100644 index 00000000..28ae768c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SQLBeautify.mjs @@ -0,0 +1,49 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import vkbeautify from "vkbeautify"; +import Operation from "../Operation.mjs"; + +/** + * SQL Beautify operation + */ +class SQLBeautify extends Operation { + + /** + * SQLBeautify constructor + */ + constructor() { + super(); + + this.name = "SQL美化"; + this.module = "Code"; + this.description = "为Structured Query Language (SQL)代码添加缩进与美化。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "缩进", + "type": "binaryShortString", + "value": "\\t" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const indentStr = args[0]; + return vkbeautify.sql(input, indentStr); + } + +} + +export default SQLBeautify; diff --git a/plugins/srktoolbox/src/core/operations/SQLMinify.mjs b/plugins/srktoolbox/src/core/operations/SQLMinify.mjs new file mode 100644 index 00000000..c7a58e7f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SQLMinify.mjs @@ -0,0 +1,42 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import vkbeautify from "vkbeautify"; +import Operation from "../Operation.mjs"; + +/** + * SQL Minify operation + */ +class SQLMinify extends Operation { + + /** + * SQLMinify constructor + */ + constructor() { + super(); + + this.name = "SQL压缩"; + this.module = "Code"; + this.description = "压缩Structured Query Language (SQL)代码(Minify/Uglify)。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return vkbeautify.sqlmin(input); + } + +} + +export default SQLMinify; diff --git a/plugins/srktoolbox/src/core/operations/SSDEEP.mjs b/plugins/srktoolbox/src/core/operations/SSDEEP.mjs new file mode 100644 index 00000000..88d9852e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SSDEEP.mjs @@ -0,0 +1,43 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import ssdeepjs from "ssdeep.js"; + +/** + * SSDEEP operation + */ +class SSDEEP extends Operation { + + /** + * SSDEEP constructor + */ + constructor() { + super(); + + this.name = "SSDEEP"; + this.module = "Crypto"; + this.description = "SSDEEP是用于计算基于内容分割的分片哈希(Context Triggered Piecewise Hash, CTPH)的程序。CTPH也被叫做模糊哈希,可以用来检测数据同源性。例如几段具有相同内容片段的数据,相同片段间的其它内容和长度不同,但CTPH的计算结果相近。

SSDEEP哈希现在广泛用于简单的辨识目的(例如VirusTotal的“Basic Properties”)。尽管有“更好”的模糊哈希算法,SSDEEP依然是日常使用首选,得益于它的运算速度,以及它已经成为一个事实标准。

此操作本质上与下面的CTPH操作是相同的,只是输出格式不同。"; + this.infoURL = "https://forensics.wiki/ssdeep"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return ssdeepjs.digest(input); + } + +} + +export default SSDEEP; diff --git a/plugins/srktoolbox/src/core/operations/SUB.mjs b/plugins/srktoolbox/src/core/operations/SUB.mjs new file mode 100644 index 00000000..8d4369fc --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SUB.mjs @@ -0,0 +1,79 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import { bitOp, sub, BITWISE_OP_DELIMS } from "../lib/BitwiseOp.mjs"; + +/** + * SUB operation + */ +class SUB extends Operation { + + /** + * SUB constructor + */ + constructor() { + super(); + + this.name = "SUB"; + this.module = "Default"; + this.description = "使用给定的Key对输入进行SUB(按位减)操作。(e.g. fe023da5), MOD 255"; + this.infoURL = "https://wikipedia.org/wiki/Bitwise_operation#Bitwise_operators"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "Key", + "type": "toggleString", + "value": "", + "toggleValues": BITWISE_OP_DELIMS + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const key = Utils.convertToByteArray(args[0].string || "", args[0].option); + + return bitOp(input, key, sub); + } + + /** + * Highlight SUB + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight SUB in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default SUB; diff --git a/plugins/srktoolbox/src/core/operations/Salsa20.mjs b/plugins/srktoolbox/src/core/operations/Salsa20.mjs new file mode 100644 index 00000000..3f43fef9 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Salsa20.mjs @@ -0,0 +1,156 @@ +/** + * @author joostrijneveld [joost@joostrijneveld.nl] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { toHex } from "../lib/Hex.mjs"; +import { salsa20Block } from "../lib/Salsa20.mjs"; + +/** + * Salsa20 operation + */ +class Salsa20 extends Operation { + + /** + * Salsa20 constructor + */ + constructor() { + super(); + + this.name = "Salsa20"; + this.module = "Ciphers"; + this.description = "Salsa20是一种流加密算法,由丹尼尔·J·伯恩斯坦提交到eSTREAM。Salsa20/8和Salsa20/12是加密轮数减少的版本。Salsa20和ChaCha流加密算法有着紧密联系。

密钥: Salsa20使用16或32字节(128或256位)长度的密钥。

Nonce: Salsa20使用8字节(64位)长度的nonce。

计数: Salsa使用8字节(64位)长度的计数。计数在流的起始处为0,每64字节递增。"; + this.infoURL = "https://wikipedia.org/wiki/Salsa20"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "密钥", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + "name": "Nonce", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64", "整数"] + }, + { + "name": "计数", + "type": "number", + "value": 0, + "min": 0 + }, + { + "name": "轮数", + "type": "option", + "value": ["20", "12", "8"] + }, + { + "name": "输入", + "type": "option", + "value": ["十六进制", "原始"] + }, + { + "name": "输出", + "type": "option", + "value": ["原始", "十六进制"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const key = Utils.convertToByteArray(args[0].string, args[0].option), + nonceType = args[1].option, + rounds = parseInt(args[3], 10), + inputType = args[4], + outputType = args[5]; + + if (key.length !== 16 && key.length !== 32) { + throw new OperationError(`无效的密钥长度: ${key.length} 字节。 + +Salsa20使用16或32字节(128或256位)的密钥。`); + } + + let counter, nonce; + if (nonceType === "整数") { + nonce = Utils.intToByteArray(parseInt(args[1].string, 10), 8, "little"); + } else { + nonce = Utils.convertToByteArray(args[1].string, args[1].option); + if (!(nonce.length === 8)) { + throw new OperationError(`无效的nonce长度: ${nonce.length} 字节。 + +Salsa20使用8字节(64位)的nonce。`); + } + } + counter = Utils.intToByteArray(args[2], 8, "little"); + + const output = []; + input = Utils.convertToByteArray(input, inputType); + + let counterAsInt = Utils.byteArrayToInt(counter, "little"); + for (let i = 0; i < input.length; i += 64) { + counter = Utils.intToByteArray(counterAsInt, 8, "little"); + const stream = salsa20Block(key, nonce, counter, rounds); + for (let j = 0; j < 64 && i + j < input.length; j++) { + output.push(input[i + j] ^ stream[j]); + } + counterAsInt++; + } + + if (outputType === "十六进制") { + return toHex(output); + } else { + return Utils.arrayBufferToStr(Uint8Array.from(output).buffer); + } + } + + /** + * Highlight Salsa20 + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + const inputType = args[4], + outputType = args[5]; + if (inputType === "原始" && outputType === "原始") { + return pos; + } + } + + /** + * Highlight Salsa20 in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + const inputType = args[4], + outputType = args[5]; + if (inputType === "原始" && outputType === "原始") { + return pos; + } + } + +} + +export default Salsa20; diff --git a/plugins/srktoolbox/src/core/operations/ScanForEmbeddedFiles.mjs b/plugins/srktoolbox/src/core/operations/ScanForEmbeddedFiles.mjs new file mode 100644 index 00000000..c2bee4f9 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ScanForEmbeddedFiles.mjs @@ -0,0 +1,80 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import { scanForFileTypes } from "../lib/FileType.mjs"; +import { FILE_SIGNATURES } from "../lib/FileSignatures.mjs"; + +/** + * Scan for Embedded Files operation + */ +class ScanForEmbeddedFiles extends Operation { + + /** + * ScanForEmbeddedFiles constructor + */ + constructor() { + super(); + + this.name = "扫描嵌入文件"; + this.module = "Default"; + this.description = "在输入内容中检测魔术字节(Magic bytes)来扫描潜在的嵌入文件。此操作容易误报。

警告:超过100KB的文件可能会需要非常长的时间处理。"; + this.infoURL = "https://wikipedia.org/wiki/List_of_file_signatures"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = Object.keys(FILE_SIGNATURES).map(cat => { + return { + name: cat, + type: "boolean", + value: cat === "Miscellaneous" ? false : true + }; + }); + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let output = "在输入内容中检测魔术字节(Magic bytes)来扫描潜在的嵌入文件。以下内容可能为误报,因为足够长的数据通常都会碰巧具有这些魔术字节。\n", + numFound = 0; + const categories = [], + data = new Uint8Array(input); + + args.forEach((cat, i) => { + if (cat) categories.push(Object.keys(FILE_SIGNATURES)[i]); + }); + + const types = scanForFileTypes(data, categories); + + if (types.length) { + types.forEach(type => { + numFound++; + output += `\n偏移量 ${type.offset} (0x${Utils.hex(type.offset)}): + 文件类型: ${type.fileDetails.name} + 扩展名: ${type.fileDetails.extension} + MIME类型: ${type.fileDetails.mime}\n`; + + if (type?.fileDetails?.description?.length) { + output += ` 描述: ${type.fileDetails.description}\n`; + } + }); + } + + if (numFound === 0) { + output += "\n未找到嵌入的文件。"; + } + + return output; + } + +} + +export default ScanForEmbeddedFiles; diff --git a/plugins/srktoolbox/src/core/operations/ScatterChart.mjs b/plugins/srktoolbox/src/core/operations/ScatterChart.mjs new file mode 100644 index 00000000..4c3205c8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ScatterChart.mjs @@ -0,0 +1,201 @@ +/** + * @author tlwr [toby@toby.codes] + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import * as d3temp from "d3"; +import * as nodomtemp from "nodom"; +import { getScatterValues, getScatterValuesWithColour, RECORD_DELIMITER_OPTIONS, COLOURS, FIELD_DELIMITER_OPTIONS } from "../lib/Charts.mjs"; + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +const d3 = d3temp.default ? d3temp.default : d3temp; +const nodom = nodomtemp.default ? nodomtemp.default: nodomtemp; + +/** + * Scatter chart operation + */ +class ScatterChart extends Operation { + + /** + * ScatterChart constructor + */ + constructor() { + super(); + + this.name = "散点图"; + this.module = "Charts"; + this.description = "将横纵坐标数据绘制为图表上的点。"; + this.infoURL = "https://wikipedia.org/wiki/Scatter_plot"; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + name: "记录分隔符", + type: "option", + value: RECORD_DELIMITER_OPTIONS, + }, + { + name: "字段分隔符", + type: "option", + value: FIELD_DELIMITER_OPTIONS, + }, + { + name: "使用表头作为标签", + type: "boolean", + value: true, + }, + { + name: "X轴标签", + type: "string", + value: "", + }, + { + name: "Y轴标签", + type: "string", + value: "", + }, + { + name: "颜色", + type: "string", + value: COLOURS.max, + }, + { + name: "点半径", + type: "number", + value: 10, + }, + { + name: "使用第三列的颜色", + type: "boolean", + value: false, + } + ]; + } + + /** + * Scatter chart operation. + * + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const recordDelimiter = Utils.charRep(args[0]), + fieldDelimiter = Utils.charRep(args[1]), + columnHeadingsAreIncluded = args[2], + fillColour = Utils.escapeHtml(args[5]), + radius = args[6], + colourInInput = args[7], + dimension = 500; + + let xLabel = args[3], + yLabel = args[4]; + + const dataFunction = colourInInput ? getScatterValuesWithColour : getScatterValues; + const { headings, values } = dataFunction( + input, + recordDelimiter, + fieldDelimiter, + columnHeadingsAreIncluded + ); + + if (headings) { + xLabel = headings.x; + yLabel = headings.y; + } + + const document = new nodom.Document(); + let svg = document.createElement("svg"); + svg = d3.select(svg) + .attr("width", "100%") + .attr("height", "100%") + .attr("viewBox", `0 0 ${dimension} ${dimension}`); + + const margin = { + top: 10, + right: 0, + bottom: 40, + left: 30, + }, + width = dimension - margin.left - margin.right, + height = dimension - margin.top - margin.bottom, + marginedSpace = svg.append("g") + .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); + + const xExtent = d3.extent(values, d => d[0]), + xDelta = xExtent[1] - xExtent[0], + yExtent = d3.extent(values, d => d[1]), + yDelta = yExtent[1] - yExtent[0], + xAxis = d3.scaleLinear() + .domain([xExtent[0] - (0.1 * xDelta), xExtent[1] + (0.1 * xDelta)]) + .range([0, width]), + yAxis = d3.scaleLinear() + .domain([yExtent[0] - (0.1 * yDelta), yExtent[1] + (0.1 * yDelta)]) + .range([height, 0]); + + marginedSpace.append("clipPath") + .attr("id", "clip") + .append("rect") + .attr("width", width) + .attr("height", height); + + marginedSpace.append("g") + .attr("class", "points") + .attr("clip-path", "url(#clip)") + .selectAll("circle") + .data(values) + .enter() + .append("circle") + .attr("cx", (d) => xAxis(d[0])) + .attr("cy", (d) => yAxis(d[1])) + .attr("r", d => radius) + .attr("fill", d => { + return colourInInput ? d[2] : fillColour; + }) + .attr("stroke", "rgba(0, 0, 0, 0.5)") + .attr("stroke-width", "0.5") + .append("title") + .text(d => { + const x = d[0], + y = d[1], + tooltip = `X: ${x}\n + Y: ${y}\n + `.replace(/\s{2,}/g, "\n"); + return tooltip; + }); + + marginedSpace.append("g") + .attr("class", "axis axis--y") + .call(d3.axisLeft(yAxis).tickSizeOuter(-width)); + + svg.append("text") + .attr("transform", "rotate(-90)") + .attr("y", -margin.left) + .attr("x", -(height / 2)) + .attr("dy", "1em") + .style("text-anchor", "middle") + .text(yLabel); + + marginedSpace.append("g") + .attr("class", "axis axis--x") + .attr("transform", "translate(0," + height + ")") + .call(d3.axisBottom(xAxis).tickSizeOuter(-height)); + + svg.append("text") + .attr("x", width / 2) + .attr("y", dimension) + .style("text-anchor", "middle") + .text(xLabel); + + return svg._groups[0][0].outerHTML; + } + +} + +export default ScatterChart; diff --git a/plugins/srktoolbox/src/core/operations/Scrypt.mjs b/plugins/srktoolbox/src/core/operations/Scrypt.mjs new file mode 100644 index 00000000..4ad07926 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Scrypt.mjs @@ -0,0 +1,92 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import scryptsy from "scryptsy"; +import { isWorkerEnvironment } from "../Utils.mjs"; + +/** + * Scrypt operation + */ +class Scrypt extends Operation { + + /** + * Scrypt constructor + */ + constructor() { + super(); + + this.name = "Scrypt"; + this.module = "Crypto"; + this.description = "scrypt(念作“ess crypt”),是加拿大计算机科学家暨计算机安全研究人员科林·珀西瓦尔(Colin Percival)于2009年所发明的密钥派生函数,当初设计用在他所创立的Tarsnap服务上。设计时考虑到大规模的客制硬件攻击而刻意设计需要大量内存运算。2016年,scrypt算法发布在RFC 7914。

在输入区输入口令来生成对应的哈希值。"; + this.infoURL = "https://wikipedia.org/wiki/Scrypt"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "盐", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "Base64", "UTF8", "Latin1"] + }, + { + "name": "迭代次数(N)", + "type": "number", + "value": 16384 + }, + { + "name": "内存因子(r)", + "type": "number", + "value": 8 + }, + { + "name": "并行因子(p)", + "type": "number", + "value": 1 + }, + { + "name": "Key长度", + "type": "number", + "value": 64 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const salt = Buffer.from(Utils.convertToByteArray(args[0].string || "", args[0].option)), + iterations = args[1], + memFactor = args[2], + parallelFactor = args[3], + keyLength = args[4]; + + try { + const data = scryptsy( + input, salt, iterations, memFactor, parallelFactor, keyLength, + p => { + // Progress callback + if (isWorkerEnvironment()) + self.sendStatusMessage(`进度: ${p.percent.toFixed(0)}%`); + } + ); + + return data.toString("hex"); + } catch (err) { + throw new OperationError("错误: " + err.toString()); + } + } + +} + +export default Scrypt; diff --git a/plugins/srktoolbox/src/core/operations/SeriesChart.mjs b/plugins/srktoolbox/src/core/operations/SeriesChart.mjs new file mode 100644 index 00000000..a0adb4e4 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SeriesChart.mjs @@ -0,0 +1,232 @@ +/** + * @author tlwr [toby@toby.codes] + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import * as d3temp from "d3"; +import * as nodomtemp from "nodom"; +import { getSeriesValues, RECORD_DELIMITER_OPTIONS, FIELD_DELIMITER_OPTIONS } from "../lib/Charts.mjs"; + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +const d3 = d3temp.default ? d3temp.default : d3temp; +const nodom = nodomtemp.default ? nodomtemp.default: nodomtemp; + +/** + * Series chart operation + */ +class SeriesChart extends Operation { + + /** + * SeriesChart constructor + */ + constructor() { + super(); + + this.name = "折线图"; + this.module = "Charts"; + this.description = "时分系列图(Time series graph)是折线图的一种,用于表示在给定时间范围内的不同测量值。"; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + name: "记录分隔符", + type: "option", + value: RECORD_DELIMITER_OPTIONS, + }, + { + name: "字段分隔符", + type: "option", + value: FIELD_DELIMITER_OPTIONS, + }, + { + name: "X轴标签", + type: "string", + value: "", + }, + { + name: "点半径", + type: "number", + value: 1, + }, + { + name: "数据系列颜色", + type: "string", + value: "mediumseagreen, dodgerblue, tomato", + }, + ]; + } + + /** + * Series chart operation. + * + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const recordDelimiter = Utils.charRep(args[0]), + fieldDelimiter = Utils.charRep(args[1]), + xLabel = args[2], + pipRadius = args[3], + // Escape HTML from all colours to prevent reflected XSS. See https://github.com/gchq/CyberChef/issues/1265 + seriesColours = args[4].split(",").map((colour) => { + return Utils.escapeHtml(colour); + }), + svgWidth = 500, + interSeriesPadding = 20, + xAxisHeight = 50, + seriesLabelWidth = 50, + seriesHeight = 100, + seriesWidth = svgWidth - seriesLabelWidth - interSeriesPadding; + + const { xValues, series } = getSeriesValues(input, recordDelimiter, fieldDelimiter), + allSeriesHeight = Object.keys(series).length * (interSeriesPadding + seriesHeight), + svgHeight = allSeriesHeight + xAxisHeight + interSeriesPadding; + + const document = new nodom.Document(); + let svg = document.createElement("svg"); + svg = d3.select(svg) + .attr("width", "100%") + .attr("height", "100%") + .attr("viewBox", `0 0 ${svgWidth} ${svgHeight}`); + + const xAxis = d3.scalePoint() + .domain(xValues) + .range([0, seriesWidth]); + + svg.append("g") + .attr("class", "axis axis--x") + .attr("transform", `translate(${seriesLabelWidth}, ${xAxisHeight})`) + .call( + d3.axisTop(xAxis).tickValues(xValues.filter((x, i) => { + return [0, Math.round(xValues.length / 2), xValues.length -1].indexOf(i) >= 0; + })) + ); + + svg.append("text") + .attr("x", svgWidth / 2) + .attr("y", xAxisHeight / 2) + .style("text-anchor", "middle") + .text(xLabel); + + const tooltipText = {}, + tooltipAreaWidth = seriesWidth / xValues.length; + + xValues.forEach(x => { + const tooltip = []; + + series.forEach(serie => { + const y = serie.data[x]; + if (typeof y === "undefined") return; + + tooltip.push(`${serie.name}: ${y}`); + }); + + tooltipText[x] = tooltip.join("\n"); + }); + + const chartArea = svg.append("g") + .attr("transform", `translate(${seriesLabelWidth}, ${xAxisHeight})`); + + chartArea + .append("g") + .selectAll("rect") + .data(xValues) + .enter() + .append("rect") + .attr("x", x => { + return xAxis(x) - (tooltipAreaWidth / 2); + }) + .attr("y", 0) + .attr("width", tooltipAreaWidth) + .attr("height", allSeriesHeight) + .attr("stroke", "none") + .attr("fill", "transparent") + .append("title") + .text(x => { + return `${x}\n + --\n + ${tooltipText[x]}\n + `.replace(/\s{2,}/g, "\n"); + }); + + const yAxesArea = svg.append("g") + .attr("transform", `translate(0, ${xAxisHeight})`); + + series.forEach((serie, seriesIndex) => { + const yExtent = d3.extent(Object.values(serie.data)), + yAxis = d3.scaleLinear() + .domain(yExtent) + .range([seriesHeight, 0]); + + const seriesGroup = chartArea + .append("g") + .attr("transform", `translate(0, ${seriesHeight * seriesIndex + interSeriesPadding * (seriesIndex + 1)})`); + + let path = ""; + xValues.forEach((x, xIndex) => { + let nextX = xValues[xIndex + 1], + y = serie.data[x], + nextY= serie.data[nextX]; + + if (typeof y === "undefined" || typeof nextY === "undefined") return; + + x = xAxis(x); nextX = xAxis(nextX); + y = yAxis(y); nextY = yAxis(nextY); + + path += `M ${x} ${y} L ${nextX} ${nextY} z `; + }); + + seriesGroup + .append("path") + .attr("d", path) + .attr("fill", "none") + .attr("stroke", seriesColours[seriesIndex % seriesColours.length]) + .attr("stroke-width", "1"); + + xValues.forEach(x => { + const y = serie.data[x]; + if (typeof y === "undefined") return; + + seriesGroup + .append("circle") + .attr("cx", xAxis(x)) + .attr("cy", yAxis(y)) + .attr("r", pipRadius) + .attr("fill", seriesColours[seriesIndex % seriesColours.length]) + .append("title") + .text(d => { + return `${x}\n + --\n + ${tooltipText[x]}\n + `.replace(/\s{2,}/g, "\n"); + }); + }); + + yAxesArea + .append("g") + .attr("transform", `translate(${seriesLabelWidth - interSeriesPadding}, ${seriesHeight * seriesIndex + interSeriesPadding * (seriesIndex + 1)})`) + .attr("class", "axis axis--y") + .call(d3.axisLeft(yAxis).ticks(5)); + + yAxesArea + .append("g") + .attr("transform", `translate(0, ${seriesHeight / 2 + seriesHeight * seriesIndex + interSeriesPadding * (seriesIndex + 1)})`) + .append("text") + .style("text-anchor", "middle") + .attr("transform", "rotate(-90)") + .text(serie.name); + }); + + return svg._groups[0][0].outerHTML; + } + +} + +export default SeriesChart; diff --git a/plugins/srktoolbox/src/core/operations/SetDifference.mjs b/plugins/srktoolbox/src/core/operations/SetDifference.mjs new file mode 100644 index 00000000..505b6179 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SetDifference.mjs @@ -0,0 +1,89 @@ +/** + * @author d98762625 [d98762625@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Set Difference operation + */ +class SetDifference extends Operation { + + /** + * Set Difference constructor + */ + constructor() { + super(); + + this.name = "补集"; + this.module = "Default"; + this.description = "计算集合的补集(相对差集)。"; + this.infoURL = "https://wikipedia.org/wiki/Complement_(set_theory)#Relative_complement"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "集合分隔符", + type: "binaryString", + value: "\\n\\n" + }, + { + name: "元素分隔符", + type: "binaryString", + value: "," + }, + ]; + } + + /** + * Validate input length + * + * @param {Object[]} sets + * @throws {Error} if not two sets + */ + validateSampleNumbers(sets) { + if (!sets || (sets.length !== 2)) { + throw new OperationError("集合数量错误,你可能需要调整集合分隔符或者添加一些数据。"); + } + } + + /** + * Run the difference operation + * + * @param {string} input + * @param {Object[]} args + * @returns {string} + * @throws {OperationError} + */ + run(input, args) { + [this.sampleDelim, this.itemDelimiter] = args; + const sets = input.split(this.sampleDelim); + + this.validateSampleNumbers(sets); + + return this.runSetDifference(...sets.map(s => s.split(this.itemDelimiter))); + } + + /** + * Get elements in set a that are not in set b + * + * @param {Object[]} a + * @param {Object[]} b + * @returns {Object[]} + */ + runSetDifference(a, b) { + return a + .filter((item) => { + return b.indexOf(item) === -1; + }) + .join(this.itemDelimiter); + } + +} + +export default SetDifference; diff --git a/plugins/srktoolbox/src/core/operations/SetIntersection.mjs b/plugins/srktoolbox/src/core/operations/SetIntersection.mjs new file mode 100644 index 00000000..ca108d81 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SetIntersection.mjs @@ -0,0 +1,89 @@ +/** + * @author d98762625 [d98762625@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Set Intersection operation + */ +class SetIntersection extends Operation { + + /** + * Set Intersection constructor + */ + constructor() { + super(); + + this.name = "交集"; + this.module = "Default"; + this.description = "计算两个集合的交集。"; + this.infoURL = "https://wikipedia.org/wiki/Intersection_(set_theory)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "集合分隔符", + type: "binaryString", + value: "\\n\\n" + }, + { + name: "元素分隔符", + type: "binaryString", + value: "," + }, + ]; + } + + /** + * Validate input length + * + * @param {Object[]} sets + * @throws {Error} if not two sets + */ + validateSampleNumbers(sets) { + if (!sets || (sets.length !== 2)) { + throw new OperationError("集合数量错误,你可能需要调整集合分隔符或者添加一些数据。"); + } + } + + /** + * Run the intersection operation + * + * @param {string} input + * @param {Object[]} args + * @returns {string} + * @throws {OperationError} + */ + run(input, args) { + [this.sampleDelim, this.itemDelimiter] = args; + const sets = input.split(this.sampleDelim); + + this.validateSampleNumbers(sets); + + return this.runIntersect(...sets.map(s => s.split(this.itemDelimiter))); + } + + /** + * Get the intersection of the two sets. + * + * @param {Object[]} a + * @param {Object[]} b + * @returns {Object[]} + */ + runIntersect(a, b) { + return a + .filter((item) => { + return b.indexOf(item) > -1; + }) + .join(this.itemDelimiter); + } + +} + +export default SetIntersection; diff --git a/plugins/srktoolbox/src/core/operations/SetUnion.mjs b/plugins/srktoolbox/src/core/operations/SetUnion.mjs new file mode 100644 index 00000000..feb8cae0 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SetUnion.mjs @@ -0,0 +1,99 @@ +/** + * @author d98762625 [d98762625@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Set Union operation + */ +class SetUnion extends Operation { + + /** + * Set Union constructor + */ + constructor() { + super(); + + this.name = "并集"; + this.module = "Default"; + this.description = "计算两个集合的并集。"; + this.infoURL = "https://wikipedia.org/wiki/Union_(set_theory)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "集合分隔符", + type: "binaryString", + value: "\\n\\n" + }, + { + name: "元素分隔符", + type: "binaryString", + value: "," + }, + ]; + } + + /** + * Validate input length + * + * @param {Object[]} sets + * @throws {Error} if not two sets + */ + validateSampleNumbers(sets) { + if (!sets || (sets.length !== 2)) { + throw new OperationError("集合数量错误,你可能需要调整集合分隔符或者添加一些数据。"); + } + } + + /** + * Run the union operation + * + * @param {string} input + * @param {Object[]} args + * @returns {string} + * @throws {OperationError} + */ + run(input, args) { + [this.sampleDelim, this.itemDelimiter] = args; + const sets = input.split(this.sampleDelim); + + this.validateSampleNumbers(sets); + + return this.runUnion(...sets.map(s => s.split(this.itemDelimiter))); + } + + /** + * Get the union of the two sets. + * + * @param {Object[]} a + * @param {Object[]} b + * @returns {Object[]} + */ + runUnion(a, b) { + const result = {}; + + /** + * Only add non-existing items + * @param {Object} hash + */ + const addUnique = (hash) => (item) => { + if (!hash[item]) { + hash[item] = true; + } + }; + + a.map(addUnique(result)); + b.map(addUnique(result)); + + return Object.keys(result).join(this.itemDelimiter); + } +} + +export default SetUnion; diff --git a/plugins/srktoolbox/src/core/operations/Shake.mjs b/plugins/srktoolbox/src/core/operations/Shake.mjs new file mode 100644 index 00000000..31d4529d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Shake.mjs @@ -0,0 +1,73 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import JSSHA3 from "js-sha3"; + +/** + * Shake operation + */ +class Shake extends Operation { + + /** + * Shake constructor + */ + constructor() { + super(); + + this.name = "Shake"; + this.module = "Crypto"; + this.description = "Shake是SHA-3算法的一个可扩展输出函数(Extendable Output Function, XOF),Keccak系列算法之一,允许可变的输出长度。"; + this.infoURL = "https://wikipedia.org/wiki/SHA-3#Instances"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "容量(Capacity)", + "type": "option", + "value": ["256", "128"] + }, + { + "name": "长度", + "type": "number", + "value": 512 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const capacity = parseInt(args[0], 10), + size = args[1]; + let algo; + + if (size < 0) + throw new OperationError("长度必须大于0"); + + switch (capacity) { + case 128: + algo = JSSHA3.shake128; + break; + case 256: + algo = JSSHA3.shake256; + break; + default: + throw new OperationError("无效长度"); + } + + return algo(input, size); + } + +} + +export default Shake; diff --git a/plugins/srktoolbox/src/core/operations/SharpenImage.mjs b/plugins/srktoolbox/src/core/operations/SharpenImage.mjs new file mode 100644 index 00000000..57cce59e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SharpenImage.mjs @@ -0,0 +1,203 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; +import { Jimp, JimpMime } from "jimp"; + +/** + * Sharpen Image operation + */ +class SharpenImage extends Operation { + /** + * SharpenImage constructor + */ + constructor() { + super(); + + this.name = "锐化图像"; + this.module = "Image"; + this.description = "锐化图像(钝化蒙版,USM)。"; + this.infoURL = "https://wikipedia.org/wiki/Unsharp_masking"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = [ + { + name: "半径", + type: "number", + value: 2, + min: 1, + }, + { + name: "强度", + type: "number", + value: 1, + min: 0, + step: 0.1, + }, + { + name: "阈值", + type: "number", + value: 10, + min: 0, + max: 100, + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + async run(input, args) { + const [radius, amount, threshold] = args; + + if (!isImage(input)) { + throw new OperationError("无效的文件类型。"); + } + + let image; + try { + image = await Jimp.read(input); + } catch (err) { + throw new OperationError(`载入图像出错:(${err})`); + } + + try { + if (isWorkerEnvironment()) + self.sendStatusMessage("锐化图像……(复制图像)"); + const blurMask = image.clone(); + + if (isWorkerEnvironment()) + self.sendStatusMessage( + "锐化图像……(模糊图像)", + ); + const blurImage = image.clone().gaussian(radius); + + if (isWorkerEnvironment()) + self.sendStatusMessage( + "锐化图像……(生成钝化蒙版)", + ); + blurMask.scan( + 0, + 0, + blurMask.bitmap.width, + blurMask.bitmap.height, + function (x, y, idx) { + const blurRed = blurImage.bitmap.data[idx]; + const blurGreen = blurImage.bitmap.data[idx + 1]; + const blurBlue = blurImage.bitmap.data[idx + 2]; + + const normalRed = this.bitmap.data[idx]; + const normalGreen = this.bitmap.data[idx + 1]; + const normalBlue = this.bitmap.data[idx + 2]; + + // Subtract blurred pixel value from normal image + this.bitmap.data[idx] = + normalRed > blurRed ? normalRed - blurRed : 0; + this.bitmap.data[idx + 1] = + normalGreen > blurGreen ? normalGreen - blurGreen : 0; + this.bitmap.data[idx + 2] = + normalBlue > blurBlue ? normalBlue - blurBlue : 0; + }, + ); + + if (isWorkerEnvironment()) + self.sendStatusMessage( + "锐化图像……(蒙版合并)", + ); + image.scan( + 0, + 0, + image.bitmap.width, + image.bitmap.height, + function (x, y, idx) { + let maskRed = blurMask.bitmap.data[idx]; + let maskGreen = blurMask.bitmap.data[idx + 1]; + let maskBlue = blurMask.bitmap.data[idx + 2]; + + const normalRed = this.bitmap.data[idx]; + const normalGreen = this.bitmap.data[idx + 1]; + const normalBlue = this.bitmap.data[idx + 2]; + + // Calculate luminance + const maskLuminance = + 0.2126 * maskRed + + 0.7152 * maskGreen + + 0.0722 * maskBlue; + const normalLuminance = + 0.2126 * normalRed + + 0.7152 * normalGreen + + 0.0722 * normalBlue; + + let luminanceDiff; + if (maskLuminance > normalLuminance) { + luminanceDiff = maskLuminance - normalLuminance; + } else { + luminanceDiff = normalLuminance - maskLuminance; + } + + // Scale mask colours by amount + maskRed = maskRed * amount; + maskGreen = maskGreen * amount; + maskBlue = maskBlue * amount; + + // Only change pixel value if the difference is higher than threshold + if ((luminanceDiff / 255) * 100 >= threshold) { + this.bitmap.data[idx] = + normalRed + maskRed <= 255 ? + normalRed + maskRed : + 255; + this.bitmap.data[idx + 1] = + normalGreen + maskGreen <= 255 ? + normalGreen + maskGreen : + 255; + this.bitmap.data[idx + 2] = + normalBlue + maskBlue <= 255 ? + normalBlue + maskBlue : + 255; + } + }, + ); + + let imageBuffer; + if (image.mime === "image/gif") { + imageBuffer = await image.getBuffer(JimpMime.png); + } else { + imageBuffer = await image.getBuffer(image.mime); + } + return imageBuffer.buffer; + } catch (err) { + throw new OperationError(`锐化图像出错:(${err})`); + } + } + + /** + * Displays the sharpened image using HTML for web apps + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const dataArray = new Uint8Array(data); + + const type = isImage(dataArray); + if (!type) { + throw new OperationError("无效的文件类型。"); + } + + return ``; + } +} + +export default SharpenImage; diff --git a/plugins/srktoolbox/src/core/operations/ShowBase64Offsets.mjs b/plugins/srktoolbox/src/core/operations/ShowBase64Offsets.mjs new file mode 100644 index 00000000..1bb72d8f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ShowBase64Offsets.mjs @@ -0,0 +1,175 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {fromBase64, toBase64} from "../lib/Base64.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Show Base64 offsets operation + */ +class ShowBase64Offsets extends Operation { + + /** + * ShowBase64Offsets constructor + */ + constructor() { + super(); + + this.name = "显示Base64偏移形式"; + this.module = "Default"; + this.description = "当一个字符串被包含在其他数据中间一起被Base64编码的时候,根据字符串所在的位置,可能有三种不同的编码结果。

此操作会显示三种不同结果,用于后期匹配。"; + this.infoURL = "https://wikipedia.org/wiki/Base64#Output_padding"; + this.inputType = "byteArray"; + this.outputType = "html"; + this.args = [ + { + name: "可用字符", + type: "binaryString", + value: "A-Za-z0-9+/=" + }, + { + name: "显示可变字符与填充位", + type: "boolean", + value: true + }, + { + name: "输入格式", + type: "option", + value: ["原始字符串", "Base64"] + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const [alphabet, showVariable, format] = args; + + if (format === "Base64") { + input = fromBase64(Utils.byteArrayToUtf8(input), null, "byteArray"); + } + + let offset0 = toBase64(input, alphabet), + offset1 = toBase64([0].concat(input), alphabet), + offset2 = toBase64([0, 0].concat(input), alphabet), + staticSection = "", + padding = ""; + + const len0 = offset0.indexOf("="), + len1 = offset1.indexOf("="), + len2 = offset2.indexOf("="), + script = ""; + + if (input.length < 1) { + throw new OperationError("请输入字符串"); + } + + // Highlight offset 0 + if (len0 % 4 === 2) { + staticSection = offset0.slice(0, -3); + offset0 = "" + + staticSection + "" + + "" + offset0.substr(offset0.length - 3, 1) + "" + + "" + offset0.substr(offset0.length - 2) + ""; + } else if (len0 % 4 === 3) { + staticSection = offset0.slice(0, -2); + offset0 = "" + + staticSection + "" + + "" + offset0.substr(offset0.length - 2, 1) + "" + + "" + offset0.substr(offset0.length - 1) + ""; + } else { + staticSection = offset0; + offset0 = "" + + staticSection + ""; + } + + if (!showVariable) { + offset0 = staticSection; + } + + + // Highlight offset 1 + padding = "" + offset1.substr(0, 1) + "" + + "" + offset1.substr(1, 1) + ""; + offset1 = offset1.substr(2); + if (len1 % 4 === 2) { + staticSection = offset1.slice(0, -3); + offset1 = padding + "" + + staticSection + "" + + "" + offset1.substr(offset1.length - 3, 1) + "" + + "" + offset1.substr(offset1.length - 2) + ""; + } else if (len1 % 4 === 3) { + staticSection = offset1.slice(0, -2); + offset1 = padding + "" + + staticSection + "" + + "" + offset1.substr(offset1.length - 2, 1) + "" + + "" + offset1.substr(offset1.length - 1) + ""; + } else { + staticSection = offset1; + offset1 = padding + "" + + staticSection + ""; + } + + if (!showVariable) { + offset1 = staticSection; + } + + // Highlight offset 2 + padding = "" + offset2.substr(0, 2) + "" + + "" + offset2.substr(2, 1) + ""; + offset2 = offset2.substr(3); + if (len2 % 4 === 2) { + staticSection = offset2.slice(0, -3); + offset2 = padding + "" + + staticSection + "" + + "" + offset2.substr(offset2.length - 3, 1) + "" + + "" + offset2.substr(offset2.length - 2) + ""; + } else if (len2 % 4 === 3) { + staticSection = offset2.slice(0, -2); + offset2 = padding + "" + + staticSection + "" + + "" + offset2.substr(offset2.length - 2, 1) + "" + + "" + offset2.substr(offset2.length - 1) + ""; + } else { + staticSection = offset2; + offset2 = padding + "" + + staticSection + ""; + } + + if (!showVariable) { + offset2 = staticSection; + } + + return (showVariable ? "绿色字符表示它根据前后数据的不同可能会发生变化。" + + "\n红色字符只是用于填充占位。" + + "\n无背景色的字符表示固定内容。" + + "\n鼠标放到固定内容部分查看此部分会解码成什么内容。\n" + + "\n偏移量0: " + offset0 + + "\n偏移量1: " + offset1 + + "\n偏移量2: " + offset2 + + script : + offset0 + "\n" + offset1 + "\n" + offset2); + } + +} + +export default ShowBase64Offsets; diff --git a/plugins/srktoolbox/src/core/operations/ShowOnMap.mjs b/plugins/srktoolbox/src/core/operations/ShowOnMap.mjs new file mode 100644 index 00000000..294527b3 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ShowOnMap.mjs @@ -0,0 +1,123 @@ +/** + * @author j433866 [j433866@gmail.com] + * @author 0xff1ce [github.com/0xff1ce] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {FORMATS, convertCoordinates} from "../lib/ConvertCoordinates.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Show on map operation + */ +class ShowOnMap extends Operation { + + /** + * ShowOnMap constructor + */ + constructor() { + super(); + + this.name = "在地图上显示"; + this.module = "Hashing"; + this.description = "在网页地图上展示坐标位置

坐标会被转换成度数格式后在地图上显示。

支持的格式:
  • 度分秒 (DMS)
  • 度分 (DDM)
  • 度数 (DD)
  • Geohash
  • 军事格网参考系统 (MGRS)
  • 地形测量局国家格网参考系统 (OSNG)
  • 通用横轴墨卡托投影 (UTM)

此操作无法离线使用。"; + this.infoURL = "https://osmfoundation.org/wiki/Terms_of_Use"; + this.inputType = "string"; + this.outputType = "string"; + this.presentType = "html"; + this.args = [ + { + name: "缩放级别", + type: "number", + value: 13 + }, + { + name: "输入格式", + type: "option", + value: ["自动"].concat(FORMATS) + }, + { + name: "输入分隔符", + type: "option", + value: [ + "自动", + "方向在前", + "方向在后", + "\\n", + "逗号", + "分号", + "冒号" + ] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (input.replace(/\s+/g, "") !== "") { + const inFormat = args[1], + inDelim = args[2]; + let latLong; + try { + latLong = convertCoordinates(input, inFormat, inDelim, "度数", "逗号", "无", 5); + } catch (error) { + throw new OperationError(error); + } + latLong = latLong.replace(/[,]$/, ""); + latLong = latLong.replace(/°/g, ""); + return latLong; + } + return input; + } + + /** + * @param {string} data + * @param {Object[]} args + * @returns {string} + */ + async present(data, args) { + if (data.replace(/\s+/g, "") === "") { + data = "0, 0"; + } + const zoomLevel = args[0]; + const tileUrl = "https://tile.openstreetmap.org/{z}/{x}/{y}.png", + tileAttribution = "© OpenStreetMap contributors", + leafletUrl = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js", + leafletCssUrl = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"; + return ` + +
+`; + } +} + +export default ShowOnMap; diff --git a/plugins/srktoolbox/src/core/operations/Shuffle.mjs b/plugins/srktoolbox/src/core/operations/Shuffle.mjs new file mode 100644 index 00000000..c3596d77 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Shuffle.mjs @@ -0,0 +1,80 @@ +/** + * @author mikecat + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs"; + +/** + * Shuffle operation + */ +class Shuffle extends Operation { + + /** + * Shuffle constructor + */ + constructor() { + super(); + + this.name = "乱序"; + this.module = "Default"; + this.description = "对输入元素随机重排。."; + this.infoURL = "https://wikipedia.org/wiki/Shuffling"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "分隔符", + type: "option", + value: INPUT_DELIM_OPTIONS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0]); + if (input.length === 0) return input; + + // return a random number in [0, 1) + const rng = (typeof crypto) !== "undefined" && crypto.getRandomValues ? (function() { + const buf = new Uint32Array(2); + return function() { + // generate 53-bit random integer: 21 + 32 bits + crypto.getRandomValues(buf); + const value = (buf[0] >>> (32 - 21)) * ((1 << 30) * 4) + buf[1]; + return value / ((1 << 23) * (1 << 30)); + }; + })() : Math.random; + + // return a random integer in [0, max) + const randint = function(max) { + return Math.floor(rng() * max); + }; + + // Split input into shuffleable sections + const toShuffle = input.split(delim); + + // shuffle elements + for (let i = toShuffle.length - 1; i > 0; i--) { + const idx = randint(i + 1); + const tmp = toShuffle[idx]; + toShuffle[idx] = toShuffle[i]; + toShuffle[i] = tmp; + } + + return toShuffle.join(delim); + } + +} + +export default Shuffle; diff --git a/plugins/srktoolbox/src/core/operations/Sleep.mjs b/plugins/srktoolbox/src/core/operations/Sleep.mjs new file mode 100644 index 00000000..aa07cd93 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Sleep.mjs @@ -0,0 +1,49 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Sleep operation + */ +class Sleep extends Operation { + + /** + * Sleep constructor + */ + constructor() { + super(); + + this.name = "Sleep"; + this.module = "Default"; + this.description = "Sleep操作让流程执行时在等待给定的毫秒数后继续。"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + "name": "时长 (ms)", + "type": "number", + "value": 1000 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + async run(input, args) { + const ms = args[0]; + await new Promise(r => setTimeout(r, ms)); + return input; + } + +} + +export default Sleep; diff --git a/plugins/srktoolbox/src/core/operations/Snefru.mjs b/plugins/srktoolbox/src/core/operations/Snefru.mjs new file mode 100644 index 00000000..df9ec510 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Snefru.mjs @@ -0,0 +1,60 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * Snefru operation + */ +class Snefru extends Operation { + + /** + * Snefru constructor + */ + constructor() { + super(); + + this.name = "Snefru"; + this.module = "Crypto"; + this.description = "Snefru是由Ralph Merkle于1990年在Xerox PARC工作时设计的哈希算法。此算法支持128位和256位长度的输出。它的名字来源于埃及法老斯尼夫鲁(Sneferu),和该作者的Khufu和Khafre块加密算法采用了相同的命名方式。

Snefru原始设计的安全漏洞由Eli Biham和Adi Shamir发现,他们使用差分密码分析找到了哈希碰撞。后续该算法通过将计算轮数从2提高到8次来解决此问题。"; + this.infoURL = "https://wikipedia.org/wiki/Snefru"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "长度", + type: "number", + value: 128, + min: 32, + max: 480, + step: 32 + }, + { + name: "轮数", + type: "option", + value: ["8", "4", "2"] + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return runHash("snefru", input, { + length: args[0], + rounds: args[1] + }); + } + +} + +export default Snefru; diff --git a/plugins/srktoolbox/src/core/operations/Sort.mjs b/plugins/srktoolbox/src/core/operations/Sort.mjs new file mode 100644 index 00000000..36ed155c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Sort.mjs @@ -0,0 +1,80 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs"; +import {caseInsensitiveSort, ipSort, numericSort, hexadecimalSort, lengthSort} from "../lib/Sort.mjs"; + +/** + * Sort operation + */ +class Sort extends Operation { + + /** + * Sort constructor + */ + constructor() { + super(); + + this.name = "排序"; + this.module = "Default"; + this.description = "按字母顺序对给定分隔符分隔的字符串进行排序。

IP地址排序仅限IPv4。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": INPUT_DELIM_OPTIONS + }, + { + "name": "反向排序", + "type": "boolean", + "value": false + }, + { + "name": "顺序", + "type": "option", + "value": ["字母顺序(区分大小写)", "字母顺序(不区分大小写)", "IP地址", "数字", "数字(十六进制)", "长度"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0]), + sortReverse = args[1], + order = args[2]; + let sorted = input.split(delim); + + if (order === "字母顺序(区分大小写)") { + sorted = sorted.sort(); + } else if (order === "字母顺序(不区分大小写)") { + sorted = sorted.sort(caseInsensitiveSort); + } else if (order === "IP地址") { + sorted = sorted.sort(ipSort); + } else if (order === "数字") { + sorted = sorted.sort(numericSort); + } else if (order === "数字(十六进制)") { + sorted = sorted.sort(hexadecimalSort); + } else if (order === "长度") { + sorted = sorted.sort(lengthSort); + } + + if (sortReverse) sorted.reverse(); + return sorted.join(delim); + } + +} + +export default Sort; diff --git a/plugins/srktoolbox/src/core/operations/Split.mjs b/plugins/srktoolbox/src/core/operations/Split.mjs new file mode 100644 index 00000000..5c14d888 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Split.mjs @@ -0,0 +1,57 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {SPLIT_DELIM_OPTIONS, JOIN_DELIM_OPTIONS} from "../lib/Delim.mjs"; + +/** + * Split operation + */ +class Split extends Operation { + + /** + * Split constructor + */ + constructor() { + super(); + + this.name = "拆分"; + this.module = "Default"; + this.description = "使用给定的分隔符拆分字符串。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Split delimiter", + "type": "editableOptionShort", + "value": SPLIT_DELIM_OPTIONS + }, + { + "name": "Join delimiter", + "type": "editableOptionShort", + "value": JOIN_DELIM_OPTIONS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const splitDelim = args[0], + joinDelim = args[1], + sections = input.split(splitDelim); + + return sections.join(joinDelim); + } + +} + +export default Split; diff --git a/plugins/srktoolbox/src/core/operations/SplitColourChannels.mjs b/plugins/srktoolbox/src/core/operations/SplitColourChannels.mjs new file mode 100644 index 00000000..7570f474 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SplitColourChannels.mjs @@ -0,0 +1,130 @@ +/** + * @author Matt C [matt@artemisbot.uk] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { Jimp, JimpMime } from "jimp"; + +/** + * Split Colour Channels operation + */ +class SplitColourChannels extends Operation { + /** + * SplitColourChannels constructor + */ + constructor() { + super(); + + this.name = "色彩通道分离"; + this.module = "Image"; + this.description = + "将给定图像分离成红、绿、蓝色通道。"; + this.infoURL = "https://wikipedia.org/wiki/Channel_(digital_image)"; + this.inputType = "ArrayBuffer"; + this.outputType = "List"; + this.presentType = "html"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {List} + */ + async run(input, args) { + input = new Uint8Array(input); + // Make sure that the input is an image + if (!isImage(input)) throw new OperationError("无效的文件类型。"); + + const parsedImage = await Jimp.read(Buffer.from(input)); + + const red = new Promise(async (resolve, reject) => { + try { + const split = parsedImage + .clone() + .color([ + { apply: "blue", params: [-255] }, + { apply: "green", params: [-255] }, + ]) + .getBuffer(JimpMime.png); + resolve( + new File( + [new Uint8Array((await split).values())], + "红.png", + { type: "image/png" }, + ), + ); + } catch (err) { + reject( + new OperationError(`无法分离红色通道:${err}`), + ); + } + }); + + const green = new Promise(async (resolve, reject) => { + try { + const split = parsedImage + .clone() + .color([ + { apply: "red", params: [-255] }, + { apply: "blue", params: [-255] }, + ]) + .getBuffer(JimpMime.png); + resolve( + new File( + [new Uint8Array((await split).values())], + "绿.png", + { type: "image/png" }, + ), + ); + } catch (err) { + reject( + new OperationError(`无法分离绿色通道:${err}`), + ); + } + }); + + const blue = new Promise(async (resolve, reject) => { + try { + const split = parsedImage + .color([ + { apply: "red", params: [-255] }, + { apply: "green", params: [-255] }, + ]) + .getBuffer(JimpMime.png); + resolve( + new File( + [new Uint8Array((await split).values())], + "蓝.png", + { type: "image/png" }, + ), + ); + } catch (err) { + reject( + new OperationError(`无法分离蓝色通道:${err}`), + ); + } + }); + + return await Promise.all([red, green, blue]); + } + + /** + * Displays the files in HTML for web apps. + * + * @param {File[]} files + * @returns {html} + */ + async present(files) { + return await Utils.displayFilesAsHTML(files); + } +} + +export default SplitColourChannels; diff --git a/plugins/srktoolbox/src/core/operations/StandardDeviation.mjs b/plugins/srktoolbox/src/core/operations/StandardDeviation.mjs new file mode 100644 index 00000000..19cc997d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/StandardDeviation.mjs @@ -0,0 +1,55 @@ +/** + * @author bwhitn [brian.m.whitney@outlook.com] + * @author d98762625 [d98762625@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import BigNumber from "bignumber.js"; +import Operation from "../Operation.mjs"; +import { stdDev, createNumArray } from "../lib/Arithmetic.mjs"; +import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs"; + + +/** + * Standard Deviation operation + */ +class StandardDeviation extends Operation { + + /** + * StandardDeviation constructor + */ + constructor() { + super(); + + this.name = "求标准差"; + this.module = "Default"; + this.description = "对一组数字求标准差。非数字的值会被忽略。

例: 0x0a 8 .5 计算出 4.089281382128433"; + this.infoURL = "https://wikipedia.org/wiki/Standard_deviation"; + this.inputType = "string"; + this.outputType = "BigNumber"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": ARITHMETIC_DELIM_OPTIONS, + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {BigNumber} + */ + run(input, args) { + const val = stdDev(createNumArray(input, args[0])); + return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN); + + } + +} + +export default StandardDeviation; diff --git a/plugins/srktoolbox/src/core/operations/Streebog.mjs b/plugins/srktoolbox/src/core/operations/Streebog.mjs new file mode 100644 index 00000000..a9f106ca --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Streebog.mjs @@ -0,0 +1,65 @@ +/** + * @author mshwed [m@ttshwed.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import GostDigest from "../vendor/gost/gostDigest.mjs"; +import {toHexFast} from "../lib/Hex.mjs"; + +/** + * Streebog operation + */ +class Streebog extends Operation { + + /** + * Streebog constructor + */ + constructor() { + super(); + + this.name = "Streebog"; + this.module = "Hashing"; + this.description = "Streebog是俄罗斯国家标准GOST R 34.11-2012 Information Technology \u2013 Cryptographic Information Security \u2013 Hash Function定义的哈希算法。此算法设计的初衷为替换旧GOST哈希算法GOST R 34.11-94,同时也是为了对标由美国国安局发起的SHA-3。"; + this.infoURL = "https://wikipedia.org/wiki/Streebog"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "长度", + "type": "option", + "value": ["256", "512"] + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [length] = args; + + const algorithm = { + version: 2012, + mode: "HASH", + length: parseInt(length, 10) + }; + + try { + const gostDigest = new GostDigest(algorithm); + + return toHexFast(gostDigest.digest(input)); + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default Streebog; diff --git a/plugins/srktoolbox/src/core/operations/Strings.mjs b/plugins/srktoolbox/src/core/operations/Strings.mjs new file mode 100644 index 00000000..1a9b0c2d --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Strings.mjs @@ -0,0 +1,141 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import XRegExp from "xregexp"; +import { search } from "../lib/Extract.mjs"; +import { caseInsensitiveSort } from "../lib/Sort.mjs"; + +/** + * Strings operation + */ +class Strings extends Operation { + + /** + * Strings constructor + */ + constructor() { + super(); + + this.name = "Strings"; + this.module = "Regex"; + this.description = "从输入中提取所有的字符串,类似Unix的strings工具。"; + this.infoURL = "https://wikipedia.org/wiki/Strings_(Unix)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "编码", + type: "option", + value: ["单字节", "16位小端序", "16位大端序", "所有"] + }, + { + name: "最短长度", + type: "number", + value: 4 + }, + { + name: "匹配类型", + type: "option", + value: [ + "[ASCII]", "字母数字+标点 (A)", "所有可打印字符 (A)", "C风格字符串 (A)", + "[Unicode]", "字母数字+标点 (U)", "所有可打印字符 (U)", "C风格字符串 (U)" + ] + }, + { + name: "显示总数", + type: "boolean", + value: false + }, + { + name: "排序", + type: "boolean", + value: false + }, + { + name: "去重", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [encoding, minLen, matchType, displayTotal, sort, unique] = args, + alphanumeric = "A-Z\\d", + punctuation = "/\\-:.,_$%'\"()<>= !\\[\\]{}@", + printable = "\x20-\x7e", + uniAlphanumeric = "\\pL\\pN", + uniPunctuation = "\\pP\\pZ", + uniPrintable = "\\pL\\pM\\pZ\\pS\\pN\\pP"; + + let strings = ""; + + switch (matchType) { + case "字母数字+标点 (A)": + strings = `[${alphanumeric + punctuation}]`; + break; + case "所有可打印字符 (A)": + case "C风格字符串 (A)": + strings = `[${printable}]`; + break; + case "字母数字+标点 (U)": + strings = `[${uniAlphanumeric + uniPunctuation}]`; + break; + case "所有可打印字符 (U)": + case "C风格字符串 (U)": + strings = `[${uniPrintable}]`; + break; + } + + // UTF-16 support is hacked in by allowing null bytes on either side of the matched chars + switch (encoding) { + case "所有": + strings = `(\x00?${strings}\x00?)`; + break; + case "16位小端序": + strings = `(${strings}\x00)`; + break; + case "16位大端序": + strings = `(\x00${strings})`; + break; + case "单字节": + default: + break; + } + + strings = `${strings}{${minLen},}`; + + if (matchType.includes("C风格字符串")) { + strings += "\x00"; + } + + const regex = new XRegExp(strings, "ig"); + const results = search( + input, + regex, + null, + sort ? caseInsensitiveSort : null, + unique + ); + + if (displayTotal) { + return `总计: ${results.length}\n\n${results.join("\n")}`; + } else { + return results.join("\n"); + } + } + +} + +export default Strings; diff --git a/plugins/srktoolbox/src/core/operations/StripHTMLTags.mjs b/plugins/srktoolbox/src/core/operations/StripHTMLTags.mjs new file mode 100644 index 00000000..858fda09 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/StripHTMLTags.mjs @@ -0,0 +1,74 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Strip HTML tags operation + */ +class StripHTMLTags extends Operation { + + /** + * StripHTMLTags constructor + */ + constructor() { + super(); + + this.name = "移除HTML标签"; + this.module = "Default"; + this.description = "从输入中移除所有的HTML标签。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "移除缩进", + "type": "boolean", + "value": true + }, + { + "name": "移除多余换行", + "type": "boolean", + "value": true + } + ]; + this.checks = [ + { + pattern: "(|
|)", + flags: "i", + args: [true, true] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [removeIndentation, removeLineBreaks] = args; + + input = Utils.stripHtmlTags(input); + + if (removeIndentation) { + input = input.replace(/\n[ \f\t]+/g, "\n"); + } + + if (removeLineBreaks) { + input = input + .replace(/^\s*\n/, "") // first line + .replace(/(\n\s*){2,}/g, "\n"); // all others + } + + return input; + } + +} + +export default StripHTMLTags; diff --git a/plugins/srktoolbox/src/core/operations/StripHTTPHeaders.mjs b/plugins/srktoolbox/src/core/operations/StripHTTPHeaders.mjs new file mode 100644 index 00000000..99d5efd7 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/StripHTTPHeaders.mjs @@ -0,0 +1,52 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Strip HTTP headers operation + */ +class StripHTTPHeaders extends Operation { + + /** + * StripHTTPHeaders constructor + */ + constructor() { + super(); + + this.name = "移除HTTP标头"; + this.module = "Default"; + this.description = "从HTTP请求或响应文本中删除请求头或响应头,使用首次出现的两个换行符作为定位。"; + this.infoURL = "https://wikipedia.org/wiki/Hypertext_Transfer_Protocol#Message_format"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + this.checks = [ + { + pattern: "^HTTP(.|\\s)+?(\\r?\\n){2}", + flags: "", + args: [] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let headerEnd = input.indexOf("\r\n\r\n"); + headerEnd = (headerEnd < 0) ? input.indexOf("\n\n") + 2 : headerEnd + 4; + + return (headerEnd < 2) ? input : input.slice(headerEnd, input.length); + } + +} + +export default StripHTTPHeaders; diff --git a/plugins/srktoolbox/src/core/operations/StripIPv4Header.mjs b/plugins/srktoolbox/src/core/operations/StripIPv4Header.mjs new file mode 100644 index 00000000..63b0f6c2 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/StripIPv4Header.mjs @@ -0,0 +1,59 @@ +/** + * @author c65722 [] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Stream from "../lib/Stream.mjs"; + +/** + * Strip IPv4 header operation + */ +class StripIPv4Header extends Operation { + + /** + * StripIPv4Header constructor + */ + constructor() { + super(); + + this.name = "移除IPv4标头"; + this.module = "Default"; + this.description = "从IPv4数据包移除IPv4标头,只输出数据包载荷"; + this.infoURL = "https://wikipedia.org/wiki/IPv4"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const MIN_HEADER_LEN = 20; + + const s = new Stream(new Uint8Array(input)); + if (s.length < MIN_HEADER_LEN) { + throw new OperationError("输入长度小于IPv4标头最小长度"); + } + + const ihl = s.readInt(1) & 0x0f; + const dataOffsetBytes = ihl * 4; + if (s.length < dataOffsetBytes) { + throw new OperationError("输入长度小于IHL"); + } + + s.moveTo(dataOffsetBytes); + + return s.getBytes().buffer; + } + +} + +export default StripIPv4Header; diff --git a/plugins/srktoolbox/src/core/operations/StripTCPHeader.mjs b/plugins/srktoolbox/src/core/operations/StripTCPHeader.mjs new file mode 100644 index 00000000..d6af87be --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/StripTCPHeader.mjs @@ -0,0 +1,62 @@ +/** + * @author c65722 [] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Stream from "../lib/Stream.mjs"; + +/** + * Strip TCP header operation + */ +class StripTCPHeader extends Operation { + + /** + * StripTCPHeader constructor + */ + constructor() { + super(); + + this.name = "移除TCP标头"; + this.module = "Default"; + this.description = "从TCP段移除TCP标头,只输出载荷。"; + this.infoURL = "https://wikipedia.org/wiki/Transmission_Control_Protocol"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const MIN_HEADER_LEN = 20; + const DATA_OFFSET_OFFSET = 12; + const DATA_OFFSET_LEN_BITS = 4; + + const s = new Stream(new Uint8Array(input)); + if (s.length < MIN_HEADER_LEN) { + throw new OperationError("TCP标头长度至少20字节"); + } + + s.moveTo(DATA_OFFSET_OFFSET); + const dataOffsetWords = s.readBits(DATA_OFFSET_LEN_BITS); + const dataOffsetBytes = dataOffsetWords * 4; + if (s.length < dataOffsetBytes) { + throw new OperationError("输入长度小于数据偏移量"); + } + + s.moveTo(dataOffsetBytes); + + return s.getBytes().buffer; + } + +} + +export default StripTCPHeader; diff --git a/plugins/srktoolbox/src/core/operations/StripUDPHeader.mjs b/plugins/srktoolbox/src/core/operations/StripUDPHeader.mjs new file mode 100644 index 00000000..98b23d1c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/StripUDPHeader.mjs @@ -0,0 +1,53 @@ +/** + * @author c65722 [] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Stream from "../lib/Stream.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Strip UDP header operation + */ +class StripUDPHeader extends Operation { + + /** + * StripUDPHeader constructor + */ + constructor() { + super(); + + this.name = "移除UDP标头"; + this.module = "Default"; + this.description = "从UDP数据报移除UDP标头,只输出载荷。"; + this.infoURL = "https://wikipedia.org/wiki/User_Datagram_Protocol"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const HEADER_LEN = 8; + + const s = new Stream(new Uint8Array(input)); + if (s.length < HEADER_LEN) { + throw new OperationError("UDP标头长度至少8字节"); + } + + s.moveTo(HEADER_LEN); + + return s.getBytes().buffer; + } + +} + +export default StripUDPHeader; diff --git a/plugins/srktoolbox/src/core/operations/Subsection.mjs b/plugins/srktoolbox/src/core/operations/Subsection.mjs new file mode 100644 index 00000000..4e7086ff --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Subsection.mjs @@ -0,0 +1,163 @@ +/** + * @author j433866 [j433866@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Recipe from "../Recipe.mjs"; +import Dish from "../Dish.mjs"; + +/** + * Subsection operation + */ +class Subsection extends Operation { + + /** + * Subsection constructor + */ + constructor() { + super(); + + this.name = "Subsection"; + this.flowControl = true; + this.module = "Default"; + this.description = "使用正则对输入数据进行匹配,然后对匹配到的内容进行下面的所有操作。

最多只能使用一个捕获组,整个流程只会针对这个捕获组的匹配内容进行操作。如果有多个捕获组,只会使用第一个的内容。

使用Merge操作来重置Subsection操作的效果。"; + this.infoURL = ""; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "匹配内容(正则)", + "type": "string", + "value": "" + }, + { + "name": "大小写不敏感(i)", + "type": "boolean", + "value": true + }, + { + "name": "全局匹配(g)", + "type": "boolean", + "value": true + }, + { + "name": "忽略报错", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {Object} state - The current state of the recipe. + * @param {number} state.progress - The current position in the recipe. + * @param {Dish} state.dish - The Dish being operated on + * @param {Operation[]} state.opList - The list of operations in the recipe + * @returns {Object} - The updated state of the recipe + */ + async run(state) { + const opList = state.opList, + inputType = opList[state.progress].inputType, + outputType = opList[state.progress].outputType, + input = await state.dish.get(inputType), + ings = opList[state.progress].ingValues, + [section, caseSensitive, global, ignoreErrors] = ings, + subOpList = []; + + if (input && section !== "") { + // Set to 1 as if we are here, then there is one, the current one. + let numOp = 1; + // Create subOpList for each tranche to operate on + // all remaining operations unless we encounter a Merge + for (let i = state.progress + 1; i < opList.length; i++) { + if (opList[i].name === "Merge" && !opList[i].disabled) { + numOp--; + if (numOp === 0 || opList[i].ingValues[0]) + break; + else + // Not this subsection's Merge. + subOpList.push(opList[i]); + } else { + if (opList[i].name === "Fork" || opList[i].name === "Subsection") + numOp++; + subOpList.push(opList[i]); + } + } + + let flags = "", + inOffset = 0, + output = "", + m, + progress = 0; + + if (!caseSensitive) flags += "i"; + if (global) flags += "g"; + + const regex = new RegExp(section, flags), + recipe = new Recipe(); + + recipe.addOperations(subOpList); + state.forkOffset += state.progress + 1; + + // Take a deep(ish) copy of the ingredient values + const ingValues = subOpList.map(op => JSON.parse(JSON.stringify(op.ingValues))); + let matched = false; + + // Run recipe over each match + while ((m = regex.exec(input))) { + matched = true; + // Add up to match + let matchStr = m[0]; + + if (m.length === 1) { // No capture groups + output += input.slice(inOffset, m.index); + inOffset = m.index + m[0].length; + } else if (m.length >= 2) { + matchStr = m[1]; + + // Need to add some of the matched string that isn't in the capture group + output += input.slice(inOffset, m.index + m[0].indexOf(m[1])); + // Set i to be after the end of the first capture group + inOffset = m.index + m[0].indexOf(m[1]) + m[1].length; + } + + // Baseline ing values for each tranche so that registers are reset + recipe.opList.forEach((op, i) => { + op.ingValues = JSON.parse(JSON.stringify(ingValues[i])); + }); + + const dish = new Dish(); + dish.set(matchStr, inputType); + + try { + progress = await recipe.execute(dish, 0, state); + } catch (err) { + if (!ignoreErrors) { + throw err; + } + progress = err.progress + 1; + } + output += await dish.get(outputType); + if (!regex.global) break; + } + + // If no matches were found, advance progress to after a Merge op + // Otherwise, the operations below Subsection will be run on all the input data + if (!matched) { + state.progress += subOpList.length + 1; + } + + output += input.slice(inOffset); + state.progress += progress; + state.dish.set(output, outputType); + } + return state; + } + +} + +export default Subsection; diff --git a/plugins/srktoolbox/src/core/operations/Substitute.mjs b/plugins/srktoolbox/src/core/operations/Substitute.mjs new file mode 100644 index 00000000..901330d8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Substitute.mjs @@ -0,0 +1,114 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Substitute operation + */ +class Substitute extends Operation { + + /** + * Substitute constructor + */ + constructor() { + super(); + + this.name = "替换密码"; + this.module = "Default"; + this.description = "替换密码允许你将明文中的任意字节替换成其它字节。可以用来生成凯撒密码,但同时提供了更多的加密手段。

输入想要替换的内容在明文框,然后替换成的内容在密文框。

无法显示的字节可以用转义形式。例如换行可以写成 \\n\\x0a

用连字符来指定字节范围。例如 0123456789 可以写成 0-9

注意反斜杠是用来转义其它字符的,所以如果需要使用反斜杠,它自身也要被转义(例\\\\)。"; + this.infoURL = "https://wikipedia.org/wiki/Substitution_cipher"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "明文", + "type": "binaryString", + "value": "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + }, + { + "name": "密文", + "type": "binaryString", + "value": "XYZABCDEFGHIJKLMNOPQRSTUVW" + }, + { + "name": "忽略大小写", + "type": "boolean", + "value": false + } + ]; + } + + /** + * Convert a single character using the dictionary, if ignoreCase is true then + * check in the dictionary for both upper and lower case versions of the character. + * In output the input character case is preserved. + * @param {string} char + * @param {Object} dict + * @param {boolean} ignoreCase + * @returns {string} + */ + cipherSingleChar(char, dict, ignoreCase) { + if (!ignoreCase) + return dict[char] || char; + + const isUpperCase = char === char.toUpperCase(); + + // convert using the dictionary keeping the case of the input character + + if (dict[char] !== undefined) { + // if the character is in the dictionary return the value with the input case + return isUpperCase ? dict[char].toUpperCase() : dict[char].toLowerCase(); + } + + // check for the other case, if it is in the dictionary return the value with the right case + if (isUpperCase) { + if (dict[char.toLowerCase()] !== undefined) + return dict[char.toLowerCase()].toUpperCase(); + } else { + if (dict[char.toUpperCase()] !== undefined) + return dict[char.toUpperCase()].toLowerCase(); + } + + return char; + } + + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const plaintext = Utils.expandAlphRange([...args[0]]), + ciphertext = Utils.expandAlphRange([...args[1]]), + ignoreCase = args[2]; + let output = ""; + + if (plaintext.length !== ciphertext.length) { + output = "警告:明文和密文长度不同\n\n"; + } + + // create dictionary for conversion + const dict = {}; + for (let i = 0; i < Math.min(ciphertext.length, plaintext.length); i++) { + dict[plaintext[i]] = ciphertext[i]; + } + + // map every letter with the conversion function + for (const character of input) { + output += this.cipherSingleChar(character, dict, ignoreCase); + } + + return output; + } + +} + +export default Substitute; diff --git a/plugins/srktoolbox/src/core/operations/Subtract.mjs b/plugins/srktoolbox/src/core/operations/Subtract.mjs new file mode 100644 index 00000000..675cf818 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Subtract.mjs @@ -0,0 +1,54 @@ +/** + * @author bwhitn [brian.m.whitney@outlook.com] + * @author d98762625 [d98762625@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import BigNumber from "bignumber.js"; +import Operation from "../Operation.mjs"; +import { sub, createNumArray } from "../lib/Arithmetic.mjs"; +import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs"; + + +/** + * Subtract operation + */ +class Subtract extends Operation { + + /** + * Subtract constructor + */ + constructor() { + super(); + + this.name = "求差"; + this.module = "Default"; + this.description = "对一组数字求差(aka. 减法)。非数字的值会被忽略。

例: 0x0a 8 .5 计算为 1.5"; + this.infoURL = "https://wikipedia.org/wiki/Subtraction"; + this.inputType = "string"; + this.outputType = "BigNumber"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": ARITHMETIC_DELIM_OPTIONS, + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {BigNumber} + */ + run(input, args) { + const val = sub(createNumArray(input, args[0])); + return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN); + } + +} + +export default Subtract; diff --git a/plugins/srktoolbox/src/core/operations/Sum.mjs b/plugins/srktoolbox/src/core/operations/Sum.mjs new file mode 100644 index 00000000..bf3cea78 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Sum.mjs @@ -0,0 +1,54 @@ +/** + * @author bwhitn [brian.m.whitney@outlook.com] + * @author d98762625 [d98762625@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import BigNumber from "bignumber.js"; +import Operation from "../Operation.mjs"; +import { sum, createNumArray } from "../lib/Arithmetic.mjs"; +import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs"; + + +/** + * Sum operation + */ +class Sum extends Operation { + + /** + * Sum constructor + */ + constructor() { + super(); + + this.name = "求和"; + this.module = "Default"; + this.description = "对一组数字求和(aka. 加法)。非数字的值会被忽略。

例: 0x0a 8 .5 计算为 18.5"; + this.infoURL = "https://wikipedia.org/wiki/Summation"; + this.inputType = "string"; + this.outputType = "BigNumber"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": ARITHMETIC_DELIM_OPTIONS, + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {BigNumber} + */ + run(input, args) { + const val = sum(createNumArray(input, args[0])); + return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN); + } + +} + +export default Sum; diff --git a/plugins/srktoolbox/src/core/operations/SwapCase.mjs b/plugins/srktoolbox/src/core/operations/SwapCase.mjs new file mode 100644 index 00000000..7925e01e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SwapCase.mjs @@ -0,0 +1,78 @@ +/** + * @author mikecat + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Swap case operation + */ +class SwapCase extends Operation { + + /** + * SwapCase constructor + */ + constructor() { + super(); + + this.name = "大小写互换"; + this.module = "Default"; + this.description = "大写转小写,小写转大写。"; + this.infoURL = ""; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let result = ""; + for (let i = 0; i < input.length; i++) { + const c = input.charAt(i); + const upper = c.toUpperCase(); + if (c === upper) { + result += c.toLowerCase(); + } else { + result += upper; + } + } + return result; + } + + /** + * Highlight Swap case + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight Swap case in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default SwapCase; diff --git a/plugins/srktoolbox/src/core/operations/SwapEndianness.mjs b/plugins/srktoolbox/src/core/operations/SwapEndianness.mjs new file mode 100644 index 00000000..c30aaa1c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SwapEndianness.mjs @@ -0,0 +1,140 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {toHex, fromHex} from "../lib/Hex.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Swap endianness operation + */ +class SwapEndianness extends Operation { + + /** + * SwapEndianness constructor + */ + constructor() { + super(); + + this.name = "端序转换"; + this.module = "Default"; + this.description = "转换输入数据的大小端序。可以读取十六进制或原始文本。输出格式与输入保持一致。"; + this.infoURL = "https://wikipedia.org/wiki/Endianness"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "数据格式", + "type": "option", + "value": ["十六进制", "原始文本"] + }, + { + "name": "字长 (字节)", + "type": "number", + "value": 4 + }, + { + "name": "填充不完整字编码", + "type": "boolean", + "value": true + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [dataFormat, wordLength, padIncompleteWords] = args, + result = [], + words = []; + let i = 0, + j = 0, + data = []; + + if (wordLength <= 0) { + throw new OperationError("字长必须大于0"); + } + + // Convert input to raw data based on specified data format + switch (dataFormat) { + case "十六进制": + data = fromHex(input); + break; + case "原始文本": + data = Utils.strToByteArray(input); + break; + default: + data = input; + } + + // Split up into words + for (i = 0; i < data.length; i += wordLength) { + const word = data.slice(i, i + wordLength); + + // Pad word if too short + if (padIncompleteWords && word.length < wordLength) { + for (j = word.length; j < wordLength; j++) { + word.push(0); + } + } + + words.push(word); + } + + // Swap endianness and flatten + for (i = 0; i < words.length; i++) { + j = words[i].length; + while (j--) { + result.push(words[i][j]); + } + } + + // Convert data back to specified data format + switch (dataFormat) { + case "十六进制": + return toHex(result); + case "原始文本": + return Utils.byteArrayToUtf8(result); + default: + return result; + } + } + + /** + * Highlight Swap endianness + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight Swap endianness in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default SwapEndianness; diff --git a/plugins/srktoolbox/src/core/operations/SymmetricDifference.mjs b/plugins/srktoolbox/src/core/operations/SymmetricDifference.mjs new file mode 100644 index 00000000..ec78f7dd --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SymmetricDifference.mjs @@ -0,0 +1,101 @@ +/** + * @author d98762625 [d98762625@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Utils from "../Utils.mjs"; +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Set Symmetric Difference operation + */ +class SymmetricDifference extends Operation { + + /** + * Symmetric Difference constructor + */ + constructor() { + super(); + + this.name = "对称差"; + this.module = "Default"; + this.description = "计算两个集合的对称差。"; + this.infoURL = "https://wikipedia.org/wiki/Symmetric_difference"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "集合分隔符", + type: "binaryString", + value: Utils.escapeHtml("\\n\\n") + }, + { + name: "元素分隔符", + type: "binaryString", + value: "," + }, + ]; + } + + /** + * Validate input length + * + * @param {Object[]} sets + * @throws {Error} if not two sets + */ + validateSampleNumbers(sets) { + if (!sets || (sets.length !== 2)) { + throw new OperationError("集合数量错误,你可能需要调整集合分隔符或者添加一些数据。"); + } + } + + /** + * Run the difference operation + * + * @param {string} input + * @param {Object[]} args + * @returns {string} + * @throws {OperationError} + */ + run(input, args) { + [this.sampleDelim, this.itemDelimiter] = args; + const sets = input.split(this.sampleDelim); + + this.validateSampleNumbers(sets); + + return this.runSymmetricDifference(...sets.map(s => s.split(this.itemDelimiter))); + } + + /** + * Get elements in set a that are not in set b + * + * @param {Object[]} a + * @param {Object[]} b + * @returns {Object[]} + */ + runSetDifference(a, b) { + return a.filter((item) => { + return b.indexOf(item) === -1; + }); + } + + /** + * Get elements of each set that aren't in the other set. + * + * @param {Object[]} a + * @param {Object[]} b + * @return {Object[]} + */ + runSymmetricDifference(a, b) { + return this.runSetDifference(a, b) + .concat(this.runSetDifference(b, a)) + .join(this.itemDelimiter); + } + +} + +export default SymmetricDifference; diff --git a/plugins/srktoolbox/src/core/operations/SyntaxHighlighter.mjs b/plugins/srktoolbox/src/core/operations/SyntaxHighlighter.mjs new file mode 100644 index 00000000..b336bc23 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/SyntaxHighlighter.mjs @@ -0,0 +1,81 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import hljs from "highlight.js"; + +/** + * Syntax highlighter operation + */ +class SyntaxHighlighter extends Operation { + + /** + * SyntaxHighlighter constructor + */ + constructor() { + super(); + + this.name = "语法高亮"; + this.module = "Code"; + this.description = "为多种编程语言添加语法高亮。注意:此操作不会对代码进行缩进,需配合使用对应的“美化(Beautify)”操作。"; + this.infoURL = "https://wikipedia.org/wiki/Syntax_highlighting"; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + "name": "语言", + "type": "option", + "value": ["自动检测"].concat(hljs.listLanguages()) + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const language = args[0]; + + if (language === "自动检测") { + return hljs.highlightAuto(input).value; + } + + return hljs.highlight(language, input, true).value; + } + + /** + * Highlight Syntax highlighter + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight Syntax highlighter in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default SyntaxHighlighter; diff --git a/plugins/srktoolbox/src/core/operations/TCPIPChecksum.mjs b/plugins/srktoolbox/src/core/operations/TCPIPChecksum.mjs new file mode 100644 index 00000000..368247c5 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/TCPIPChecksum.mjs @@ -0,0 +1,56 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * TCP/IP Checksum operation + */ +class TCPIPChecksum extends Operation { + + /** + * TCPIPChecksum constructor + */ + constructor() { + super(); + + this.name = "TCP/IP校验和"; + this.module = "Crypto"; + this.description = "从输入的原始字节内容计算TCP (Transport Control Protocol)或IP (Internet Protocol)标头的校验和。"; + this.infoURL = "https://wikipedia.org/wiki/IPv4_header_checksum"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + input = new Uint8Array(input); + let csum = 0; + + for (let i = 0; i < input.length; i++) { + if (i % 2 === 0) { + csum += (input[i] << 8); + } else { + csum += input[i]; + } + } + + csum = (csum >> 16) + (csum & 0xffff); + + return Utils.hex(0xffff - csum); + } + +} + +export default TCPIPChecksum; diff --git a/plugins/srktoolbox/src/core/operations/Tail.mjs b/plugins/srktoolbox/src/core/operations/Tail.mjs new file mode 100644 index 00000000..de2bd703 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Tail.mjs @@ -0,0 +1,72 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs"; + +/** + * Tail operation + */ +class Tail extends Operation { + + /** + * Tail constructor + */ + constructor() { + super(); + + this.name = "Tail"; + this.module = "Default"; + this.description = "和UNIX的tail工具类似。
输出后n行。
输入负数可以选取除最前n行之外的内容。
可以选择不同的分隔符来实现选取最后n个数据。"; + this.infoURL = "https://wikipedia.org/wiki/Tail_(Unix)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": INPUT_DELIM_OPTIONS + }, + { + "name": "选取数量", + "type": "number", + "value": 10 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let delimiter = args[0]; + const number = args[1]; + + delimiter = Utils.charRep(delimiter); + const splitInput = input.split(delimiter); + + return splitInput + .filter((line, lineIndex) => { + lineIndex += 1; + + if (number < 0) { + return lineIndex > -number; + } else { + return lineIndex > splitInput.length - number; + } + }) + .join(delimiter); + + } + +} + +export default Tail; diff --git a/plugins/srktoolbox/src/core/operations/TakeBytes.mjs b/plugins/srktoolbox/src/core/operations/TakeBytes.mjs new file mode 100644 index 00000000..51f2ce84 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/TakeBytes.mjs @@ -0,0 +1,119 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * Take bytes operation + */ +class TakeBytes extends Operation { + + /** + * TakeBytes constructor + */ + constructor() { + super(); + + this.name = "提取字节"; + this.module = "Default"; + this.description = "从数据中提取特定数量的字节。允许使用负数值。"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + "name": "起始位置", + "type": "number", + "value": 0 + }, + { + "name": "长度", + "type": "number", + "value": 5 + }, + { + "name": "对每一行单独进行提取", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + * + * @throws {OperationError} if invalid value + */ + run(input, args) { + let start = args[0], + length = args[1]; + const applyToEachLine = args[2]; + + if (!applyToEachLine) { + if (start < 0) { // Take from the end + start = input.byteLength + start; + } + + if (length < 0) { // Flip start point + start = start + length; + if (start < 0) { + start = input.byteLength + start; + length = start - length; + } else { + length = -length; + } + } + + return input.slice(start, start+length); + } + + // Split input into lines + const data = new Uint8Array(input); + const lines = []; + let line = [], + i; + + for (i = 0; i < data.length; i++) { + if (data[i] === 0x0a) { + lines.push(line); + line = []; + } else { + line.push(data[i]); + } + } + lines.push(line); + + let output = []; + let s = start, + l = length; + for (i = 0; i < lines.length; i++) { + if (s < 0) { // Take from the end + s = lines[i].length + s; + } + + if (l < 0) { // Flip start point + s = s + l; + if (s < 0) { + s = lines[i].length + s; + l = s - l; + } else { + l = -l; + } + } + output = output.concat(lines[i].slice(s, s+l)); + output.push(0x0a); + s = start; + l = length; + } + return new Uint8Array(output.slice(0, output.length-1)).buffer; + } + +} + +export default TakeBytes; diff --git a/plugins/srktoolbox/src/core/operations/TakeNthBytes.mjs b/plugins/srktoolbox/src/core/operations/TakeNthBytes.mjs new file mode 100644 index 00000000..e0c13d3e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/TakeNthBytes.mjs @@ -0,0 +1,81 @@ +/** + * @author Oshawk [oshawk@protonmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Take nth bytes operation + */ +class TakeNthBytes extends Operation { + + /** + * TakeNthBytes constructor + */ + constructor() { + super(); + + this.name = "提取每N个字节"; + this.module = "Default"; + this.description = "提取输入内容的每N个字节。"; + this.infoURL = ""; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "提取每N个字节", + type: "number", + value: 4 + }, + { + name: "起始位置", + type: "number", + value: 0 + }, + { + name: "应用到每一行", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const n = args[0]; + const start = args[1]; + const eachLine = args[2]; + + if (parseInt(n, 10) !== n || n <= 0) { + throw new OperationError("'提取每N个字节'必须为正整数"); + } + if (parseInt(start, 10) !== start || start < 0) { + throw new OperationError("'起始位置'必须为非负整数"); + } + + let offset = 0; + const output = []; + for (let i = 0; i < input.length; i++) { + if (eachLine && input[i] === 0x0a) { + output.push(0x0a); + offset = i + 1; + } else if (i - offset >= start && (i - (start + offset)) % n === 0) { + output.push(input[i]); + } + } + + return output; + } + +} + +export default TakeNthBytes; diff --git a/plugins/srktoolbox/src/core/operations/Tar.mjs b/plugins/srktoolbox/src/core/operations/Tar.mjs new file mode 100644 index 00000000..8d44b430 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Tar.mjs @@ -0,0 +1,144 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Tar operation + */ +class Tar extends Operation { + + /** + * Tar constructor + */ + constructor() { + super(); + + this.name = "Tar"; + this.module = "Compression"; + this.description = "把输入打包成tarball。

目前不支持多个文件。"; + this.infoURL = "https://wikipedia.org/wiki/Tar_(computing)"; + this.inputType = "ArrayBuffer"; + this.outputType = "File"; + this.args = [ + { + "name": "文件名", + "type": "string", + "value": "file.txt" + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + input = new Uint8Array(input); + + const Tarball = function() { + this.bytes = new Array(512); + this.position = 0; + }; + + Tarball.prototype.addEmptyBlock = function() { + const filler = new Array(512); + filler.fill(0); + this.bytes = this.bytes.concat(filler); + }; + + Tarball.prototype.writeBytes = function(bytes) { + const self = this; + + if (this.position + bytes.length > this.bytes.length) { + this.addEmptyBlock(); + } + + Array.prototype.forEach.call(bytes, function(b, i) { + if (typeof b.charCodeAt !== "undefined") { + b = b.charCodeAt(); + } + + self.bytes[self.position] = b; + self.position += 1; + }); + }; + + Tarball.prototype.writeEndBlocks = function() { + const numEmptyBlocks = 2; + for (let i = 0; i < numEmptyBlocks; i++) { + this.addEmptyBlock(); + } + }; + + const fileSize = input.length.toString(8).padStart(11, "0"); + const currentUnixTimestamp = Math.floor(Date.now() / 1000); + const lastModTime = currentUnixTimestamp.toString(8).padStart(11, "0"); + + const file = { + fileName: Utils.padBytesRight(args[0], 100), + fileMode: Utils.padBytesRight("0000664", 8), + ownerUID: Utils.padBytesRight("0", 8), + ownerGID: Utils.padBytesRight("0", 8), + size: Utils.padBytesRight(fileSize, 12), + lastModTime: Utils.padBytesRight(lastModTime, 12), + checksum: " ", + type: "0", + linkedFileName: Utils.padBytesRight("", 100), + USTARFormat: Utils.padBytesRight("ustar", 6), + version: "00", + ownerUserName: Utils.padBytesRight("", 32), + ownerGroupName: Utils.padBytesRight("", 32), + deviceMajor: Utils.padBytesRight("", 8), + deviceMinor: Utils.padBytesRight("", 8), + fileNamePrefix: Utils.padBytesRight("", 155), + }; + + let checksum = 0; + for (const key in file) { + const bytes = file[key]; + Array.prototype.forEach.call(bytes, function(b) { + if (typeof b.charCodeAt !== "undefined") { + checksum += b.charCodeAt(); + } else { + checksum += b; + } + }); + } + checksum = Utils.padBytesRight(checksum.toString(8).padStart(7, "0"), 8); + file.checksum = checksum; + + const tarball = new Tarball(); + tarball.writeBytes(file.fileName); + tarball.writeBytes(file.fileMode); + tarball.writeBytes(file.ownerUID); + tarball.writeBytes(file.ownerGID); + tarball.writeBytes(file.size); + tarball.writeBytes(file.lastModTime); + tarball.writeBytes(file.checksum); + tarball.writeBytes(file.type); + tarball.writeBytes(file.linkedFileName); + tarball.writeBytes(file.USTARFormat); + tarball.writeBytes(file.version); + tarball.writeBytes(file.ownerUserName); + tarball.writeBytes(file.ownerGroupName); + tarball.writeBytes(file.deviceMajor); + tarball.writeBytes(file.deviceMinor); + tarball.writeBytes(file.fileNamePrefix); + tarball.writeBytes(Utils.padBytesRight("", 12)); + tarball.writeBytes(input); + tarball.writeEndBlocks(); + + return new File([new Uint8Array(tarball.bytes)], args[0]); + } + +} + +export default Tar; diff --git a/plugins/srktoolbox/src/core/operations/Template.mjs b/plugins/srktoolbox/src/core/operations/Template.mjs new file mode 100644 index 00000000..13210943 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Template.mjs @@ -0,0 +1,55 @@ +/** + * @author kendallgoto [k@kgo.to] + * @copyright Crown Copyright 2025 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Handlebars from "handlebars"; + +/** + * Template operation + */ +class Template extends Operation { + + /** + * Template constructor + */ + constructor() { + super(); + + this.name = "模板渲染"; + this.module = "Handlebars"; + this.description = "使用Handlebars/Mustache模板引擎,通过JSON输入数据替换变量并渲染模板。模板渲染结果将仅输出纯文本,以防止跨站脚本攻击。"; + this.infoURL = "https://handlebarsjs.com/"; + this.inputType = "JSON"; + this.outputType = "string"; + this.args = [ + { + name: "模板定义(.handlebars)", + type: "text", + value: "" + } + ]; + } + + /** + * @param {JSON} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [templateStr] = args; + try { + const template = Handlebars.compile(templateStr); + return template(input); + } catch (e) { + throw new OperationError(e); + } + } +} + +export default Template; diff --git a/plugins/srktoolbox/src/core/operations/TextEncodingBruteForce.mjs b/plugins/srktoolbox/src/core/operations/TextEncodingBruteForce.mjs new file mode 100644 index 00000000..56d25928 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/TextEncodingBruteForce.mjs @@ -0,0 +1,94 @@ +/** + * @author Cynser + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import cptable from "codepage"; +import {CHR_ENC_CODE_PAGES} from "../lib/ChrEnc.mjs"; + +/** + * Text Encoding Brute Force operation + */ +class TextEncodingBruteForce extends Operation { + + /** + * TextEncodingBruteForce constructor + */ + constructor() { + super(); + + this.name = "文本编码暴力破解"; + this.module = "Encodings"; + this.description = [ + "列出所有支持的字符集解码/编码结果,让你可以看出哪个是正确的。", + "

", + "支持的字符集:", + "
    ", + Object.keys(CHR_ENC_CODE_PAGES).map(e => `
  • ${e}
  • `).join("\n"), + "
" + ].join("\n"); + this.infoURL = "https://wikipedia.org/wiki/Character_encoding"; + this.inputType = "string"; + this.outputType = "json"; + this.presentType = "html"; + this.args = [ + { + name: "模式", + type: "option", + value: ["编码", "解码"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {json} + */ + run(input, args) { + const output = {}, + charsets = Object.keys(CHR_ENC_CODE_PAGES), + mode = args[0]; + + charsets.forEach(charset => { + try { + if (mode === "解码") { + output[charset] = cptable.utils.decode(CHR_ENC_CODE_PAGES[charset], input); + } else { + output[charset] = Utils.arrayBufferToStr(cptable.utils.encode(CHR_ENC_CODE_PAGES[charset], input)); + } + } catch (err) { + output[charset] = "无法解码"; + } + }); + + return output; + } + + /** + * Displays the encodings in an HTML table for web apps. + * + * @param {Object[]} encodings + * @returns {html} + */ + present(encodings) { + let table = ""; + + for (const enc in encodings) { + const value = Utils.escapeHtml(Utils.escapeWhitespace(encodings[enc])); + table += ``; + } + + table += "
字符集结果
${enc}${value}
"; + return table; + } + +} + +export default TextEncodingBruteForce; diff --git a/plugins/srktoolbox/src/core/operations/ToBCD.mjs b/plugins/srktoolbox/src/core/operations/ToBCD.mjs new file mode 100644 index 00000000..9f6f14ad --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToBCD.mjs @@ -0,0 +1,144 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {ENCODING_SCHEME, ENCODING_LOOKUP, FORMAT} from "../lib/BCD.mjs"; +import BigNumber from "bignumber.js"; + +/** + * To BCD operation + */ +class ToBCD extends Operation { + + /** + * ToBCD constructor + */ + constructor() { + super(); + + this.name = "BCD码编码"; + this.module = "Default"; + this.description = "BCD码(Binary-Coded Decimal)是一种十进制数字编码的形式。在这种编码下,每个十进制数字用一串单独的二进制比特来存储与表示。常见的有以4位或8位表示1个十进制数字。有时会用特殊的码位表示特殊符号。"; + this.infoURL = "https://wikipedia.org/wiki/Binary-coded_decimal"; + this.inputType = "BigNumber"; + this.outputType = "string"; + this.args = [ + { + "name": "编码方式", + "type": "option", + "value": ENCODING_SCHEME + }, + { + "name": "压缩", + "type": "boolean", + "value": true + }, + { + "name": "有符号", + "type": "boolean", + "value": false + }, + { + "name": "输出格式", + "type": "option", + "value": FORMAT + } + ]; + } + + /** + * @param {BigNumber} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (input.isNaN()) + throw new OperationError("无效输入"); + if (!input.integerValue(BigNumber.ROUND_DOWN).isEqualTo(input)) + throw new OperationError("BCD不支持非整数"); + + const encoding = ENCODING_LOOKUP[args[0]], + packed = args[1], + signed = args[2], + outputFormat = args[3]; + + // Split input number up into separate digits + const digits = input.toFixed().split(""); + + if (digits[0] === "-" || digits[0] === "+") { + digits.shift(); + } + + let nibbles = []; + + digits.forEach(d => { + const n = parseInt(d, 10); + nibbles.push(encoding[n]); + }); + + if (signed) { + if (packed && digits.length % 2 === 0) { + // If there are an even number of digits, we add a leading 0 so + // that the sign nibble doesn't sit in its own byte, leading to + // ambiguity around whether the number ends with a 0 or not. + nibbles.unshift(encoding[0]); + } + + nibbles.push(input > 0 ? 12 : 13); + // 12 ("C") for + (credit) + // 13 ("D") for - (debit) + } + + let bytes = []; + + if (packed) { + let encoded = 0, + little = false; + + nibbles.forEach(n => { + encoded ^= little ? n : (n << 4); + if (little) { + bytes.push(encoded); + encoded = 0; + } + little = !little; + }); + + if (little) bytes.push(encoded); + } else { + bytes = nibbles; + + // Add null high nibbles + nibbles = nibbles.map(n => { + return [0, n]; + }).reduce((a, b) => { + return a.concat(b); + }); + } + + // Output + switch (outputFormat) { + case "半字节": + return nibbles.map(n => { + return n.toString(2).padStart(4, "0"); + }).join(" "); + case "字节": + return bytes.map(b => { + return b.toString(2).padStart(8, "0"); + }).join(" "); + case "原始数据": + default: + return Utils.byteArrayToChars(bytes); + } + } + +} + +export default ToBCD; diff --git a/plugins/srktoolbox/src/core/operations/ToBase.mjs b/plugins/srktoolbox/src/core/operations/ToBase.mjs new file mode 100644 index 00000000..6f2afbbe --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToBase.mjs @@ -0,0 +1,56 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * To Base operation + */ +class ToBase extends Operation { + + /** + * ToBase constructor + */ + constructor() { + super(); + + this.name = "十进制数转其它进制"; + this.module = "Default"; + this.description = "把十进制数转换成其它给定进制"; + this.infoURL = "https://wikipedia.org/wiki/Radix"; + this.inputType = "BigNumber"; + this.outputType = "string"; + this.args = [ + { + "name": "进制", + "type": "number", + "value": 36 + } + ]; + } + + /** + * @param {BigNumber} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (!input) { + throw new OperationError("错误:输入必须是数字"); + } + const radix = args[0]; + if (radix < 2 || radix > 36) { + throw new OperationError("错误:进制必须在2~36之间"); + } + return input.toString(radix); + } + +} + +export default ToBase; diff --git a/plugins/srktoolbox/src/core/operations/ToBase32.mjs b/plugins/srktoolbox/src/core/operations/ToBase32.mjs new file mode 100644 index 00000000..8a4c048a --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToBase32.mjs @@ -0,0 +1,89 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {ALPHABET_OPTIONS} from "../lib/Base32.mjs"; + +/** + * To Base32 operation + */ +class ToBase32 extends Operation { + + /** + * ToBase32 constructor + */ + constructor() { + super(); + + this.name = "Base32编码"; + this.module = "Default"; + this.description = "Base32是把字节数据转换成特定字符组合的编码方式,编码后便于人类阅读,也方便计算机读取。Base32比Base64使用的字母表小一些,通常只包含大写字母和数字2到7。"; + this.infoURL = "https://wikipedia.org/wiki/Base32"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "可用字符", + type: "editableOption", + value: ALPHABET_OPTIONS + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (!input) return ""; + input = new Uint8Array(input); + + const alphabet = args[0] ? Utils.expandAlphRange(args[0]).join("") : "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="; + let output = "", + chr1, chr2, chr3, chr4, chr5, + enc1, enc2, enc3, enc4, enc5, enc6, enc7, enc8, + i = 0; + while (i < input.length) { + chr1 = input[i++]; + chr2 = input[i++]; + chr3 = input[i++]; + chr4 = input[i++]; + chr5 = input[i++]; + + enc1 = chr1 >> 3; + enc2 = ((chr1 & 7) << 2) | (chr2 >> 6); + enc3 = (chr2 >> 1) & 31; + enc4 = ((chr2 & 1) << 4) | (chr3 >> 4); + enc5 = ((chr3 & 15) << 1) | (chr4 >> 7); + enc6 = (chr4 >> 2) & 31; + enc7 = ((chr4 & 3) << 3) | (chr5 >> 5); + enc8 = chr5 & 31; + + if (isNaN(chr2)) { + enc3 = enc4 = enc5 = enc6 = enc7 = enc8 = 32; + } else if (isNaN(chr3)) { + enc5 = enc6 = enc7 = enc8 = 32; + } else if (isNaN(chr4)) { + enc6 = enc7 = enc8 = 32; + } else if (isNaN(chr5)) { + enc8 = 32; + } + + output += alphabet.charAt(enc1) + alphabet.charAt(enc2) + alphabet.charAt(enc3) + + alphabet.charAt(enc4) + alphabet.charAt(enc5) + alphabet.charAt(enc6) + + alphabet.charAt(enc7) + alphabet.charAt(enc8); + } + return output; + } + +} + +export default ToBase32; + diff --git a/plugins/srktoolbox/src/core/operations/ToBase45.mjs b/plugins/srktoolbox/src/core/operations/ToBase45.mjs new file mode 100644 index 00000000..e99f5cda --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToBase45.mjs @@ -0,0 +1,84 @@ +/** + * @author Thomas Weißschuh [thomas@t-8ch.de] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import {ALPHABET, highlightToBase45, highlightFromBase45} from "../lib/Base45.mjs"; +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * To Base45 operation + */ +class ToBase45 extends Operation { + + /** + * ToBase45 constructor + */ + constructor() { + super(); + + this.name = "Base45编码"; + this.module = "Default"; + this.description = "Base45是把字节数据转换成特定字符组合的编码方式,编码后便于人类阅读,也方便计算机读取。越高的Base数目会生成越短的字符串。Base45是为二维码优化的编码方式。"; + this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "可用字符", + type: "string", + value: ALPHABET + } + ]; + + this.highlight = highlightToBase45; + this.highlightReverse = highlightFromBase45; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (!input) return ""; + input = new Uint8Array(input); + const alphabet = Utils.expandAlphRange(args[0]); + + const res = []; + + for (const pair of Utils.chunked(input, 2)) { + let b = 0; + for (const e of pair) { + b *= 256; + b += e; + } + + let chars = 0; + do { + res.push(alphabet[b % 45]); + chars++; + b = Math.floor(b / 45); + } while (b > 0); + + if (chars < 2) { + res.push("0"); + chars++; + } + if (pair.length > 1 && chars < 3) { + res.push("0"); + } + } + + + return res.join(""); + + } + +} + +export default ToBase45; diff --git a/plugins/srktoolbox/src/core/operations/ToBase58.mjs b/plugins/srktoolbox/src/core/operations/ToBase58.mjs new file mode 100644 index 00000000..57da9ee4 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToBase58.mjs @@ -0,0 +1,92 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {ALPHABET_OPTIONS} from "../lib/Base58.mjs"; + +/** + * To Base58 operation + */ +class ToBase58 extends Operation { + + /** + * ToBase58 constructor + */ + constructor() { + super(); + + this.name = "Base58编码"; + this.module = "Default"; + this.description = "Base58(类似于Base64)是把字节数据转换成特定字符组合的编码方式。和Base64的区别是移除了形状相近的易混字符(例如l、I、0和O)来提高可读性。

此操作将原始数据编码成使用ASCII字符的Base64字符串。

例: hello world 编码为 StV1DL6CwTryKyV

Base58常见于加密货币(比特币、Ripple等)。"; + this.infoURL = "https://wikipedia.org/wiki/Base58"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "可用字符", + "type": "editableOption", + "value": ALPHABET_OPTIONS + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + input = new Uint8Array(input); + let alphabet = args[0] || ALPHABET_OPTIONS[0].value, + result = []; + + alphabet = Utils.expandAlphRange(alphabet).join(""); + + if (alphabet.length !== 58 || + [].unique.call(alphabet).length !== 58) { + throw new OperationError("错误:可用字符必须是58个"); + } + + if (input.length === 0) return ""; + + let zeroPrefix = 0; + for (let i = 0; i < input.length && input[i] === 0; i++) { + zeroPrefix++; + } + + input.forEach(function(b) { + let carry = b; + + for (let i = 0; i < result.length; i++) { + carry += result[i] << 8; + result[i] = carry % 58; + carry = (carry / 58) | 0; + } + + while (carry > 0) { + result.push(carry % 58); + carry = (carry / 58) | 0; + } + }); + + result = result.map(function(b) { + return alphabet[b]; + }).reverse().join(""); + + while (zeroPrefix--) { + result = alphabet[0] + result; + } + + return result; + } + +} + +export default ToBase58; diff --git a/plugins/srktoolbox/src/core/operations/ToBase62.mjs b/plugins/srktoolbox/src/core/operations/ToBase62.mjs new file mode 100644 index 00000000..e94c8343 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToBase62.mjs @@ -0,0 +1,64 @@ +/** + * @author tcode2k16 [tcode2k16@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import BigNumber from "bignumber.js"; +import Utils from "../Utils.mjs"; +import {toHexFast} from "../lib/Hex.mjs"; + +/** + * To Base62 operation + */ +class ToBase62 extends Operation { + + /** + * ToBase62 constructor + */ + constructor() { + super(); + + this.name = "Base62编码"; + this.module = "Default"; + this.description = "Base62是把字节数据转换成特定字符组合的编码方式,编码后便于人类阅读,也方便计算机读取。

此操作将原始数据编码成使用ASCII字符的Base62字符串。"; + this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "可用字符", + type: "string", + value: "0-9A-Za-z" + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + input = new Uint8Array(input); + if (input.length < 1) return ""; + + const alphabet = Utils.expandAlphRange(args[0]).join(""); + const BN62 = BigNumber.clone({ ALPHABET: alphabet }); + + input = toHexFast(input).toUpperCase(); + + // Read number in as hex using normal alphabet + const normalized = new BigNumber(input, 16); + // Copy to BigNumber clone that uses the specified Base62 alphabet + const number = new BN62(normalized); + + return number.toString(62); + } + +} + +export default ToBase62; diff --git a/plugins/srktoolbox/src/core/operations/ToBase64.mjs b/plugins/srktoolbox/src/core/operations/ToBase64.mjs new file mode 100644 index 00000000..31e98be7 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToBase64.mjs @@ -0,0 +1,79 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {toBase64, ALPHABET_OPTIONS} from "../lib/Base64.mjs"; + +/** + * To Base64 operation + */ +class ToBase64 extends Operation { + + /** + * ToBase64 constructor + */ + constructor() { + super(); + + this.name = "Base64编码"; + this.module = "Default"; + this.description = "Base64是把字节数据转换成特定字符组合的编码方式,编码后便于人类阅读,也方便计算机读取。

此操作将原始数据编码成使用ASCII字符的Base64字符串。

例: hello 编码成 aGVsbG8="; + this.infoURL = "https://wikipedia.org/wiki/Base64"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "可用字符", + type: "editableOption", + value: ALPHABET_OPTIONS + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const alphabet = args[0]; + return toBase64(input, alphabet); + } + + /** + * Highlight to Base64 + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + pos[0].start = Math.floor(pos[0].start / 3 * 4); + pos[0].end = Math.ceil(pos[0].end / 3 * 4); + return pos; + } + + /** + * Highlight from Base64 + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + pos[0].start = Math.ceil(pos[0].start / 4 * 3); + pos[0].end = Math.floor(pos[0].end / 4 * 3); + return pos; + } +} + +export default ToBase64; diff --git a/plugins/srktoolbox/src/core/operations/ToBase85.mjs b/plugins/srktoolbox/src/core/operations/ToBase85.mjs new file mode 100644 index 00000000..23bf6c5c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToBase85.mjs @@ -0,0 +1,96 @@ +/** + * @author PenguinGeorge [george@penguingeorge.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import {alphabetName, ALPHABET_OPTIONS} from "../lib/Base85.mjs"; + +/** + * To Base85 operation + */ +class ToBase85 extends Operation { + + /** + * To Base85 constructor + */ + constructor() { + super(); + + this.name = "Base85编码"; + this.module = "Default"; + this.description = "Base85(也叫Ascii85)是把字节数据转换成特定字符组合的编码方式。通常比Base64效率更高。

此操作将原始数据编码成使用ASCII字符的Base64字符串。字符表可选,带有预设。

例如:hello world 编码成 BOu!rD]j7BEbo7

Base85在Adobe的PostScript和PDF格式中较为常见。

选项
可用字符
  • 标准 - 标准字母表,又叫Ascii85
  • Z85 (ZeroMQ) - 不带有引号和反斜杠之类,适用于生成字符串。
  • IPv6 - 适合编码IPV6地址的变体 (RFC 1924)
包括分隔符
在数据开头和结尾添加 '<~' 和 '~>'。Adobe的Base85一般采用此格式。"; + this.infoURL = "https://wikipedia.org/wiki/Ascii85"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "可用字符", + type: "editableOption", + value: ALPHABET_OPTIONS + }, + { + name: "包括分隔符", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + input = new Uint8Array(input); + const alphabet = Utils.expandAlphRange(args[0]).join(""), + encoding = alphabetName(alphabet), + includeDelim = args[1]; + let result = ""; + + if (alphabet.length !== 85 || + [].unique.call(alphabet).length !== 85) { + throw new OperationError("错误:字符表必须包含85个字符"); + } + + if (input.length === 0) return ""; + + let block; + for (let i = 0; i < input.length; i += 4) { + block = ( + ((input[i]) << 24) + + ((input[i + 1] || 0) << 16) + + ((input[i + 2] || 0) << 8) + + ((input[i + 3] || 0)) + ) >>> 0; + + if (encoding !== "标准" || block > 0) { + let digits = []; + for (let j = 0; j < 5; j++) { + digits.push(block % 85); + block = Math.floor(block / 85); + } + + digits = digits.reverse(); + + if (input.length < i + 4) { + digits.splice(input.length - (i + 4), 4); + } + + result += digits.map(digit => alphabet[digit]).join(""); + } else { + result += (encoding === "标准") ? "z" : null; + } + } + + return includeDelim ? `<~${result}~>` : result; + } +} + +export default ToBase85; diff --git a/plugins/srktoolbox/src/core/operations/ToBase92.mjs b/plugins/srktoolbox/src/core/operations/ToBase92.mjs new file mode 100644 index 00000000..d1ed50d8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToBase92.mjs @@ -0,0 +1,69 @@ +/** + * @author sg5506844 [sg5506844@gmail.com] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import { base92Chr } from "../lib/Base92.mjs"; +import Operation from "../Operation.mjs"; + +/** + * To Base92 operation + */ +class ToBase92 extends Operation { + /** + * ToBase92 constructor + */ + constructor() { + super(); + + this.name = "Base92编码"; + this.module = "Default"; + this.description = "Base92是把字节数据转换成特定字符组合的编码方式,编码后便于人类阅读,也方便计算机读取。"; + this.infoURL = "https://wikipedia.org/wiki/List_of_numeral_systems"; + this.inputType = "string"; + this.outputType = "byteArray"; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const res = []; + let bitString = ""; + + while (input.length > 0) { + while (bitString.length < 13 && input.length > 0) { + bitString += input[0].charCodeAt(0).toString(2).padStart(8, "0"); + input = input.slice(1); + } + if (bitString.length < 13) + break; + const i = parseInt(bitString.slice(0, 13), 2); + res.push(base92Chr(Math.floor(i / 91))); + res.push(base92Chr(i % 91)); + bitString = bitString.slice(13); + } + + if (bitString.length > 0) { + if (bitString.length < 7) { + bitString = bitString.padEnd(6, "0"); + res.push(base92Chr(parseInt(bitString, 2))); + } else { + bitString = bitString.padEnd(13, "0"); + const i = parseInt(bitString.slice(0, 13), 2); + res.push(base92Chr(Math.floor(i / 91))); + res.push(base92Chr(i % 91)); + } + } + + return res; + + } +} + +export default ToBase92; diff --git a/plugins/srktoolbox/src/core/operations/ToBech32.mjs b/plugins/srktoolbox/src/core/operations/ToBech32.mjs new file mode 100644 index 00000000..8d6d56ba --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToBech32.mjs @@ -0,0 +1,94 @@ +/** + * @author Medjedtxm + * @copyright Crown Copyright 2025 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import { encode } from "../lib/Bech32.mjs"; +import { fromHex } from "../lib/Hex.mjs"; + +/** + * To Bech32 operation + */ +class ToBech32 extends Operation { + + /** + * ToBech32 constructor + */ + constructor() { + super(); + + this.name = "Bech32编码"; + this.module = "Default"; + this.description = "Bech32 是一种编码方案,主要应用于比特币隔离见证地址(BIP-0173)。它采用 32 字符字母表,其中排除了易混淆的字符(1、b、i、o),并包含用于错误检测的校验和。

Bech32m(BIP-0350)是其更新版本,用于比特币 Taproot 地址。

自动检测功能会先尝试以 Bech32 格式解码,若校验和失败则尝试 Bech32m 格式。

输出格式选项允许您查看人类可读部分(HRP)及解码后的数据。"; + this.infoURL = "https://wikipedia.org/wiki/Bech32"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "人类可读部分(HRP)", + "type": "string", + "value": "bc" + }, + { + "name": "编码方式", + "type": "option", + "value": ["Bech32", "Bech32m"] + }, + { + "name": "输入格式", + "type": "option", + "value": ["原始字节", "十六进制"] + }, + { + "name": "模式", + "type": "option", + "value": ["通用", "Bitcoin SegWit"] + }, + { + "name": "见证版本(Witness Version)", + "type": "number", + "value": 0, + "hint": "SegWit 隔离见证版本 (0-16)。只用于比特币隔离见证(Bitcoin SegWit)模式。" + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const hrp = args[0]; + const encoding = args[1]; + const inputFormat = args[2]; + const mode = args[3]; + const witnessVersion = args[4]; + + let inputArray; + if (inputFormat === "十六进制") { + // Convert hex string to bytes + const hexStr = new TextDecoder().decode(new Uint8Array(input)).replace(/\s/g, ""); + inputArray = fromHex(hexStr); + } else { + inputArray = new Uint8Array(input); + } + + if (mode === "Bitcoin SegWit") { + // Prepend witness version to the input data + const withVersion = new Uint8Array(inputArray.length + 1); + withVersion[0] = witnessVersion; + withVersion.set(inputArray, 1); + return encode(hrp, withVersion, encoding, true); + } + + return encode(hrp, inputArray, encoding, false); + } + +} + +export default ToBech32; diff --git a/plugins/srktoolbox/src/core/operations/ToBinary.mjs b/plugins/srktoolbox/src/core/operations/ToBinary.mjs new file mode 100644 index 00000000..fbbf98ae --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToBinary.mjs @@ -0,0 +1,90 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {BIN_DELIM_OPTIONS} from "../lib/Delim.mjs"; +import {toBinary} from "../lib/Binary.mjs"; + +/** + * To Binary operation + */ +class ToBinary extends Operation { + + /** + * ToBinary constructor + */ + constructor() { + super(); + + this.name = "字符转二进制"; + this.module = "Default"; + this.description = "将输入字符串转换为对应的二进制表示(使用给定的分隔符)。

Hi 编码为 01001000 01101001"; + this.infoURL = "https://wikipedia.org/wiki/Binary_code"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": BIN_DELIM_OPTIONS + }, + { + "name": "字节长度", + "type": "number", + "value": 8 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + input = new Uint8Array(input); + const padding = args[1] ? args[1] : 8; + return toBinary(input, args[0], padding); + } + + /** + * Highlight To Binary + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + const delim = Utils.charRep(args[0] || "空格"); + pos[0].start = pos[0].start * (8 + delim.length); + pos[0].end = pos[0].end * (8 + delim.length) - delim.length; + return pos; + } + + /** + * Highlight To Binary in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + const delim = Utils.charRep(args[0] || "空格"); + pos[0].start = pos[0].start === 0 ? 0 : Math.floor(pos[0].start / (8 + delim.length)); + pos[0].end = pos[0].end === 0 ? 0 : Math.ceil(pos[0].end / (8 + delim.length)); + return pos; + } + +} + +export default ToBinary; diff --git a/plugins/srktoolbox/src/core/operations/ToBraille.mjs b/plugins/srktoolbox/src/core/operations/ToBraille.mjs new file mode 100644 index 00000000..c84f5815 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToBraille.mjs @@ -0,0 +1,72 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {BRAILLE_LOOKUP} from "../lib/Braille.mjs"; + +/** + * To Braille operation + */ +class ToBraille extends Operation { + + /** + * ToBraille constructor + */ + constructor() { + super(); + + this.name = "盲文编码"; + this.module = "Default"; + this.description = "把文本编码为六点盲文符号。"; + this.infoURL = "https://wikipedia.org/wiki/Braille"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return input.split("").map(c => { + const idx = BRAILLE_LOOKUP.ascii.indexOf(c.toUpperCase()); + return idx < 0 ? c : BRAILLE_LOOKUP.dot6[idx]; + }).join(""); + } + + /** + * Highlight To Braille + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight To Braille in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default ToBraille; diff --git a/plugins/srktoolbox/src/core/operations/ToCNNumberUpperCase.mjs b/plugins/srktoolbox/src/core/operations/ToCNNumberUpperCase.mjs new file mode 100644 index 00000000..e0a96c94 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToCNNumberUpperCase.mjs @@ -0,0 +1,86 @@ +/** + * @author Raka-loah [i@lotc.cc] + * @copyright Crown Copyright 2022 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; + + +/** + * To CN Number Upper Case operation + */ +class ToCNNumberUpperCase extends Operation { + + /** + * ToCNNumberUpperCase constructor + */ + constructor() { + super(); + + this.name = "转换为大写数字"; + this.module = "Default"; + this.description = "把简体中文汉字数字转换为对应的大写形式。

例如: 一十一万四千五百一十四 转换为 壹拾壹万肆仟伍佰壹拾肆。"; + this.infoURL = "https://zh.wikipedia.org/wiki/%E5%A4%A7%E5%86%99%E6%95%B0%E5%AD%97"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const numberDict = { + "一": "壹", + "二": "贰", + "三": "叁", + "四": "肆", + "五": "伍", + "六": "陆", + "七": "柒", + "八": "捌", + "九": "玖", + "十": "拾", + "〇": "零", + "百": "佰", + "千": "仟" + }; + + const upperStr = input.split("").map(ch => numberDict[ch] ?? ch).join(""); + + return upperStr; + } + + /** + * Highlight To CN Number Upper Case + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight To CN Number Upper Case in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default ToCNNumberUpperCase; diff --git a/plugins/srktoolbox/src/core/operations/ToCamelCase.mjs b/plugins/srktoolbox/src/core/operations/ToCamelCase.mjs new file mode 100644 index 00000000..631ff80b --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToCamelCase.mjs @@ -0,0 +1,56 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import camelCase from "lodash/camelCase.js"; +import Operation from "../Operation.mjs"; +import { replaceVariableNames } from "../lib/Code.mjs"; + +/** + * To Camel case operation + */ +class ToCamelCase extends Operation { + + /** + * ToCamelCase constructor + */ + constructor() { + super(); + + this.name = "转换为Camel case"; + this.module = "Code"; + this.description = "将输入字符串转换为camel case。\n

\nCamel case是除了单词边界之外的字母全小写的格式。\n

\n例如: thisIsCamelCase\n

\n勾选“尝试识别上下文”后此操作将尝试只转换函数和变量名。"; + this.infoURL = "https://wikipedia.org/wiki/Camel_case"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "尝试识别上下文", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const smart = args[0]; + + if (smart) { + return replaceVariableNames(input, camelCase); + } else { + return camelCase(input); + } + } + +} + +export default ToCamelCase; diff --git a/plugins/srktoolbox/src/core/operations/ToCaseInsensitiveRegex.mjs b/plugins/srktoolbox/src/core/operations/ToCaseInsensitiveRegex.mjs new file mode 100644 index 00000000..c94f708b --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToCaseInsensitiveRegex.mjs @@ -0,0 +1,97 @@ +/** + * @author masq [github.cyberchef@masq.cc] + * @author n1073645 + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * To Case Insensitive Regex operation + */ +class ToCaseInsensitiveRegex extends Operation { + + /** + * ToCaseInsensitiveRegex constructor + */ + constructor() { + super(); + + this.name = "转换为大小写不敏感正则"; + this.module = "Default"; + this.description = "把大小写敏感正则字符串转换为大小写不敏感形式,用于无法使用正则i选项的场合。

例如:Mozilla/[0-9].[0-9] .* 转换为 [mM][oO][zZ][iI][lL][lL][aA]/[0-9].[0-9] .*"; + this.infoURL = "https://wikipedia.org/wiki/Regular_expression"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + + /** + * Simulates look behind behaviour since javascript doesn't support it. + * + * @param {string} input + * @returns {string} + */ + function preProcess(input) { + let result = ""; + for (let i = 0; i < input.length; i++) { + const temp = input.charAt(i); + if (temp.match(/[a-zA-Z]/g) && (input.charAt(i-1) !== "-") && (input.charAt(i+1) !== "-")) + result += "[" + temp.toLowerCase() + temp.toUpperCase() + "]"; + else + result += temp; + } + return result; + } + + try { + RegExp(input); + } catch (error) { + throw new OperationError("无效的正则表达式(请注意此版本的Node不支持正则的后行断言)。"); + } + + // Example: [test] -> [[tT][eE][sS][tT]] + return preProcess(input) + + // Example: [A-Z] -> [A-Za-z] + .replace(/([A-Z]-[A-Z]|[a-z]-[a-z])/g, m => `${m[0].toUpperCase()}-${m[2].toUpperCase()}${m[0].toLowerCase()}-${m[2].toLowerCase()}`) + + // Example: [H-d] -> [A-DH-dh-z] + .replace(/[A-Z]-[a-z]/g, m => `A-${m[2].toUpperCase()}${m}${m[0].toLowerCase()}-z`) + + // Example: [!-D] -> [!-Da-d] + .replace(/\\?[ -@]-[A-Z]/g, m => `${m}a-${m[2].toLowerCase()}`) + + // Example: [%-^] -> [%-^a-z] + .replace(/\\?[ -@]-\\?[[-`]/g, m => `${m}a-z`) + + // Example: [K-`] -> [K-`k-z] + .replace(/[A-Z]-\\?[[-`]/g, m => `${m}${m[0].toLowerCase()}-z`) + + // Example: [[-}] -> [[-}A-Z] + .replace(/\\?[[-`]-\\?[{-~]/g, m => `${m}A-Z`) + + // Example: [b-}] -> [b-}B-Z] + .replace(/[a-z]-\\?[{-~]/g, m => `${m}${m[0].toUpperCase()}-Z`) + + // Example: [<-j] -> [<-z] + .replace(/\\?[ -@]-[a-z]/g, m => `${m[0]}-z`) + + // Example: [^-j] -> [A-J^-j] + .replace(/\\?[[-`]-[a-z]/g, m => `A-${m[2].toUpperCase()}${m}`); + + } +} + +export default ToCaseInsensitiveRegex; diff --git a/plugins/srktoolbox/src/core/operations/ToCharcode.mjs b/plugins/srktoolbox/src/core/operations/ToCharcode.mjs new file mode 100644 index 00000000..f269b6dc --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToCharcode.mjs @@ -0,0 +1,89 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import { DELIM_OPTIONS } from "../lib/Delim.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; + +/** + * To Charcode operation + */ +class ToCharcode extends Operation { + + /** + * ToCharcode constructor + */ + constructor() { + super(); + + this.name = "转换为字符码"; + this.module = "Default"; + this.description = "把字符转换成对应的Unicode字符码

例: Γειά σου 编码为 0393 03b5 03b9 03ac 20 03c3 03bf 03c5"; + this.infoURL = "https://wikipedia.org/wiki/Plane_(Unicode)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": DELIM_OPTIONS + }, + { + "name": "进制", + "type": "number", + "value": 16 + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + * + * @throws {OperationError} if base argument out of range + */ + run(input, args) { + const delim = Utils.charRep(args[0] || "空格"), + base = args[1]; + let output = "", + padding, + ordinal; + + if (base < 2 || base > 36) { + throw new OperationError("错误:进制必须在2~36之间"); + } + + const charcode = Utils.strToCharcode(input); + for (let i = 0; i < charcode.length; i++) { + ordinal = charcode[i]; + + if (base === 16) { + if (ordinal < 256) padding = 2; + else if (ordinal < 65536) padding = 4; + else if (ordinal < 16777216) padding = 6; + else if (ordinal < 4294967296) padding = 8; + else padding = 2; + + if (padding > 2 && isWorkerEnvironment()) self.setOption("attemptHighlight", false); + + output += Utils.hex(ordinal, padding) + delim; + } else { + if (isWorkerEnvironment()) self.setOption("attemptHighlight", false); + output += ordinal.toString(base) + delim; + } + } + + return output.slice(0, -delim.length); + } + +} + +export default ToCharcode; diff --git a/plugins/srktoolbox/src/core/operations/ToDecimal.mjs b/plugins/srktoolbox/src/core/operations/ToDecimal.mjs new file mode 100644 index 00000000..26f762bc --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToDecimal.mjs @@ -0,0 +1,62 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {DELIM_OPTIONS} from "../lib/Delim.mjs"; + + +/** + * To Decimal operation + */ +class ToDecimal extends Operation { + + /** + * ToDecimal constructor + */ + constructor() { + super(); + + this.name = "字符转十进制"; + this.module = "Default"; + this.description = "将输入字符串转换为对应的十进制表示(使用给定的分隔符)。

例: Hello 编码为 72 101 108 108 111"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": DELIM_OPTIONS + }, + { + "name": "支持带符号数值(signed int)", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0]), + signed = args[1]; + if (signed) { + input = new Int8Array(input); + } else { + input = new Uint8Array(input); + } + return input.join(delim); + } + +} + +export default ToDecimal; diff --git a/plugins/srktoolbox/src/core/operations/ToFloat.mjs b/plugins/srktoolbox/src/core/operations/ToFloat.mjs new file mode 100644 index 00000000..9ed769dc --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToFloat.mjs @@ -0,0 +1,82 @@ +/** + * @author tcode2k16 [tcode2k16@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import ieee754 from "ieee754"; +import {DELIM_OPTIONS} from "../lib/Delim.mjs"; + +/** + * To Float operation + */ +class ToFloat extends Operation { + + /** + * ToFloat constructor + */ + constructor() { + super(); + + this.name = "字符转浮点数"; + this.module = "Default"; + this.description = "转换为 IEEE754 浮点数"; + this.infoURL = "https://wikipedia.org/wiki/IEEE_754"; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = [ + { + "name": "端序", + "type": "option", + "value": [ + "大端序", + "小端序" + ] + }, + { + "name": "类型", + "type": "option", + "value": [ + "Float (4字节)", + "Double (8字节)" + ] + }, + { + "name": "分隔符", + "type": "option", + "value": DELIM_OPTIONS + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [endianness, size, delimiterName] = args; + const delim = Utils.charRep(delimiterName || "空格"); + const byteSize = size === "Double (8字节)" ? 8 : 4; + const isLE = endianness === "小端序"; + const mLen = byteSize === 4 ? 23 : 52; + + if (input.length % byteSize !== 0) { + throw new OperationError(`输入长度不是 ${byteSize} 字节的倍数`); + } + + const output = []; + for (let i = 0; i < input.length; i+=byteSize) { + output.push(ieee754.read(input, i, isLE, mLen, byteSize)); + } + return output.join(delim); + } + +} + +export default ToFloat; diff --git a/plugins/srktoolbox/src/core/operations/ToHTMLEntity.mjs b/plugins/srktoolbox/src/core/operations/ToHTMLEntity.mjs new file mode 100644 index 00000000..f0be1e2c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToHTMLEntity.mjs @@ -0,0 +1,1514 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * To HTML Entity operation + */ +class ToHTMLEntity extends Operation { + + /** + * ToHTMLEntity constructor + */ + constructor() { + super(); + + this.name = "HTML实体编码"; + this.module = "Encodings"; + this.description = "把字符编码为HTML实体

例: & 编码为 &amp;"; + this.infoURL = "https://wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "转换所有字符", + "type": "boolean", + "value": false + }, + { + "name": "转换成", + "type": "option", + "value": ["名称", "十进制", "十六进制"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const convertAll = args[0], + numeric = args[1] === "十进制", + hexa = args[1] === "十六进制"; + + const charcodes = Utils.strToCharcode(input); + let output = ""; + + for (let i = 0; i < charcodes.length; i++) { + if (convertAll && numeric) { + output += "&#" + charcodes[i] + ";"; + } else if (convertAll && hexa) { + output += "&#x" + Utils.hex(charcodes[i]) + ";"; + } else if (convertAll) { + output += byteToEntity[charcodes[i]] || "&#" + charcodes[i] + ";"; + } else if (numeric) { + if (charcodes[i] > 255 || charcodes[i] in byteToEntity) { + output += "&#" + charcodes[i] + ";"; + } else { + output += Utils.chr(charcodes[i]); + } + } else if (hexa) { + if (charcodes[i] > 255 || charcodes[i] in byteToEntity) { + output += "&#x" + Utils.hex(charcodes[i]) + ";"; + } else { + output += Utils.chr(charcodes[i]); + } + } else { + output += byteToEntity[charcodes[i]] || ( + charcodes[i] > 255 ? + "&#" + charcodes[i] + ";" : + Utils.chr(charcodes[i]) + ); + } + } + return output; + } + +} + +/** + * Lookup table to translate byte values to their HTML entity codes. + */ +const byteToEntity = { + 9: " ", + 10: " ", + 33: "!", + 34: """, + 35: "#", + 36: "$", + 37: "%", + 38: "&", + 39: "'", + 40: "(", + 41: ")", + 42: "*", + 43: "+", + 44: ",", + 46: ".", + 47: "/", + 58: ":", + 59: ";", + 60: "<", + 61: "=", + 62: ">", + 63: "?", + 64: "@", + 91: "[", + 92: "\", + 93: "]", + 94: "^", + 95: "_", + 96: "`", + 123: "{", + 124: "|", + 125: "}", + 160: " ", + 161: "¡", + 162: "¢", + 163: "£", + 164: "¤", + 165: "¥", + 166: "¦", + 167: "§", + 168: "¨", + 169: "©", + 170: "ª", + 171: "«", + 172: "¬", + 173: "­", + 174: "®", + 175: "¯", + 176: "°", + 177: "±", + 178: "²", + 179: "³", + 180: "´", + 181: "µ", + 182: "¶", + 183: "·", + 184: "¸", + 185: "¹", + 186: "º", + 187: "»", + 188: "¼", + 189: "½", + 190: "¾", + 191: "¿", + 192: "À", + 193: "Á", + 194: "Â", + 195: "Ã", + 196: "Ä", + 197: "Å", + 198: "Æ", + 199: "Ç", + 200: "È", + 201: "É", + 202: "Ê", + 203: "Ë", + 204: "Ì", + 205: "Í", + 206: "Î", + 207: "Ï", + 208: "Ð", + 209: "Ñ", + 210: "Ò", + 211: "Ó", + 212: "Ô", + 213: "Õ", + 214: "Ö", + 215: "×", + 216: "Ø", + 217: "Ù", + 218: "Ú", + 219: "Û", + 220: "Ü", + 221: "Ý", + 222: "Þ", + 223: "ß", + 224: "à", + 225: "á", + 226: "â", + 227: "ã", + 228: "ä", + 229: "å", + 230: "æ", + 231: "ç", + 232: "è", + 233: "é", + 234: "ê", + 235: "ë", + 236: "ì", + 237: "í", + 238: "î", + 239: "ï", + 240: "ð", + 241: "ñ", + 242: "ò", + 243: "ó", + 244: "ô", + 245: "õ", + 246: "ö", + 247: "÷", + 248: "ø", + 249: "ù", + 250: "ú", + 251: "û", + 252: "ü", + 253: "ý", + 254: "þ", + 255: "ÿ", + 256: "Ā", + 257: "ā", + 258: "Ă", + 259: "ă", + 260: "Ą", + 261: "ą", + 262: "Ć", + 263: "ć", + 264: "Ĉ", + 265: "ĉ", + 266: "Ċ", + 267: "ċ", + 268: "Č", + 269: "č", + 270: "Ď", + 271: "ď", + 272: "Đ", + 273: "đ", + 274: "Ē", + 275: "ē", + 278: "Ė", + 279: "ė", + 280: "Ę", + 281: "ę", + 282: "Ě", + 283: "ě", + 284: "Ĝ", + 285: "ĝ", + 286: "Ğ", + 287: "ğ", + 288: "Ġ", + 289: "ġ", + 290: "Ģ", + 292: "Ĥ", + 293: "ĥ", + 294: "Ħ", + 295: "ħ", + 296: "Ĩ", + 297: "ĩ", + 298: "Ī", + 299: "ī", + 302: "Į", + 303: "į", + 304: "İ", + 305: "ı", + 306: "IJ", + 307: "ij", + 308: "Ĵ", + 309: "ĵ", + 310: "Ķ", + 311: "ķ", + 312: "ĸ", + 313: "Ĺ", + 314: "ĺ", + 315: "Ļ", + 316: "ļ", + 317: "Ľ", + 318: "ľ", + 319: "Ŀ", + 320: "ŀ", + 321: "Ł", + 322: "ł", + 323: "Ń", + 324: "ń", + 325: "Ņ", + 326: "ņ", + 327: "Ň", + 328: "ň", + 329: "ʼn", + 330: "Ŋ", + 331: "ŋ", + 332: "Ō", + 333: "ō", + 336: "Ő", + 337: "ő", + 338: "Œ", + 339: "œ", + 340: "Ŕ", + 341: "ŕ", + 342: "Ŗ", + 343: "ŗ", + 344: "Ř", + 345: "ř", + 346: "Ś", + 347: "ś", + 348: "Ŝ", + 349: "ŝ", + 350: "Ş", + 351: "ş", + 352: "Š", + 353: "š", + 354: "Ţ", + 355: "ţ", + 356: "Ť", + 357: "ť", + 358: "Ŧ", + 359: "ŧ", + 360: "Ũ", + 361: "ũ", + 362: "Ū", + 363: "ū", + 364: "Ŭ", + 365: "ŭ", + 366: "Ů", + 367: "ů", + 368: "Ű", + 369: "ű", + 370: "Ų", + 371: "ų", + 372: "Ŵ", + 373: "ŵ", + 374: "Ŷ", + 375: "ŷ", + 376: "Ÿ", + 377: "Ź", + 378: "ź", + 379: "Ż", + 380: "ż", + 381: "Ž", + 382: "ž", + 402: "ƒ", + 437: "Ƶ", + 501: "ǵ", + 567: "ȷ", + 710: "ˆ", + 711: "ˇ", + 728: "˘", + 729: "˙", + 730: "˚", + 731: "˛", + 732: "˜", + 785: "̑", + 818: "_", + 913: "Α", + 914: "Β", + 915: "Γ", + 916: "Δ", + 917: "Ε", + 918: "Ζ", + 919: "Η", + 920: "Θ", + 921: "Ι", + 922: "Κ", + 923: "Λ", + 924: "Μ", + 925: "Ν", + 926: "Ξ", + 927: "Ο", + 928: "Π", + 929: "Ρ", + 931: "Σ", + 932: "Τ", + 933: "Υ", + 934: "Φ", + 935: "Χ", + 936: "Ψ", + 937: "Ω", + 945: "α", + 946: "β", + 947: "γ", + 948: "δ", + 949: "ε", + 950: "ζ", + 951: "η", + 952: "θ", + 953: "ι", + 954: "κ", + 955: "λ", + 956: "μ", + 957: "ν", + 958: "ξ", + 959: "ο", + 960: "π", + 961: "ρ", + 962: "ς", + 963: "σ", + 964: "τ", + 965: "υ", + 966: "φ", + 967: "χ", + 968: "ψ", + 969: "ω", + 977: "ϑ", + 978: "ϒ", + 981: "ϕ", + 982: "ϖ", + 988: "Ϝ", + 989: "ϝ", + 1008: "ϰ", + 1009: "ϱ", + 1013: "ε,", + 1014: "϶", + 1025: "Ё", + 1026: "Ђ", + 1027: "Ѓ", + 1028: "Є", + 1029: "Ѕ", + 1030: "І", + 1031: "Ї", + 1032: "Ј", + 1033: "Љ", + 1034: "Њ", + 1035: "Ћ", + 1036: "Ќ", + 1038: "Ў", + 1039: "Џ", + 1040: "А", + 1041: "Б", + 1042: "В", + 1043: "Г", + 1044: "Д", + 1045: "Е", + 1046: "Ж", + 1047: "З", + 1048: "И", + 1049: "Й", + 1050: "К", + 1051: "Л", + 1052: "М", + 1053: "Н", + 1054: "О", + 1055: "П", + 1056: "Р", + 1057: "С", + 1058: "Т", + 1059: "У", + 1060: "Ф", + 1061: "Х", + 1062: "Ц", + 1063: "Ч", + 1064: "Ш", + 1065: "Щ", + 1066: "Ъ", + 1067: "Ы", + 1068: "Ь", + 1069: "Э", + 1070: "Ю", + 1071: "Я", + 1072: "а", + 1073: "б", + 1074: "в", + 1075: "г", + 1076: "д", + 1077: "е", + 1078: "ж", + 1079: "з", + 1080: "и", + 1081: "й", + 1082: "к", + 1083: "л", + 1084: "м", + 1085: "н", + 1086: "о", + 1087: "п", + 1088: "р", + 1089: "с", + 1090: "т", + 1091: "у", + 1092: "ф", + 1093: "х", + 1094: "ц", + 1095: "ч", + 1096: "ш", + 1097: "щ", + 1098: "ъ", + 1099: "ы", + 1100: "ь", + 1101: "э", + 1102: "ю", + 1103: "я", + 1105: "ё", + 1106: "ђ", + 1107: "ѓ", + 1108: "є", + 1109: "ѕ", + 1110: "і", + 1111: "ї", + 1112: "ј", + 1113: "љ", + 1114: "њ", + 1115: "ћ", + 1116: "ќ", + 1118: "ў", + 1119: "џ", + 8194: " ", + 8195: " ", + 8196: " ", + 8197: " ", + 8199: " ", + 8200: " ", + 8201: " ", + 8202: " ", + 8203: "​", + 8204: "‌", + 8205: "‍", + 8206: "‎", + 8207: "‏", + 8208: "‐", + 8211: "–", + 8212: "—", + 8213: "―", + 8214: "‖", + 8216: "‘", + 8217: "’", + 8218: "‚", + 8220: "“", + 8221: "”", + 8222: "„", + 8224: "†", + 8225: "‡", + 8226: "•", + 8229: "‥", + 8230: "…", + 8240: "‰", + 8241: "‱", + 8242: "′", + 8243: "″", + 8244: "‴", + 8245: "‵", + 8249: "‹", + 8250: "›", + 8254: "‾", + 8257: "⁁", + 8259: "⁃", + 8260: "⁄", + 8271: "⁏", + 8279: "⁗", + 8287: " ", + 8288: "⁠", + 8289: "⁡", + 8290: "⁢", + 8291: "⁣", + 8364: "€", + 8411: "⃛", + 8412: "⃜", + 8450: "ℂ", + 8453: "℅", + 8458: "ℊ", + 8459: "ℋ", + 8460: "ℌ", + 8461: "ℍ", + 8462: "ℎ", + 8463: "ℏ", + 8464: "ℐ", + 8465: "ℑ", + 8466: "ℒ", + 8467: "ℓ", + 8469: "ℕ", + 8470: "№", + 8471: "℗", + 8472: "℘", + 8473: "ℙ", + 8474: "ℚ", + 8475: "ℛ", + 8476: "ℜ", + 8477: "ℝ", + 8478: "℞", + 8482: "™", + 8484: "ℤ", + 8486: "Ω", + 8487: "℧", + 8488: "ℨ", + 8489: "℩", + 8491: "Å", + 8492: "ℬ", + 8493: "ℭ", + 8495: "ℯ", + 8496: "ℰ", + 8497: "ℱ", + 8499: "ℳ", + 8500: "ℴ", + 8501: "ℵ", + 8502: "ℶ", + 8503: "ℷ", + 8504: "ℸ", + 8517: "ⅅ", + 8518: "ⅆ", + 8519: "ⅇ", + 8520: "ⅈ", + 8531: "⅓", + 8532: "⅔", + 8533: "⅕", + 8534: "⅖", + 8535: "⅗", + 8536: "⅘", + 8537: "⅙", + 8538: "⅚", + 8539: "⅛", + 8540: "⅜", + 8541: "⅝", + 8542: "⅞", + 8592: "←", + 8593: "↑", + 8594: "→", + 8595: "↓", + 8596: "↔", + 8597: "↕", + 8598: "↖", + 8599: "↗", + 8600: "↘", + 8601: "↙", + 8602: "↚", + 8603: "↛", + 8605: "↝", + 8606: "↞", + 8607: "↟", + 8608: "↠", + 8609: "↡", + 8610: "↢", + 8611: "↣", + 8612: "↤", + 8613: "↥", + 8614: "↦", + 8615: "↧", + 8617: "↩", + 8618: "↪", + 8619: "↫", + 8620: "↬", + 8621: "↭", + 8622: "↮", + 8624: "↰", + 8625: "↱", + 8626: "↲", + 8627: "↳", + 8629: "↵", + 8630: "↶", + 8631: "↷", + 8634: "↺", + 8635: "↻", + 8636: "↼", + 8637: "↽", + 8638: "↾", + 8639: "↿", + 8640: "⇀", + 8641: "⇁", + 8642: "⇂", + 8643: "⇃", + 8644: "⇄", + 8645: "⇅", + 8646: "⇆", + 8647: "⇇", + 8648: "⇈", + 8649: "⇉", + 8650: "⇊", + 8651: "⇋", + 8652: "⇌;", + 8653: "⇍", + 8654: "⇎", + 8655: "⇏", + 8656: "⇐", + 8657: "⇑", + 8658: "⇒", + 8659: "⇓", + 8660: "⇔", + 8661: "⇕", + 8662: "⇖", + 8663: "⇗", + 8664: "⇘", + 8665: "⇙", + 8666: "⇚", + 8667: "⇛", + 8669: "⇝", + 8676: "⇤", + 8677: "⇥", + 8693: "⇵", + 8701: "⇽", + 8702: "⇾", + 8703: "⇿", + 8704: "∀", + 8705: "∁", + 8706: "∂", + 8707: "∃", + 8708: "∄", + 8709: "∅", + 8711: "∇", + 8712: "∈", + 8713: "∉", + 8715: "∋", + 8716: "∌", + 8719: "∏", + 8720: "∐", + 8721: "∑", + 8722: "−", + 8723: "∓", + 8724: "∔", + 8726: "∖", + 8727: "∗", + 8728: "∘", + 8730: "√", + 8733: "∝", + 8734: "∞", + 8735: "∟", + 8736: "∠", + 8737: "∡", + 8738: "∢", + 8739: "∣", + 8740: "∤", + 8741: "∥", + 8742: "∦", + 8743: "∧", + 8744: "∨", + 8745: "∩", + 8746: "∪", + 8747: "∫", + 8748: "∬", + 8749: "∭", + 8750: "∮", + 8751: "∯", + 8752: "∰", + 8753: "∱", + 8754: "∲", + 8755: "∳", + 8756: "∴", + 8757: "∵", + 8758: "∶", + 8759: "∷", + 8760: "∸", + 8762: "∺", + 8763: "∻", + 8764: "∼", + 8765: "∽", + 8766: "∾", + 8767: "∿", + 8768: "≀", + 8769: "≁", + 8770: "≂", + 8771: "≃", + 8772: "≄", + 8773: "≅", + 8774: "≆", + 8775: "≇", + 8776: "≈", + 8777: "≉", + 8778: "≊", + 8779: "≋", + 8780: "≌", + 8781: "≍", + 8782: "≎", + 8783: "≏", + 8784: "≐", + 8785: "≑", + 8786: "≒", + 8787: "≓", + 8788: "≔", + 8789: "≕", + 8790: "≖", + 8791: "≗", + 8793: "≙", + 8794: "≚", + 8796: "≜", + 8799: "≟", + 8800: "≠", + 8801: "≡", + 8802: "≢", + 8804: "≤", + 8805: "≥", + 8806: "≦", + 8807: "≧", + 8808: "≨", + 8809: "≩", + 8810: "≪", + 8811: "≫", + 8812: "≬", + 8813: "≭", + 8814: "≮", + 8815: "≯", + 8816: "≰", + 8817: "≱;", + 8818: "≲", + 8819: "≳", + 8820: "≴", + 8821: "≵", + 8822: "≶", + 8823: "≷", + 8824: "≸", + 8825: "≹", + 8826: "≺", + 8827: "≻", + 8828: "≼", + 8829: "≽", + 8830: "≾", + 8831: "≿", + 8832: "⊀", + 8833: "⊁", + 8834: "⊂", + 8835: "⊃", + 8836: "⊄", + 8837: "⊅", + 8838: "⊆", + 8839: "⊇", + 8840: "⊈", + 8841: "⊉", + 8842: "⊊", + 8843: "⊋", + 8845: "⊍", + 8846: "⊎", + 8847: "⊏", + 8848: "⊐", + 8849: "⊑", + 8850: "⊒", + 8851: "⊓", + 8852: "⊔", + 8853: "⊕", + 8854: "⊖", + 8855: "⊗", + 8856: "⊘", + 8857: "⊙", + 8858: "⊚", + 8859: "⊛", + 8861: "⊝", + 8862: "⊞", + 8863: "⊟", + 8864: "⊠", + 8865: "⊡", + 8866: "⊢", + 8867: "⊣", + 8868: "⊤", + 8869: "⊥", + 8871: "⊧", + 8872: "⊨", + 8873: "⊩", + 8874: "⊪", + 8875: "⊫", + 8876: "⊬", + 8877: "⊭", + 8878: "⊮", + 8879: "⊯", + 8880: "⊰", + 8882: "⊲", + 8883: "⊳", + 8884: "⊴", + 8885: "⊵", + 8886: "⊶", + 8887: "⊷", + 8888: "⊸", + 8889: "⊹", + 8890: "⊺", + 8891: "⊻", + 8893: "⊽", + 8894: "⊾", + 8895: "⊿", + 8896: "⋀", + 8897: "⋁", + 8898: "⋂", + 8899: "⋃", + 8900: "⋄", + 8901: "⋅", + 8902: "⋆", + 8903: "⋇", + 8904: "⋈", + 8905: "⋉", + 8906: "⋊", + 8907: "⋋", + 8908: "⋌", + 8909: "⋍", + 8910: "⋎", + 8911: "⋏", + 8912: "⋐", + 8913: "⋑", + 8914: "⋒", + 8915: "⋓", + 8916: "⋔", + 8917: "⋕", + 8918: "⋖", + 8919: "⋗", + 8920: "⋘", + 8921: "⋙", + 8922: "⋚", + 8923: "⋛", + 8926: "⋞", + 8927: "⋟", + 8928: "⋠", + 8929: "⋡", + 8930: "⋢", + 8931: "⋣", + 8934: "⋦", + 8935: "⋧", + 8936: "⋨", + 8937: "⋩", + 8938: "⋪", + 8939: "⋫", + 8940: "⋬", + 8941: "⋭", + 8942: "⋮", + 8943: "⋯", + 8944: "⋰", + 8945: "⋱", + 8946: "⋲", + 8947: "⋳", + 8948: "⋴", + 8949: "⋵", + 8950: "⋶", + 8951: "⋷", + 8953: "⋹", + 8954: "⋺", + 8955: "⋻", + 8956: "⋼", + 8957: "⋽", + 8958: "⋾", + 8965: "⌅", + 8966: "⌆", + 8968: "⌈", + 8969: "⌉", + 8970: "⌊", + 8971: "⌋", + 8972: "⌌", + 8973: "⌍", + 8974: "⌎", + 8975: "⌏", + 8976: "⌐", + 8978: "⌒", + 8979: "⌓", + 8981: "⌕", + 8982: "⌖", + 8988: "⌜", + 8989: "⌝", + 8990: "⌞", + 8991: "⌟", + 8994: "⌢", + 8995: "⌣", + 9001: "⟨", + 9002: "⟩", + 9005: "⌭", + 9006: "⌮", + 9014: "⌶", + 9021: "⌽", + 9023: "⌿", + 9084: "⍼", + 9136: "⎰", + 9137: "⎱", + 9140: "⎴", + 9141: "⎵", + 9142: "⎶", + 9180: "⏜", + 9181: "⏝", + 9182: "⏞", + 9183: "⏟", + 9186: "⏢", + 9191: "⏧", + 9251: "␣", + 9416: "Ⓢ", + 9472: "─", + 9474: "│", + 9484: "┌", + 9488: "┐", + 9492: "└", + 9496: "┘", + 9500: "├", + 9508: "┤", + 9516: "┬", + 9524: "┴", + 9532: "┼", + 9552: "═", + 9553: "║", + 9554: "╒", + 9555: "╓", + 9556: "╔", + 9557: "╕", + 9558: "╖", + 9559: "╗", + 9560: "╘", + 9561: "╙", + 9562: "╚", + 9563: "╛", + 9564: "╜", + 9565: "╝", + 9566: "╞", + 9567: "╟", + 9568: "╠", + 9569: "╡", + 9570: "╢", + 9571: "╣", + 9572: "╤", + 9573: "╥", + 9674: "◊", + 9675: "○", + 9708: "◬", + 9711: "◯", + 9720: "◸", + 9721: "◹", + 9722: "◺", + 9723: "◻", + 9724: "◼", + 9733: "★", + 9734: "☆", + 9742: "☎", + 9792: "♀", + 9794: "♂", + 9824: "♠", + 9827: "♣", + 9829: "♥", + 9830: "♦", + 9834: "♪", + 9837: "♭", + 9838: "♮", + 9839: "♯", + 10003: "✓", + 10007: "✗", + 10016: "✠", + 10038: "✶", + 10072: "❘", + 10098: "❲", + 10099: "❳", + 10214: "⟦", + 10215: "⟧", + 10216: "⟨", + 10217: "⟩", + 10218: "⟪", + 10219: "⟫", + 10220: "⟬", + 10221: "⟭", + 10229: "⟵", + 10230: "⟶", + 10231: "⟷", + 10232: "⟸", + 10233: "⟹", + 10234: "⟺", + 10236: "⟼", + 10239: "⟿", + 10498: "⤂", + 10499: "⤃", + 10500: "⤄", + 10501: "⤅", + 10508: "⤌", + 10509: "⤍", + 10510: "⤎", + 10511: "⤏", + 10512: "⤐", + 10513: "⤑", + 10514: "⤒", + 10515: "⤓", + 10518: "⤖", + 10521: "⤙", + 10522: "⤚", + 10523: "⤛", + 10524: "⤜", + 10525: "⤝", + 10526: "⤞", + 10527: "⤟", + 10528: "⤠", + 10531: "⤣", + 10532: "⤤", + 10533: "⤥", + 10534: "⤦", + 10535: "⤧", + 10536: "⤨", + 10537: "⤩", + 10538: "⤪", + 10547: "⤳", + 10549: "⤵", + 10550: "⤶", + 10551: "⤷", + 10552: "⤸", + 10553: "⤹", + 10556: "⤼", + 10557: "⤽", + 10565: "⥅", + 10568: "⥈", + 10569: "⥉", + 10570: "⥊", + 10571: "⥋", + 10574: "⥎", + 10575: "⥏", + 10576: "⥐", + 10577: "⥑", + 10578: "⥒", + 10579: "⥓", + 10580: "⥔", + 10581: "⥕", + 10582: "⥖", + 10583: "⥗", + 10584: "⥘", + 10585: "⥙", + 10586: "⥚", + 10587: "⥛", + 10588: "⥜", + 10589: "⥝", + 10590: "⥞", + 10591: "⥟", + 10592: "⥠", + 10593: "⥡", + 10594: "⥢", + 10595: "⥣", + 10596: "⥤", + 10597: "⥥", + 10598: "⥦", + 10599: "⥧", + 10600: "⥨", + 10601: "⥩", + 10602: "⥪", + 10603: "⥫", + 10604: "⥬", + 10605: "⥭", + 10606: "⥮", + 10607: "⥯", + 10608: "⥰", + 10609: "⥱", + 10610: "⥲", + 10611: "⥳", + 10612: "⥴", + 10613: "⥵", + 10614: "⥶", + 10616: "⥸", + 10617: "⥹", + 10619: "⥻", + 10620: "⥼", + 10621: "⥽", + 10622: "⥾", + 10623: "⥿", + 10629: "⦅", + 10630: "⦆", + 10635: "⦋", + 10636: "⦌", + 10637: "⦍", + 10638: "⦎", + 10639: "⦏", + 10640: "⦐", + 10641: "⦑", + 10642: "⦒", + 10643: "⦓", + 10644: "⦔", + 10645: "⦕", + 10646: "⦖", + 10650: "⦚", + 10652: "⦜", + 10653: "⦝", + 10660: "⦤", + 10661: "⦥", + 10662: "⦦", + 10663: "⦧", + 10664: "⦨", + 10665: "⦩", + 10666: "⦪", + 10667: "⦫", + 10668: "⦬", + 10669: "⦭", + 10670: "⦮", + 10671: "⦯", + 10672: "⦰", + 10673: "⦱", + 10674: "⦲", + 10675: "⦳", + 10676: "⦴", + 10677: "⦵", + 10678: "⦶", + 10679: "⦷", + 10681: "⦹", + 10683: "⦻", + 10684: "⦼", + 10686: "⦾", + 10687: "⦿", + 10688: "⧀", + 10689: "⧁", + 10690: "⧂", + 10691: "⧃", + 10692: "⧄", + 10693: "⧅", + 10697: "⧉", + 10701: "⧍", + 10702: "⧎", + 10703: "⧏", + 10704: "⧐", + 10714: "∽̱", + 10716: "⧜", + 10717: "⧝", + 10718: "⧞", + 10723: "⧣", + 10724: "⧤", + 10725: "⧥", + 10731: "⧫", + 10740: "⧴", + 10742: "⧶", + 10752: "⨀", + 10753: "⨁", + 10754: "⨂", + 10756: "⨄", + 10758: "⨆", + 10764: "⨌", + 10765: "⨍", + 10768: "⨐", + 10769: "⨑", + 10770: "⨒", + 10771: "⨓", + 10772: "⨔", + 10773: "⨕", + 10774: "⨖", + 10775: "⨗", + 10786: "⨢", + 10787: "⨣", + 10788: "⨤", + 10789: "⨥", + 10790: "⨦", + 10791: "⨧", + 10793: "⨩", + 10794: "⨪", + 10797: "⨭", + 10798: "⨮", + 10799: "⨯", + 10800: "⨰", + 10801: "⨱", + 10803: "⨳", + 10804: "⨴", + 10805: "⨵", + 10806: "⨶", + 10807: "⨷", + 10808: "⨸", + 10809: "⨹", + 10810: "⨺", + 10811: "⨻", + 10812: "⨼", + 10815: "⨿", + 10816: "⩀", + 10818: "⩂", + 10819: "⩃", + 10820: "⩄", + 10821: "⩅", + 10822: "⩆", + 10823: "⩇", + 10824: "⩈", + 10825: "⩉", + 10826: "⩊", + 10827: "⩋", + 10828: "⩌", + 10829: "⩍", + 10832: "⩐", + 10835: "⩓", + 10836: "⩔", + 10837: "⩕", + 10838: "⩖", + 10839: "⩗", + 10840: "⩘", + 10842: "⩚", + 10843: "⩛", + 10844: "⩜", + 10845: "⩝", + 10847: "⩟", + 10854: "⩦", + 10858: "⩪", + 10861: "⩭", + 10862: "⩮", + 10863: "⩯", + 10864: "⩰", + 10865: "⩱", + 10866: "⩲", + 10867: "⩳", + 10868: "⩴", + 10869: "⩵", + 10871: "⩷", + 10872: "⩸", + 10873: "⩹", + 10874: "⩺", + 10875: "⩻", + 10876: "⩼", + 10877: "⩽", + 10878: "⩾", + 10879: "⩿", + 10880: "⪀", + 10881: "⪁", + 10882: "⪂", + 10883: "⪃", + 10884: "⪄", + 10885: "⪅", + 10886: "⪆", + 10887: "⪇", + 10888: "⪈", + 10889: "⪉", + 10890: "⪊", + 10891: "⪋", + 10892: "⪌", + 10893: "⪍", + 10894: "⪎", + 10895: "⪏", + 10896: "⪐", + 10897: "⪑", + 10898: "⪒", + 10899: "⪓", + 10900: "⪔", + 10901: "⪕", + 10902: "⪖", + 10903: "⪗", + 10904: "⪘", + 10905: "⪙", + 10906: "⪚", + 10909: "⪝", + 10910: "⪞", + 10911: "⪟", + 10912: "⪠", + 10913: "⪡", + 10914: "⪢", + 10916: "⪤", + 10917: "⪥", + 10918: "⪦", + 10919: "⪧", + 10920: "⪨", + 10921: "⪩", + 10922: "⪪", + 10923: "⪫", + 10924: "⪬", + 10925: "⪭", + 10926: "⪮", + 10927: "⪯", + 10928: "⪰", + 10931: "⪳", + 10932: "⪴", + 10933: "⪵", + 10934: "⪶", + 10935: "⪷", + 10936: "⪸", + 10937: "⪹", + 10938: "⪺", + 10939: "⪻", + 10940: "⪼", + 10941: "⪽", + 10942: "⪾", + 10943: "⪿", + 10944: "⫀", + 10945: "⫁", + 10946: "⫂", + 10947: "⫃", + 10948: "⫄", + 10949: "⫅", + 10950: "⫆", + 10951: "⫇", + 10952: "⫈", + 10955: "⫋", + 10956: "⫌", + 10959: "⫏", + 10960: "⫐", + 10961: "⫑", + 10962: "⫒", + 10963: "⫓", + 10964: "⫔", + 10965: "⫕", + 10966: "⫖", + 10967: "⫗", + 10968: "⫘", + 10969: "⫙", + 10970: "⫚", + 10971: "⫛", + 10980: "⫤", + 10982: "⫦", + 10983: "⫧", + 10984: "⫨", + 10985: "⫩", + 10987: "⫫", + 10988: "⫬", + 10989: "⫭", + 10990: "⫮", + 10991: "⫯", + 10992: "⫰", + 10993: "⫱", + 10994: "⫲", + 10995: "⫳", + 11005: "⫽", + 64256: "ff", + 64257: "fi", + 64258: "fl", + 64259: "ffi", + 64260: "ffl", + 119964: "𝒜", + 119966: "𝒞", + 119967: "𝒟", + 119970: "𝒢", + 119973: "𝒥", + 119974: "𝒦", + 119977: "𝒩", + 119978: "𝒪", + 119979: "𝒫", + 119980: "𝒬", + 119982: "𝒮", + 119983: "𝒯", + 119984: "𝒰", + 119985: "𝒱", + 119986: "𝒲", + 119987: "𝒳", + 119988: "𝒴", + 119989: "𝒵", + 119990: "𝒶", + 119991: "𝒷", + 119992: "𝒸", + 119993: "𝒹", + 119995: "𝒻", + 119997: "𝒽", + 119998: "𝒾", + 119999: "𝒿", + 120000: "𝓀", + 120001: "𝓁", + 120002: "𝓂", + 120003: "𝓃", + 120005: "𝓅", + 120006: "𝓆", + 120007: "𝓇", + 120008: "𝓈", + 120009: "𝓉", + 120010: "𝓊", + 120011: "𝓋", + 120012: "𝓌", + 120013: "𝓍", + 120014: "𝓎", + 120015: "𝓏", + 120068: "𝔄", + 120069: "𝔅", + 120071: "𝔇", + 120072: "𝔈", + 120073: "𝔉", + 120074: "𝔊", + 120077: "𝔍", + 120078: "𝔎", + 120079: "𝔏", + 120080: "𝔐", + 120081: "𝔑", + 120082: "𝔒", + 120083: "𝔓", + 120084: "𝔔", + 120086: "𝔖", + 120087: "𝔗", + 120088: "𝔘", + 120089: "𝔙", + 120090: "𝔚", + 120091: "𝔛", + 120092: "𝔜", + 120094: "𝔞", + 120095: "𝔟", + 120096: "𝔠", + 120097: "𝔡", + 120098: "𝔢", + 120099: "𝔣", + 120100: "𝔤", + 120101: "𝔥", + 120102: "𝔦", + 120103: "𝔧", + 120104: "𝔨", + 120105: "𝔩", + 120106: "𝔪", + 120107: "𝔫", + 120108: "𝔬", + 120109: "𝔭", + 120110: "𝔮", + 120111: "𝔯", + 120112: "𝔰", + 120113: "𝔱", + 120114: "𝔲", + 120115: "𝔳", + 120116: "𝔴", + 120117: "𝔵", + 120118: "𝔶", + 120119: "𝔷", + 120120: "𝔸", + 120121: "𝔹", + 120123: "𝔻", + 120124: "𝔼", + 120125: "𝔽", + 120126: "𝔾", + 120128: "𝕀", + 120129: "𝕁", + 120130: "𝕂", + 120131: "𝕃", + 120132: "𝕄", + 120134: "𝕆", + 120138: "𝕊", + 120139: "𝕋", + 120140: "𝕌", + 120141: "𝕍", + 120142: "𝕎", + 120143: "𝕏", + 120144: "𝕐", + 120146: "𝕒", + 120147: "𝕓", + 120148: "𝕔", + 120149: "𝕕", + 120150: "𝕖", + 120151: "𝕗", + 120152: "𝕘", + 120153: "𝕙", + 120154: "𝕚", + 120155: "𝕛", + 120156: "𝕜", + 120157: "𝕝", + 120158: "𝕞", + 120159: "𝕟", + 120160: "𝕠", + 120161: "𝕡", + 120162: "𝕢", + 120163: "𝕣", + 120164: "𝕤", + 120165: "𝕥", + 120166: "𝕦", + 120167: "𝕧", + 120168: "𝕨", + 120169: "𝕩", + 120170: "𝕪", + 120171: "𝕫" +}; + +export default ToHTMLEntity; diff --git a/plugins/srktoolbox/src/core/operations/ToHex.mjs b/plugins/srktoolbox/src/core/operations/ToHex.mjs new file mode 100644 index 00000000..d1f31305 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToHex.mjs @@ -0,0 +1,134 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {toHex, TO_HEX_DELIM_OPTIONS} from "../lib/Hex.mjs"; +import Utils from "../Utils.mjs"; + +/** + * To Hex operation + */ +class ToHex extends Operation { + + /** + * ToHex constructor + */ + constructor() { + super(); + + this.name = "字符转十六进制"; + this.module = "Default"; + this.description = "将输入字符串转换为对应的十六进制表示(使用给定的分隔符)。

例如:UTF-8字符串 Γειά σου 编码成 ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a"; + this.infoURL = "https://wikipedia.org/wiki/Hexadecimal"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "分隔符", + type: "option", + value: TO_HEX_DELIM_OPTIONS + }, + { + name: "每行字节数", + type: "number", + value: 0 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + let delim, comma; + if (args[0] === "0x和逗号") { + delim = "0x"; + comma = ","; + } else { + delim = Utils.charRep(args[0] || "空格"); + } + const lineSize = args[1]; + + return toHex(new Uint8Array(input), delim, 2, comma, lineSize); + } + + /** + * Highlight to Hex + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + let delim, commaLen = 0; + if (args[0] === "0x with comma") { + delim = "0x"; + commaLen = 1; + } else { + delim = Utils.charRep(args[0] || "空格"); + } + + const lineSize = args[1], + len = delim.length + commaLen; + + const countLF = function(p) { + // Count the number of LFs from 0 upto p + return (p / lineSize | 0) - (p >= lineSize && p % lineSize === 0); + }; + + pos[0].start = pos[0].start * (2 + len) + countLF(pos[0].start); + pos[0].end = pos[0].end * (2 + len) + countLF(pos[0].end); + + // if the delimiters are not prepended, trim the trailing delimiter + if (!(delim === "0x" || delim === "\\x")) { + pos[0].end -= delim.length; + } + // if there is comma, trim the trailing comma + pos[0].end -= commaLen; + return pos; + } + + /** + * Highlight from Hex + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + let delim, commaLen = 0; + if (args[0] === "0x和逗号") { + delim = "0x"; + commaLen = 1; + } else { + delim = Utils.charRep(args[0] || "空格"); + } + + const lineSize = args[1], + len = delim.length + commaLen, + width = len + 2; + + const countLF = function(p) { + // Count the number of LFs from 0 up to p + const lineLength = width * lineSize; + return (p / lineLength | 0) - (p >= lineLength && p % lineLength === 0); + }; + + pos[0].start = pos[0].start === 0 ? 0 : Math.round((pos[0].start - countLF(pos[0].start)) / width); + pos[0].end = pos[0].end === 0 ? 0 : Math.ceil((pos[0].end - countLF(pos[0].end)) / width); + return pos; + } +} + +export default ToHex; diff --git a/plugins/srktoolbox/src/core/operations/ToHexContent.mjs b/plugins/srktoolbox/src/core/operations/ToHexContent.mjs new file mode 100644 index 00000000..f2be57c8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToHexContent.mjs @@ -0,0 +1,85 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {toHex} from "../lib/Hex.mjs"; + +/** + * To Hex Content operation + */ +class ToHexContent extends Operation { + + /** + * ToHexContent constructor + */ + constructor() { + super(); + + this.name = "Snort Content编码"; + this.module = "Default"; + this.description = "把字符串的特殊字符转换成十六进制。SNORT的Content关键字使用此格式。

例: foo=bar 编码为 foo|3d|bar."; + this.infoURL = "http://manual-snort-org.s3-website-us-east-1.amazonaws.com/node32.html#SECTION00451000000000000000"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "转换", + "type": "option", + "value": ["仅特殊字符", "仅特殊字符(包括空格)", "所有字符"] + }, + { + "name": "字节间用空格分隔", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + input = new Uint8Array(input); + const convert = args[0]; + const spaces = args[1]; + if (convert === "所有字符") { + let result = "|" + toHex(input) + "|"; + if (!spaces) result = result.replace(/ /g, ""); + return result; + } + + let output = "", + inHex = false, + b; + const convertSpaces = convert === "仅特殊字符(包括空格)"; + for (let i = 0; i < input.length; i++) { + b = input[i]; + if ((b === 32 && convertSpaces) || (b < 48 && b !== 32) || (b > 57 && b < 65) || (b > 90 && b < 97) || b > 122) { + if (!inHex) { + output += "|"; + inHex = true; + } else if (spaces) output += " "; + output += toHex([b]); + } else { + if (inHex) { + output += "|"; + inHex = false; + } + output += Utils.chr(input[i]); + } + } + if (inHex) output += "|"; + return output; + } + +} + +export default ToHexContent; diff --git a/plugins/srktoolbox/src/core/operations/ToHexdump.mjs b/plugins/srktoolbox/src/core/operations/ToHexdump.mjs new file mode 100644 index 00000000..496889fa --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToHexdump.mjs @@ -0,0 +1,197 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * To Hexdump operation + */ +class ToHexdump extends Operation { + + /** + * ToHexdump constructor + */ + constructor() { + super(); + + this.name = "转换到Hexdump"; + this.module = "Default"; + this.description = "生成输入数据的hexdump,显示十六进制以及每个字节的ASCII字符。

'UNIX格式'参数用于确定显示哪些可打印的ASCII字符。"; + this.infoURL = "https://wikipedia.org/wiki/Hex_dump"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "宽度", + "type": "number", + "value": 16, + "min": 1 + }, + { + "name": "十六进制大写", + "type": "boolean", + "value": false + }, + { + "name": "包括最终长度", + "type": "boolean", + "value": false + }, + { + "name": "UNIX格式", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const data = new Uint8Array(input); + const [length, upperCase, includeFinalLength, unixFormat] = args; + const padding = 2; + + if (length < 1 || Math.round(length) !== length) + throw new OperationError("宽度必须为正整数"); + + const lines = []; + for (let i = 0; i < data.length; i += length) { + let lineNo = Utils.hex(i, 8); + + const buff = data.slice(i, i+length); + const hex = []; + buff.forEach(b => hex.push(Utils.hex(b, padding))); + let hexStr = hex.join(" ").padEnd(length*(padding+1), " "); + + const ascii = Utils.printable(Utils.byteArrayToChars(buff), false, unixFormat); + const asciiStr = ascii.padEnd(buff.length, " "); + + if (upperCase) { + hexStr = hexStr.toUpperCase(); + lineNo = lineNo.toUpperCase(); + } + + lines.push(`${lineNo} ${hexStr} |${asciiStr}|`); + + + if (includeFinalLength && i+buff.length === data.length) { + lines.push(Utils.hex(i+buff.length, 8)); + } + } + + return lines.join("\n"); + } + + /** + * Highlight To Hexdump + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + // Calculate overall selection + const w = args[0] || 16, + width = 14 + (w*4); + let line = Math.floor(pos[0].start / w), + offset = pos[0].start % w, + start = 0, + end = 0; + + pos[0].start = line*width + 10 + offset*3; + + line = Math.floor(pos[0].end / w); + offset = pos[0].end % w; + if (offset === 0) { + line--; + offset = w; + } + pos[0].end = line*width + 10 + offset*3 - 1; + + // Set up multiple selections for bytes + let startLineNum = Math.floor(pos[0].start / width); + const endLineNum = Math.floor(pos[0].end / width); + + if (startLineNum === endLineNum) { + pos.push(pos[0]); + } else { + start = pos[0].start; + end = (startLineNum+1) * width - w - 5; + pos.push({ start: start, end: end }); + while (end < pos[0].end) { + startLineNum++; + start = startLineNum * width + 10; + end = (startLineNum+1) * width - w - 5; + if (end > pos[0].end) end = pos[0].end; + pos.push({ start: start, end: end }); + } + } + + // Set up multiple selections for ASCII + const len = pos.length; + let lineNum = 0; + start = 0; + end = 0; + for (let i = 1; i < len; i++) { + lineNum = Math.floor(pos[i].start / width); + start = (((pos[i].start - (lineNum * width)) - 10) / 3) + (width - w -2) + (lineNum * width); + end = (((pos[i].end + 1 - (lineNum * width)) - 10) / 3) + (width - w -2) + (lineNum * width); + pos.push({ start: start, end: end }); + } + return pos; + } + + /** + * Highlight To Hexdump in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + const w = args[0] || 16; + const width = 14 + (w*4); + + let line = Math.floor(pos[0].start / width); + let offset = pos[0].start % width; + + if (offset < 10) { // In line number section + pos[0].start = line*w; + } else if (offset > 10+(w*3)) { // In ASCII section + pos[0].start = (line+1)*w; + } else { // In byte section + pos[0].start = line*w + Math.floor((offset-10)/3); + } + + line = Math.floor(pos[0].end / width); + offset = pos[0].end % width; + + if (offset < 10) { // In line number section + pos[0].end = line*w; + } else if (offset > 10+(w*3)) { // In ASCII section + pos[0].end = (line+1)*w; + } else { // In byte section + pos[0].end = line*w + Math.ceil((offset-10)/3); + } + + return pos; + } + +} + +export default ToHexdump; diff --git a/plugins/srktoolbox/src/core/operations/ToKebabCase.mjs b/plugins/srktoolbox/src/core/operations/ToKebabCase.mjs new file mode 100644 index 00000000..a254e439 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToKebabCase.mjs @@ -0,0 +1,56 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import kebabCase from "lodash/kebabCase.js"; +import Operation from "../Operation.mjs"; +import { replaceVariableNames } from "../lib/Code.mjs"; + +/** + * To Kebab case operation + */ +class ToKebabCase extends Operation { + + /** + * ToKebabCase constructor + */ + constructor() { + super(); + + this.name = "转换为Kebab case"; + this.module = "Code"; + this.description = "将输入字符串转换为kebab case。\n

\nKebab case是全小写使用连字符作为单词边界的格式。\n

\n例如: this-is-kebab-case\n

\n勾选“尝试识别上下文”后此操作将尝试只转换函数和变量名。"; + this.infoURL = "https://wikipedia.org/wiki/Kebab_case"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "尝试识别上下文", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const smart = args[0]; + + if (smart) { + return replaceVariableNames(input, kebabCase); + } else { + return kebabCase(input); + } + } + +} + +export default ToKebabCase; diff --git a/plugins/srktoolbox/src/core/operations/ToLowerCase.mjs b/plugins/srktoolbox/src/core/operations/ToLowerCase.mjs new file mode 100644 index 00000000..0e49f97e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToLowerCase.mjs @@ -0,0 +1,67 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * To Lower case operation + */ +class ToLowerCase extends Operation { + + /** + * ToLowerCase constructor + */ + constructor() { + super(); + + this.name = "转换为小写"; + this.module = "Default"; + this.description = "将输入中的所有字符转换为小写。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return input.toLowerCase(); + } + + /** + * Highlight To Lower case + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight To Lower case in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default ToLowerCase; diff --git a/plugins/srktoolbox/src/core/operations/ToMessagePack.mjs b/plugins/srktoolbox/src/core/operations/ToMessagePack.mjs new file mode 100644 index 00000000..255b0dbc --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToMessagePack.mjs @@ -0,0 +1,55 @@ +/** + * @author Matt C [matt@artemisbot.uk] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import notepack from "notepack.io"; +import { isWorkerEnvironment } from "../Utils.mjs"; + +/** + * To MessagePack operation + */ +class ToMessagePack extends Operation { + + /** + * ToMessagePack constructor + */ + constructor() { + super(); + + this.name = "MessagePack编码"; + this.module = "Code"; + this.description = "把JSON转换成MessagePack编码的字节buffer。MessagePack是一种计算机数据交换格式。它是一种二进制形式,用于表示简单的数据结构,如数组和关联数组。"; + this.infoURL = "https://wikipedia.org/wiki/MessagePack"; + this.inputType = "JSON"; + this.outputType = "ArrayBuffer"; + this.args = []; + } + + /** + * @param {JSON} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + try { + if (isWorkerEnvironment()) { + return notepack.encode(input); + } else { + const res = notepack.encode(input); + // Safely convert from Node Buffer to ArrayBuffer using the correct view of the data + return (new Uint8Array(res)).buffer; + } + } catch (err) { + throw new OperationError(`无法将 JSON 转换为 MessagePack: ${err}`); + } + } + +} + +export default ToMessagePack; diff --git a/plugins/srktoolbox/src/core/operations/ToModhex.mjs b/plugins/srktoolbox/src/core/operations/ToModhex.mjs new file mode 100644 index 00000000..c027f502 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToModhex.mjs @@ -0,0 +1,57 @@ +/** + * @author linuxgemini [ilteris@asenkron.com.tr] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import Operation from "../Operation.mjs"; +import { TO_MODHEX_DELIM_OPTIONS, toModhex } from "../lib/Modhex.mjs"; +import Utils from "../Utils.mjs"; + +/** + * To Modhex operation + */ +class ToModhex extends Operation { + + /** + * ToModhex constructor + */ + constructor() { + super(); + + this.name = "Modhex编码"; + this.module = "Default"; + this.description = "将输入字符串使用给定的分隔符编码为Modhex字符串。"; + this.infoURL = "https://en.wikipedia.org/wiki/YubiKey#ModHex"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "分隔符", + type: "option", + value: TO_MODHEX_DELIM_OPTIONS + }, + { + name: "每行字节数", + type: "number", + value: 0 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0]); + const lineSize = args[1]; + + return toModhex(new Uint8Array(input), delim, 2, "", lineSize); + } +} + +export default ToModhex; diff --git a/plugins/srktoolbox/src/core/operations/ToMorseCode.mjs b/plugins/srktoolbox/src/core/operations/ToMorseCode.mjs new file mode 100644 index 00000000..e445d5e8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToMorseCode.mjs @@ -0,0 +1,157 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {LETTER_DELIM_OPTIONS, WORD_DELIM_OPTIONS} from "../lib/Delim.mjs"; + +/** + * To Morse Code operation + */ +class ToMorseCode extends Operation { + + /** + * ToMorseCode constructor + */ + constructor() { + super(); + + this.name = "摩尔斯电码编码"; + this.module = "Default"; + this.description = "把字母编码为国际摩尔斯电码。

忽略非摩尔斯码字符。

例: SOS 编码为 ... --- ..."; + this.infoURL = "https://wikipedia.org/wiki/Morse_code"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "格式", + "type": "option", + "value": ["-/.", "_/.", "Dash/Dot", "DASH/DOT", "dash/dot"] + }, + { + "name": "字母分隔符", + "type": "option", + "value": LETTER_DELIM_OPTIONS + }, + { + "name": "单词分隔符", + "type": "option", + "value": WORD_DELIM_OPTIONS + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const format = args[0].split("/"); + const dash = format[0]; + const dot = format[1]; + + const letterDelim = Utils.charRep(args[1]); + const wordDelim = Utils.charRep(args[2]); + + input = input.split(/\r?\n/); + input = Array.prototype.map.call(input, function(line) { + let words = line.split(/ +/); + words = Array.prototype.map.call(words, function(word) { + const letters = Array.prototype.map.call(word, function(character) { + const letter = character.toUpperCase(); + if (typeof MORSE_TABLE[letter] == "undefined") { + return ""; + } + + return MORSE_TABLE[letter]; + }); + + return letters.join(""); + }); + line = words.join(""); + return line; + }); + input = input.join("\n"); + + input = input.replace( + /|||/g, + function(match) { + switch (match) { + case "": return dash; + case "": return dot; + case "": return letterDelim; + case "": return wordDelim; + } + } + ); + + return input; + } + +} + +const MORSE_TABLE = { + "A": "", + "B": "", + "C": "", + "D": "", + "E": "", + "F": "", + "G": "", + "H": "", + "I": "", + "J": "", + "K": "", + "L": "", + "M": "", + "N": "", + "O": "", + "P": "", + "Q": "", + "R": "", + "S": "", + "T": "", + "U": "", + "V": "", + "W": "", + "X": "", + "Y": "", + "Z": "", + "1": "", + "2": "", + "3": "", + "4": "", + "5": "", + "6": "", + "7": "", + "8": "", + "9": "", + "0": "", + ".": "", + ",": "", + ":": "", + ";": "", + "!": "", + "?": "", + "'": "", + "\"": "", + "/": "", + "-": "", + "+": "", + "(": "", + ")": "", + "@": "", + "=": "", + "&": "", + "_": "", + "$": "", + " ": "" +}; + +export default ToMorseCode; diff --git a/plugins/srktoolbox/src/core/operations/ToOctal.mjs b/plugins/srktoolbox/src/core/operations/ToOctal.mjs new file mode 100644 index 00000000..78fe0060 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToOctal.mjs @@ -0,0 +1,52 @@ +/** + * @author Matt C [matt@artemisbot.uk] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {DELIM_OPTIONS} from "../lib/Delim.mjs"; + + +/** + * To Octal operation + */ +class ToOctal extends Operation { + + /** + * ToOctal constructor + */ + constructor() { + super(); + + this.name = "字符转八进制"; + this.module = "Default"; + this.description = "将输入字符串转换为对应的八进制表示(使用给定的分隔符)。

例: UTF-8编码字符串 Γειά σου 编码为 316 223 316 265 316 271 316 254 40 317 203 316 277 317 205"; + this.infoURL = "https://wikipedia.org/wiki/Octal"; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = [ + { + "name": "分隔符", + "type": "option", + "value": DELIM_OPTIONS + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0] || "Space"); + return input.map(val => val.toString(8)).join(delim); + } + +} + +export default ToOctal; diff --git a/plugins/srktoolbox/src/core/operations/ToPunycode.mjs b/plugins/srktoolbox/src/core/operations/ToPunycode.mjs new file mode 100644 index 00000000..6bdc6d73 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToPunycode.mjs @@ -0,0 +1,55 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import punycode from "punycode"; + +/** + * To Punycode operation + */ +class ToPunycode extends Operation { + + /** + * ToPunycode constructor + */ + constructor() { + super(); + + this.name = "Punycode编码"; + this.module = "Encodings"; + this.description = "Punycode是用ASCII字符的一个子集来编码Unicode域名的一种方法。

例: m\xfcnchen 编码为 mnchen-3ya"; + this.infoURL = "https://wikipedia.org/wiki/Punycode"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "国际化域名(带xn--)", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const idn = args[0]; + + if (idn) { + return punycode.toASCII(input); + } else { + return punycode.encode(input); + } + } + +} + +export default ToPunycode; diff --git a/plugins/srktoolbox/src/core/operations/ToQuotedPrintable.mjs b/plugins/srktoolbox/src/core/operations/ToQuotedPrintable.mjs new file mode 100644 index 00000000..92a5efcf --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToQuotedPrintable.mjs @@ -0,0 +1,248 @@ +/** + * Some parts taken from mimelib (http://github.com/andris9/mimelib) + * @author Andris Reinman + * @license MIT + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * To Quoted Printable operation + */ +class ToQuotedPrintable extends Operation { + + /** + * ToQuotedPrintable constructor + */ + constructor() { + super(); + + this.name = "QP编码"; + this.module = "Default"; + this.description = "Quoted-printable或QP encoding,没有规范的中文译名,可译为可打印字符引用编码或使用可打印字符的编码。Quoted-printable是使用可打印的ASCII字符(如字母、数字与“=”)表示各种编码格式下的字符,以便能在7-bit数据通路上传输8-bit数据, 或者更一般地说在非8-bit clean媒体上正确处理数据。它被定义为在Email中使用的MIME。

QP使用“=”开头的转义字符。一般限制行宽为76,因为有些软件限制了行宽。"; + this.infoURL = "https://wikipedia.org/wiki/Quoted-printable"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + input = new Uint8Array(input); + let mimeEncodedStr = this.mimeEncode(input); + + // fix line breaks + mimeEncodedStr = mimeEncodedStr.replace(/\r?\n|\r/g, function() { + return "\r\n"; + }).replace(/[\t ]+$/gm, function(spaces) { + return spaces.replace(/ /g, "=20").replace(/\t/g, "=09"); + }); + + return this._addSoftLinebreaks(mimeEncodedStr, "qp"); + } + + + /** @license + ======================================================================== + mimelib: http://github.com/andris9/mimelib + Copyright (c) 2011-2012 Andris Reinman + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + + /** + * Encodes mime data. + * + * @param {byteArray|Uint8Array} buffer + * @returns {string} + */ + mimeEncode(buffer) { + const ranges = [ + [0x09], + [0x0A], + [0x0D], + [0x20], + [0x21], + [0x23, 0x3C], + [0x3E], + [0x40, 0x5E], + [0x60, 0x7E] + ]; + let result = ""; + + for (let i = 0, len = buffer.length; i < len; i++) { + if (this._checkRanges(buffer[i], ranges)) { + result += String.fromCharCode(buffer[i]); + continue; + } + result += "=" + (buffer[i] < 0x10 ? "0" : "") + buffer[i].toString(16).toUpperCase(); + } + + return result; + } + + /** + * Checks if a given number falls within a given set of ranges. + * + * @private + * @param {number} nr + * @param {byteArray[]} ranges + * @returns {boolean} + */ + _checkRanges(nr, ranges) { + for (let i = ranges.length - 1; i >= 0; i--) { + if (!ranges[i].length) + continue; + if (ranges[i].length === 1 && nr === ranges[i][0]) + return true; + if (ranges[i].length === 2 && nr >= ranges[i][0] && nr <= ranges[i][1]) + return true; + } + return false; + } + + /** + * Adds soft line breaks to a string. + * Lines can't be longer that 76 + = 78 bytes + * http://tools.ietf.org/html/rfc2045#section-6.7 + * + * @private + * @param {string} str + * @param {string} encoding + * @returns {string} + */ + _addSoftLinebreaks(str, encoding) { + const lineLengthMax = 76; + + encoding = (encoding || "base64").toString().toLowerCase().trim(); + + if (encoding === "qp") { + return this._addQPSoftLinebreaks(str, lineLengthMax); + } else { + return this._addBase64SoftLinebreaks(str, lineLengthMax); + } + } + + /** + * Adds soft line breaks to a base64 string. + * + * @private + * @param {string} base64EncodedStr + * @param {number} lineLengthMax + * @returns {string} + */ + _addBase64SoftLinebreaks(base64EncodedStr, lineLengthMax) { + base64EncodedStr = (base64EncodedStr || "").toString().trim(); + return base64EncodedStr.replace(new RegExp(".{" + lineLengthMax + "}", "g"), "$&\r\n").trim(); + } + + /** + * Adds soft line breaks to a quoted printable string. + * + * @private + * @param {string} mimeEncodedStr + * @param {number} lineLengthMax + * @returns {string} + */ + _addQPSoftLinebreaks(mimeEncodedStr, lineLengthMax) { + const len = mimeEncodedStr.length, + lineMargin = Math.floor(lineLengthMax / 3); + let pos = 0, + match, code, line, + result = ""; + + // insert soft linebreaks where needed + while (pos < len) { + line = mimeEncodedStr.substr(pos, lineLengthMax); + if ((match = line.match(/\r\n/))) { + line = line.substr(0, match.index + match[0].length); + result += line; + pos += line.length; + continue; + } + + if (line.substr(-1) === "\n") { + // nothing to change here + result += line; + pos += line.length; + continue; + } else if ((match = line.substr(-lineMargin).match(/\n.*?$/))) { + // truncate to nearest line break + line = line.substr(0, line.length - (match[0].length - 1)); + result += line; + pos += line.length; + continue; + } else if (line.length > lineLengthMax - lineMargin && (match = line.substr(-lineMargin).match(/[ \t.,!?][^ \t.,!?]*$/))) { + // truncate to nearest space + line = line.substr(0, line.length - (match[0].length - 1)); + } else if (line.substr(-1) === "\r") { + line = line.substr(0, line.length - 1); + } else { + if (line.match(/=[\da-f]{0,2}$/i)) { + + // push incomplete encoding sequences to the next line + if ((match = line.match(/=[\da-f]{0,1}$/i))) { + line = line.substr(0, line.length - match[0].length); + } + + // ensure that utf-8 sequences are not split + while (line.length > 3 && line.length < len - pos && !line.match(/^(?:=[\da-f]{2}){1,4}$/i) && (match = line.match(/=[\da-f]{2}$/ig))) { + code = parseInt(match[0].substr(1, 2), 16); + if (code < 128) { + break; + } + + line = line.substr(0, line.length - 3); + + if (code >= 0xC0) { + break; + } + } + + } + } + + if (pos + line.length < len && line.substr(-1) !== "\n") { + if (line.length === 76 && line.match(/=[\da-f]{2}$/i)) { + line = line.substr(0, line.length - 3); + } else if (line.length === 76) { + line = line.substr(0, line.length - 1); + } + pos += line.length; + line += "=\r\n"; + } else { + pos += line.length; + } + + result += line; + } + + return result; + } + +} + +export default ToQuotedPrintable; diff --git a/plugins/srktoolbox/src/core/operations/ToSnakeCase.mjs b/plugins/srktoolbox/src/core/operations/ToSnakeCase.mjs new file mode 100644 index 00000000..a0a28d5f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToSnakeCase.mjs @@ -0,0 +1,55 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import snakeCase from "lodash/snakeCase.js"; +import Operation from "../Operation.mjs"; +import { replaceVariableNames } from "../lib/Code.mjs"; + +/** + * To Snake case operation + */ +class ToSnakeCase extends Operation { + + /** + * ToSnakeCase constructor + */ + constructor() { + super(); + + this.name = "转换为Snake case"; + this.module = "Code"; + this.description = "将输入字符串转换为snake case。\n

\nSnake case是全小写并使用下划线作为单词分隔的格式。\n

\n例如: this_is_snake_case\n

\n勾选“尝试识别上下文”后此操作将尝试只转换函数和变量名。"; + this.infoURL = "https://wikipedia.org/wiki/Snake_case"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "尝试识别上下文", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const smart = args[0]; + + if (smart) { + return replaceVariableNames(input, snakeCase); + } else { + return snakeCase(input); + } + } +} + +export default ToSnakeCase; diff --git a/plugins/srktoolbox/src/core/operations/ToTable.mjs b/plugins/srktoolbox/src/core/operations/ToTable.mjs new file mode 100644 index 00000000..29426857 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToTable.mjs @@ -0,0 +1,248 @@ +/** + * @author Mark Jones [github.com/justanothermark] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * To Table operation + */ +class ToTable extends Operation { + + /** + * ToTable constructor + */ + constructor() { + super(); + + this.name = "转换为表格"; + this.module = "Default"; + this.description = "用给定的分隔符分隔数据后渲染成HTML、ASCII或Markdown表格,可以额外添加表头。

默认支持CSV(逗号分隔)格式。将单元格分隔符修改为 \\t 用于支持TSV(Tab分隔),修改为 | 用于支持PSV(管道符分隔)。

你可以输入任意个数的分隔符,每个字符都会用作单独的分隔符。"; + this.infoURL = "https://wikipedia.org/wiki/Comma-separated_values"; + this.inputType = "string"; + this.outputType = "html"; + this.args = [ + { + "name": "单元格分隔符", + "type": "binaryShortString", + "value": "," + }, + { + "name": "行分隔符", + "type": "binaryShortString", + "value": "\\r\\n" + }, + { + "name": "第一行作为表头", + "type": "boolean", + "value": false + }, + { + "name": "格式", + "type": "option", + "value": ["ASCII", "HTML", "Markdown"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const [cellDelims, rowDelims, firstRowHeader, format] = args; + + // Process the input into a nested array of elements. + const tableData = Utils.parseCSV(Utils.escapeHtml(input), cellDelims.split(""), rowDelims.split("")); + + if (!tableData.length) return ""; + + // Render the data in the requested format. + switch (format) { + case "ASCII": + return asciiOutput(tableData); + case "HTML": + return htmlOutput(tableData); + case "Markdown": + return markdownOutput(tableData); + default: + return htmlOutput(tableData); + } + + /** + * Outputs an array of data as an ASCII table. + * + * @param {string[][]} tableData + * @returns {string} + */ + function asciiOutput(tableData) { + const horizontalBorder = "-"; + const verticalBorder = "|"; + const crossBorder = "+"; + + let output = ""; + const longestCells = []; + + // Find longestCells value per column to pad cells equally. + tableData.forEach(function(row, index) { + row.forEach(function(cell, cellIndex) { + if (longestCells[cellIndex] === undefined || cell.length > longestCells[cellIndex]) { + longestCells[cellIndex] = cell.length; + } + }); + }); + + // Add the top border of the table to the output. + output += outputHorizontalBorder(longestCells); + + // If the first row is a header, remove the row from the data and + // add it to the output with another horizontal border. + if (firstRowHeader) { + const row = tableData.shift(); + output += outputRow(row, longestCells); + output += outputHorizontalBorder(longestCells); + } + + // Add the rest of the table rows. + tableData.forEach(function(row, index) { + output += outputRow(row, longestCells); + }); + + // Close the table with a final horizontal border. + output += outputHorizontalBorder(longestCells); + + return output; + + /** + * Outputs a row of correctly padded cells. + */ + function outputRow(row, longestCells) { + let rowOutput = verticalBorder; + row.forEach(function(cell, index) { + rowOutput += " " + cell + " ".repeat(longestCells[index] - cell.length) + " " + verticalBorder; + }); + rowOutput += "\n"; + return rowOutput; + } + + /** + * Outputs a horizontal border with a different character where + * the horizontal border meets a vertical border. + */ + function outputHorizontalBorder(longestCells) { + let rowOutput = crossBorder; + longestCells.forEach(function(cellLength) { + rowOutput += horizontalBorder.repeat(cellLength + 2) + crossBorder; + }); + rowOutput += "\n"; + return rowOutput; + } + } + + /** + * Outputs a table of data as a HTML table. + * + * @param {string[][]} tableData + * @returns {string} + */ + function htmlOutput(tableData) { + // Start the HTML output with suitable classes for styling. + let output = "
"; + + // If the first row is a header then put it in with "; + output += outputRow(row, "th"); + output += ""; + } + + // Output the rest of the rows in the . + output += ""; + tableData.forEach(function(row, index) { + output += outputRow(row, "td"); + }); + + // Close the body and table elements. + output += "
cells. + if (firstRowHeader) { + const row = tableData.shift(); + output += "
"; + return output; + + /** + * Outputs a table row. + * + * @param {string[]} row + * @param {string} cellType + */ + function outputRow(row, cellType) { + let output = ""; + row.forEach(function(cell) { + output += "<" + cellType + ">" + cell + ""; + }); + output += ""; + return output; + } + } + + /** + * Outputs an array of data as a Markdown table. + * + * @param {string[][]} tableData + * @returns {string} + */ + function markdownOutput(tableData) { + const headerDivider = "-"; + const verticalBorder = "|"; + + let output = ""; + const longestCells = []; + + // Find longestCells value per column to pad cells equally. + tableData.forEach(function(row, index) { + row.forEach(function(cell, cellIndex) { + if (longestCells[cellIndex] === undefined || cell.length > longestCells[cellIndex]) { + longestCells[cellIndex] = cell.length; + } + }); + }); + + // Ignoring the checkbox, as current Mardown renderer in CF doesn't handle table without headers + const row = tableData.shift(); + output += outputRow(row, longestCells); + let rowOutput = verticalBorder; + row.forEach(function(cell, index) { + rowOutput += " " + headerDivider.repeat(longestCells[index]) + " " + verticalBorder; + }); + output += rowOutput += "\n"; + + // Add the rest of the table rows. + tableData.forEach(function(row, index) { + output += outputRow(row, longestCells); + }); + + return output; + + /** + * Outputs a row of correctly padded cells. + */ + function outputRow(row, longestCells) { + let rowOutput = verticalBorder; + row.forEach(function(cell, index) { + rowOutput += " " + cell + " ".repeat(longestCells[index] - cell.length) + " " + verticalBorder; + }); + rowOutput += "\n"; + return rowOutput; + } + + } + + } + +} + +export default ToTable; diff --git a/plugins/srktoolbox/src/core/operations/ToUNIXTimestamp.mjs b/plugins/srktoolbox/src/core/operations/ToUNIXTimestamp.mjs new file mode 100644 index 00000000..ba9d1cbb --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToUNIXTimestamp.mjs @@ -0,0 +1,80 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import moment from "moment-timezone"; +import {UNITS} from "../lib/DateTime.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * To UNIX Timestamp operation + */ +class ToUNIXTimestamp extends Operation { + + /** + * ToUNIXTimestamp constructor + */ + constructor() { + super(); + + this.name = "转换到UNIX时间戳"; + this.module = "Default"; + this.description = "解析DateTime字符串(UTC时区)并返回对应的UNIX时间戳。

例: Mon 1 January 2001 11:00:00 转换为 978346800

UNIX时间,或称POSIX时间是UNIX或类UNIX系统使用的时间表示方式:从UTC1970年1月1日0时0分0秒起至现在的总秒数,不考虑闰秒。"; + this.infoURL = "https://wikipedia.org/wiki/Unix_time"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "单位", + "type": "option", + "value": UNITS + }, + { + "name": "当作UTC时间", + "type": "boolean", + "value": true + }, + { + "name": "显示解析后的DateTime", + "type": "boolean", + "value": true + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + * + * @throws {OperationError} if unit unrecognised + */ + run(input, args) { + const [units, treatAsUTC, showDateTime] = args, + d = treatAsUTC ? moment.utc(input) : moment(input); + + let result = ""; + + if (units === "秒 (s)") { + result = d.unix(); + } else if (units === "毫秒 (ms)") { + result = d.valueOf(); + } else if (units === "微秒 (μs)") { + result = d.valueOf() * 1000; + } else if (units === "纳秒 (ns)") { + result = d.valueOf() * 1000000; + } else { + throw new OperationError("无效单位"); + } + + return showDateTime ? `${result} (${d.tz("UTC").format("ddd D MMMM YYYY HH:mm:ss")} UTC)` : result.toString(); + } + +} + +export default ToUNIXTimestamp; diff --git a/plugins/srktoolbox/src/core/operations/ToUpperCase.mjs b/plugins/srktoolbox/src/core/operations/ToUpperCase.mjs new file mode 100644 index 00000000..c7cdcd1e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ToUpperCase.mjs @@ -0,0 +1,97 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * To Upper case operation + */ +class ToUpperCase extends Operation { + + /** + * ToUpperCase constructor + */ + constructor() { + super(); + + this.name = "转换为大写"; + this.module = "Default"; + this.description = "将输入字符串转换成大写,可选限制为每个单词、句子或段落首字母大写。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "粒度", + "type": "option", + "value": ["所有字符", "单词", "句子", "段落"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + if (!args || args.length === 0) { + throw new OperationError("未提供操作粒度信息。"); + } + + const scope = args[0]; + + if (scope === "所有字符") { + return input.toUpperCase(); + } + + const scopeRegex = { + "单词": /(\b\w)/gi, + "句子": /(?:\.|^)\s*(\b\w)/gi, + "段落": /(?:\n|^)\s*(\b\w)/gi + }[scope]; + + if (scopeRegex === undefined) { + throw new OperationError("无效的操作粒度。"); + } + + // Use the regex to capitalize the input + return input.replace(scopeRegex, function(m) { + return m.toUpperCase(); + }); + } + + /** + * Highlight To Upper case + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight To Upper case in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default ToUpperCase; diff --git a/plugins/srktoolbox/src/core/operations/TranslateDateTimeFormat.mjs b/plugins/srktoolbox/src/core/operations/TranslateDateTimeFormat.mjs new file mode 100644 index 00000000..695b405f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/TranslateDateTimeFormat.mjs @@ -0,0 +1,95 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import moment from "moment-timezone"; +import {DATETIME_FORMATS, FORMAT_EXAMPLES} from "../lib/DateTime.mjs"; + +/** + * Translate DateTime Format operation + */ +class TranslateDateTimeFormat extends Operation { + + /** + * TranslateDateTimeFormat constructor + */ + constructor() { + super(); + + this.name = "转换DateTime格式"; + this.module = "Default"; + this.description = "将输入的DateTime转换成另一种格式。

不输入任何内容来查看格式示例字符串。"; + this.infoURL = "https://momentjs.com/docs/#/parsing/string-format/"; + this.inputType = "string"; + this.outputType = "string"; + this.presentType = "html"; + this.args = [ + { + "name": "内置格式", + "type": "populateOption", + "value": DATETIME_FORMATS, + "target": 1 + }, + { + "name": "输入格式", + "type": "binaryString", + "value": "DD/MM/YYYY HH:mm:ss" + }, + { + "name": "输入时区", + "type": "option", + "value": ["UTC"].concat(moment.tz.names()) + }, + { + "name": "输出格式", + "type": "binaryString", + "value": "dddd Do MMMM YYYY HH:mm:ss Z z" + }, + { + "name": "输出时区", + "type": "option", + "value": ["UTC"].concat(moment.tz.names()) + } + ]; + + this.invalidFormatMessage = "无效格式。"; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [inputFormat, inputTimezone, outputFormat, outputTimezone] = args.slice(1); + let date; + + try { + date = moment.tz(input, inputFormat, inputTimezone); + if (!date || date.format() === "Invalid date") throw Error; + } catch (err) { + return this.invalidFormatMessage; + } + + return date.tz(outputTimezone).format(outputFormat.replace(/[<>]/g, "")); + } + + /** + * @param {string} data + * @returns {html} + */ + present(data) { + if (data === this.invalidFormatMessage) { + return `${data}\n\n${FORMAT_EXAMPLES}`; + } + return Utils.escapeHtml(data); + } +} + +export default TranslateDateTimeFormat; diff --git a/plugins/srktoolbox/src/core/operations/TripleDESDecrypt.mjs b/plugins/srktoolbox/src/core/operations/TripleDESDecrypt.mjs new file mode 100644 index 00000000..7175af54 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/TripleDESDecrypt.mjs @@ -0,0 +1,112 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import forge from "node-forge"; + +/** + * Triple DES Decrypt operation + */ +class TripleDESDecrypt extends Operation { + + /** + * TripleDESDecrypt constructor + */ + constructor() { + super(); + + this.name = "3DES解密"; + this.module = "Ciphers"; + this.description = "Triple DES applies DES three times to each block to increase key size.

Key: Triple DES uses a key length of 24 bytes (192 bits).

IV: The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.

Padding: In CBC and ECB mode, PKCS#7 padding will be used as a default."; + this.infoURL = "https://wikipedia.org/wiki/Triple_DES"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Key", + "type": "toggleString", + "value": "", + "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"] + }, + { + "name": "IV", + "type": "toggleString", + "value": "", + "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"] + }, + { + "name": "模式", + "type": "option", + "value": ["CBC", "CFB", "OFB", "CTR", "ECB", "CBC/NoPadding", "ECB/NoPadding"] + }, + { + "name": "输入", + "type": "option", + "value": ["十六进制", "原始内容"] + }, + { + "name": "输出", + "type": "option", + "value": ["原始内容", "十六进制"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const key = Utils.convertToByteString(args[0].string, args[0].option), + iv = Utils.convertToByteArray(args[1].string, args[1].option), + mode = args[2].substring(0, 3), + noPadding = args[2].endsWith("NoPadding"), + inputType = args[3], + outputType = args[4]; + + if (key.length !== 24 && key.length !== 16) { + throw new OperationError(`无效的key长度: ${key.length} 字节 + +Triple DES uses a key length of 24 bytes (192 bits).`); + } + if (iv.length !== 8 && mode !== "ECB") { + throw new OperationError(`无效的IV长度: ${iv.length} 字节 + +三重DES的IV长度为8字节(64位)。 +核实IV格式选取正确(例:十六进制或UTF8)。`); + } + + input = Utils.convertToByteString(input, inputType); + + const decipher = forge.cipher.createDecipher("3DES-" + mode, + key.length === 16 ? key + key.substring(0, 8) : key); + + /* Allow for a "no padding" mode */ + if (noPadding) { + decipher.mode.unpad = function(output, options) { + return true; + }; + } + + decipher.start({iv: iv}); + decipher.update(forge.util.createBuffer(input)); + const result = decipher.finish(); + + if (result) { + return outputType === "十六进制" ? decipher.output.toHex() : decipher.output.getBytes(); + } else { + throw new OperationError("无法解密,参数错误"); + } + } + +} + +export default TripleDESDecrypt; diff --git a/plugins/srktoolbox/src/core/operations/TripleDESEncrypt.mjs b/plugins/srktoolbox/src/core/operations/TripleDESEncrypt.mjs new file mode 100644 index 00000000..a2a20198 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/TripleDESEncrypt.mjs @@ -0,0 +1,99 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import forge from "node-forge"; + +/** + * Triple DES Encrypt operation + */ +class TripleDESEncrypt extends Operation { + + /** + * TripleDESEncrypt constructor + */ + constructor() { + super(); + + this.name = "3DES加密"; + this.module = "Ciphers"; + this.description = "Triple DES applies DES three times to each block to increase key size.

Key: Triple DES uses a key length of 24 bytes (192 bits).

You can generate a password-based key using one of the KDF operations.

IV: The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.

Padding: In CBC and ECB mode, PKCS#7 padding will be used."; + this.infoURL = "https://wikipedia.org/wiki/Triple_DES"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Key", + "type": "toggleString", + "value": "", + "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"] + }, + { + "name": "IV", + "type": "toggleString", + "value": "", + "toggleValues": ["Hex", "UTF8", "Latin1", "Base64"] + }, + { + "name": "模式", + "type": "option", + "value": ["CBC", "CFB", "OFB", "CTR", "ECB"] + }, + { + "name": "输入", + "type": "option", + "value": ["原始内容", "十六进制"] + }, + { + "name": "输出", + "type": "option", + "value": ["十六进制", "原始内容"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const key = Utils.convertToByteString(args[0].string, args[0].option), + iv = Utils.convertToByteArray(args[1].string, args[1].option), + mode = args[2], + inputType = args[3], + outputType = args[4]; + + if (key.length !== 24 && key.length !== 16) { + throw new OperationError(`无效的key长度: ${key.length} 字节 + +Triple DES uses a key length of 24 bytes (192 bits).`); + } + if (iv.length !== 8 && mode !== "ECB") { + throw new OperationError(`无效的IV长度: ${iv.length} 字节 + +三重DES的IV长度为8字节(64位)。 +核实IV格式选取正确(例:十六进制或UTF8)。`); + } + + input = Utils.convertToByteString(input, inputType); + + const cipher = forge.cipher.createCipher("3DES-" + mode, + key.length === 16 ? key + key.substring(0, 8) : key); + cipher.start({iv: iv}); + cipher.update(forge.util.createBuffer(input)); + cipher.finish(); + + return outputType === "十六进制" ? cipher.output.toHex() : cipher.output.getBytes(); + } + +} + +export default TripleDESEncrypt; diff --git a/plugins/srktoolbox/src/core/operations/Typex.mjs b/plugins/srktoolbox/src/core/operations/Typex.mjs new file mode 100644 index 00000000..5c9d952e --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Typex.mjs @@ -0,0 +1,253 @@ +/** + * Emulation of the Typex machine. + * + * Tested against a genuine Typex machine using a variety of inputs + * and settings to confirm correctness. + * + * @author s2224834 + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {LETTERS, Reflector} from "../lib/Enigma.mjs"; +import {ROTORS, REFLECTORS, TypexMachine, Plugboard, Rotor} from "../lib/Typex.mjs"; + +/** + * Typex operation + */ +class Typex extends Operation { + /** + * Typex constructor + */ + constructor() { + super(); + + this.name = "Typex"; + this.module = "Bletchley"; + this.description = "Encipher/decipher with the WW2 Typex machine.

Typex was originally built by the British Royal Air Force prior to WW2, and is based on the Enigma machine with some improvements made, including using five rotors with more stepping points and interchangeable wiring cores. It was used across the British and Commonwealth militaries. A number of later variants were produced; here we simulate a WW2 era Mark 22 Typex with plugboards for the reflector and input. Typex rotors were changed regularly and none are public: a random example set are provided.

To configure the reflector plugboard, enter a string of connected pairs of letters in the reflector box, e.g. AB CD EF connects A to B, C to D, and E to F (you'll need to connect every letter). There is also an input plugboard: unlike Enigma's plugboard, it's not restricted to pairs, so it's entered like a rotor (without stepping). To create your own rotor, enter the letters that the rotor maps A to Z to, in order, optionally followed by < then a list of stepping points.

More detailed descriptions of the Enigma, Typex and Bombe operations can be found here."; + this.infoURL = "https://wikipedia.org/wiki/Typex"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "1st (left-hand) rotor", + type: "editableOption", + value: ROTORS, + defaultIndex: 0 + }, + { + name: "1st rotor reversed", + type: "boolean", + value: false + }, + { + name: "1st rotor ring setting", + type: "option", + value: LETTERS + }, + { + name: "1st rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "2nd rotor", + type: "editableOption", + value: ROTORS, + defaultIndex: 1 + }, + { + name: "2nd rotor reversed", + type: "boolean", + value: false + }, + { + name: "2nd rotor ring setting", + type: "option", + value: LETTERS + }, + { + name: "2nd rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "3rd (middle) rotor", + type: "editableOption", + value: ROTORS, + defaultIndex: 2 + }, + { + name: "3rd rotor reversed", + type: "boolean", + value: false + }, + { + name: "3rd rotor ring setting", + type: "option", + value: LETTERS + }, + { + name: "3rd rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "4th (static) rotor", + type: "editableOption", + value: ROTORS, + defaultIndex: 3 + }, + { + name: "4th rotor reversed", + type: "boolean", + value: false + }, + { + name: "4th rotor ring setting", + type: "option", + value: LETTERS + }, + { + name: "4th rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "5th (right-hand, static) rotor", + type: "editableOption", + value: ROTORS, + defaultIndex: 4 + }, + { + name: "5th rotor reversed", + type: "boolean", + value: false + }, + { + name: "5th rotor ring setting", + type: "option", + value: LETTERS + }, + { + name: "5th rotor initial value", + type: "option", + value: LETTERS + }, + { + name: "Reflector", + type: "editableOption", + value: REFLECTORS + }, + { + name: "Plugboard", + type: "string", + value: "" + }, + { + name: "Typex keyboard emulation", + type: "option", + value: ["None", "Encrypt", "Decrypt"] + }, + { + name: "Strict output", + hint: "Remove non-alphabet letters and group output", + type: "boolean", + value: true + }, + ]; + } + + /** + * Helper - for ease of use rotors are specified as a single string; this + * method breaks the spec string into wiring and steps parts. + * + * @param {string} rotor - Rotor specification string. + * @param {number} i - For error messages, the number of this rotor. + * @returns {string[]} + */ + parseRotorStr(rotor, i) { + if (rotor === "") { + throw new OperationError(`Rotor ${i} must be provided.`); + } + if (!rotor.includes("<")) { + return [rotor, ""]; + } + return rotor.split("<", 2); + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const reflectorstr = args[20]; + const plugboardstr = args[21]; + const typexKeyboard = args[22]; + const removeOther = args[23]; + const rotors = []; + for (let i=0; i<5; i++) { + const [rotorwiring, rotorsteps] = this.parseRotorStr(args[i*4]); + rotors.push(new Rotor(rotorwiring, rotorsteps, args[i*4 + 1], args[i*4+2], args[i*4+3])); + } + // Rotors are handled in reverse + rotors.reverse(); + const reflector = new Reflector(reflectorstr); + let plugboardstrMod = plugboardstr; + if (plugboardstrMod === "") { + plugboardstrMod = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + } + const plugboard = new Plugboard(plugboardstrMod); + if (removeOther) { + if (typexKeyboard === "Encrypt") { + input = input.replace(/[^A-Za-z0-9 /%£()',.-]/g, ""); + } else { + input = input.replace(/[^A-Za-z]/g, ""); + } + } + const typex = new TypexMachine(rotors, reflector, plugboard, typexKeyboard); + let result = typex.crypt(input); + if (removeOther && typexKeyboard !== "Decrypt") { + // Five character cipher groups is traditional + result = result.replace(/([A-Z]{5})(?!$)/g, "$1 "); + } + return result; + } + + /** + * Highlight Typex + * This is only possible if we're passing through non-alphabet characters. + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + if (args[18] === false) { + return pos; + } + } + + /** + * Highlight Typex in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + if (args[18] === false) { + return pos; + } + } + +} + +export default Typex; diff --git a/plugins/srktoolbox/src/core/operations/UNIXTimestampToWindowsFiletime.mjs b/plugins/srktoolbox/src/core/operations/UNIXTimestampToWindowsFiletime.mjs new file mode 100644 index 00000000..4110a6e1 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/UNIXTimestampToWindowsFiletime.mjs @@ -0,0 +1,95 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import BigNumber from "bignumber.js"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * UNIX Timestamp to Windows Filetime operation + */ +class UNIXTimestampToWindowsFiletime extends Operation { + + /** + * UNIXTimestampToWindowsFiletime constructor + */ + constructor() { + super(); + + this.name = "UNIX时间戳转Windows Filetime"; + this.module = "Default"; + this.description = "将UNIX时间戳转换为Windows Filetime数值。br>
Windows Filetime是对应从1601年1月1日(UTC)开始的以100纳秒为单位的64位数值。

UNIX 时间戳是对应从1970年1月1日(UTC)开始的以秒为单位的32位数值。

此操作也支持不同的UNIX时间单位如毫秒、微秒和纳秒。"; + this.infoURL = "https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).aspx"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "输入单位", + "type": "option", + "value": ["秒 (s)", "毫秒 (ms)", "微秒 (μs)", "纳秒 (ns)"] + }, + { + "name": "输出格式", + "type": "option", + "value": ["十进制", "十六进制 (大端序)", "十六进制 (小端序)"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [units, format] = args; + + if (!input) return ""; + + input = new BigNumber(input); + + if (units === "秒 (s)") { + input = input.multipliedBy(new BigNumber("10000000")); + } else if (units === "毫秒 (ms)") { + input = input.multipliedBy(new BigNumber("10000")); + } else if (units === "微秒 (μs)") { + input = input.multipliedBy(new BigNumber("10")); + } else if (units === "纳秒 (ns)") { + input = input.dividedBy(new BigNumber("100")); + } else { + throw new OperationError("无效单位"); + } + + input = input.plus(new BigNumber("116444736000000000")); + + let result; + if (format.startsWith("十六进制")) { + result = input.toString(16); + } else { + result = input.toFixed(); + } + + if (format === "十六进制 (小端序)") { + // Swap endianness + let flipped = ""; + for (let i = result.length - 2; i >= 0; i -= 2) { + flipped += result.charAt(i); + flipped += result.charAt(i + 1); + } + if (result.length % 2 !== 0) { + flipped += "0" + result.charAt(0); + } + result = flipped; + } + + return result; + } + +} + +export default UNIXTimestampToWindowsFiletime; diff --git a/plugins/srktoolbox/src/core/operations/URLDecode.mjs b/plugins/srktoolbox/src/core/operations/URLDecode.mjs new file mode 100644 index 00000000..6923f774 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/URLDecode.mjs @@ -0,0 +1,61 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * URL Decode operation + */ +class URLDecode extends Operation { + + /** + * URLDecode constructor + */ + constructor() { + super(); + + this.name = "URL解码"; + this.module = "URL"; + this.description = "把URI/URL百分号编码的内容解码为原始内容。

例: %3d 解码为 ="; + this.infoURL = "https://wikipedia.org/wiki/Percent-encoding"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Treat \"+\" as space", + "type": "boolean", + "value": true + }, + ]; + this.checks = [ + { + pattern: ".*(?:%[\\da-f]{2}.*){4}", + flags: "i", + args: [] + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const plusIsSpace = args[0]; + const data = plusIsSpace ? input.replace(/\+/g, "%20") : input; + try { + return decodeURIComponent(data); + } catch (err) { + return unescape(data); + } + } + +} + +export default URLDecode; diff --git a/plugins/srktoolbox/src/core/operations/URLEncode.mjs b/plugins/srktoolbox/src/core/operations/URLEncode.mjs new file mode 100644 index 00000000..d7c037cc --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/URLEncode.mjs @@ -0,0 +1,71 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; + +/** + * URL Encode operation + */ +class URLEncode extends Operation { + + /** + * URLEncode constructor + */ + constructor() { + super(); + + this.name = "URL编码"; + this.module = "URL"; + this.description = "把特殊字符编码为百分号开头的形式,即URI/URL编码。

例: = 编码为 %3d"; + this.infoURL = "https://wikipedia.org/wiki/Percent-encoding"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "编码所有特殊字符", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const encodeAll = args[0]; + return encodeAll ? this.encodeAllChars(input) : encodeURI(input); + } + + /** + * Encode characters in URL outside of encodeURI() function spec + * + * @param {string} str + * @returns {string} + */ + encodeAllChars (str) { + // TODO Do this programmatically + return encodeURIComponent(str) + .replace(/!/g, "%21") + .replace(/#/g, "%23") + .replace(/'/g, "%27") + .replace(/\(/g, "%28") + .replace(/\)/g, "%29") + .replace(/\*/g, "%2A") + .replace(/-/g, "%2D") + .replace(/\./g, "%2E") + .replace(/_/g, "%5F") + .replace(/~/g, "%7E"); + } + +} + + +export default URLEncode; diff --git a/plugins/srktoolbox/src/core/operations/UnescapeString.mjs b/plugins/srktoolbox/src/core/operations/UnescapeString.mjs new file mode 100644 index 00000000..30e283a8 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/UnescapeString.mjs @@ -0,0 +1,43 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Unescape string operation + */ +class UnescapeString extends Operation { + + /** + * UnescapeString constructor + */ + constructor() { + super(); + + this.name = "字符串转义恢复"; + this.module = "Default"; + this.description = "将已经转义的字符串恢复。例如,Don\\'t stop me now 恢复为 Don't stop me now

支持以下的字符转义:
  • \\n (换行,LF)
  • \\r (回车,CR)
  • \\t (制表符)
  • \\b (退格)
  • \\f (换页,FF)
  • \\xnn (十六进制,n是0到f)
  • \\\\ (反斜杠)
  • \\' (单引号)
  • \\" (双引号)
  • \\unnnn (Unicode字符)
  • \\u{nnnnnn} (Unicode码点)
"; + this.infoURL = "https://wikipedia.org/wiki/Escape_sequence"; + this.inputType = "string"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + return Utils.parseEscapedChars(input); + } + +} + +export default UnescapeString; diff --git a/plugins/srktoolbox/src/core/operations/UnescapeUnicodeCharacters.mjs b/plugins/srktoolbox/src/core/operations/UnescapeUnicodeCharacters.mjs new file mode 100644 index 00000000..199f3411 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/UnescapeUnicodeCharacters.mjs @@ -0,0 +1,93 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Unescape Unicode Characters operation + */ +class UnescapeUnicodeCharacters extends Operation { + + /** + * UnescapeUnicodeCharacters constructor + */ + constructor() { + super(); + + this.name = "Unicode转义恢复"; + this.module = "Default"; + this.description = "把转义后的Unicode字符恢复成原本形式。

支持以下前缀:
  • \\u
  • %u
  • U+
例: \\u03c3\\u03bf\\u03c5 解码为 σου"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "前缀", + "type": "option", + "value": ["\\u", "%u", "U+"] + } + ]; + this.checks = [ + { + pattern: "\\\\u(?:[\\da-f]{4,6})", + flags: "i", + args: ["\\u"] + }, + { + pattern: "%u(?:[\\da-f]{4,6})", + flags: "i", + args: ["%u"] + }, + { + pattern: "U\\+(?:[\\da-f]{4,6})", + flags: "i", + args: ["U+"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const prefix = prefixToRegex[args[0]], + regex = new RegExp(prefix+"([a-f\\d]{4})", "ig"); + let output = "", + m, + i = 0; + + while ((m = regex.exec(input))) { + // Add up to match + output += input.slice(i, m.index); + + // Add match + output += Utils.chr(parseInt(m[1], 16)); + + i = regex.lastIndex; + } + + // Add all after final match + output += input.slice(i, input.length); + + return output; + } + +} + +/** + * Lookup table to add prefixes to unicode delimiters so that they can be used in a regex. + */ +const prefixToRegex = { + "\\u": "\\\\u", + "%u": "%u", + "U+": "U\\+" +}; + +export default UnescapeUnicodeCharacters; diff --git a/plugins/srktoolbox/src/core/operations/UnicodeTextFormat.mjs b/plugins/srktoolbox/src/core/operations/UnicodeTextFormat.mjs new file mode 100644 index 00000000..6cf7e8af --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/UnicodeTextFormat.mjs @@ -0,0 +1,69 @@ +/** + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; + +/** + * Unicode Text Format operation + */ +class UnicodeTextFormat extends Operation { + + /** + * UnicodeTextFormat constructor + */ + constructor() { + super(); + + this.name = "Unicode文本格式"; + this.module = "Default"; + this.description = "使用Unicode组合字符为纯文本添加格式。"; + this.infoURL = "https://wikipedia.org/wiki/Combining_character"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "下划线", + type: "boolean", + value: "false" + }, + { + name: "删除线", + type: "boolean", + value: "false" + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const [underline, strikethrough] = args; + let output = input.map(char => [char]); + if (strikethrough) { + output = output.map(charFormat => { + charFormat.push(...Utils.strToUtf8ByteArray("\u0336")); + return charFormat; + }); + } + if (underline) { + output = output.map(charFormat => { + charFormat.push(...Utils.strToUtf8ByteArray("\u0332")); + return charFormat; + }); + } + // return output.flat(); - Not supported in Node 10, polyfilled + return [].concat(...output); + } + +} + +export default UnicodeTextFormat; diff --git a/plugins/srktoolbox/src/core/operations/Unique.mjs b/plugins/srktoolbox/src/core/operations/Unique.mjs new file mode 100644 index 00000000..5dce1a31 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Unique.mjs @@ -0,0 +1,70 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {INPUT_DELIM_OPTIONS} from "../lib/Delim.mjs"; + +/** + * Unique operation + */ +class Unique extends Operation { + + /** + * Unique constructor + */ + constructor() { + super(); + + this.name = "去重"; + this.module = "Default"; + this.description = "从输入移除重复的字符串。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "分隔符", + type: "option", + value: INPUT_DELIM_OPTIONS + }, + { + name: "显示个数", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const delim = Utils.charRep(args[0]), + count = args[1]; + + if (count) { + const valMap = input.split(delim).reduce((acc, curr) => { + if (Object.prototype.hasOwnProperty.call(acc, curr)) { + acc[curr]++; + } else { + acc[curr] = 1; + } + return acc; + }, {}); + + return Object.keys(valMap).map(val => `${valMap[val]} ${val}`).join(delim); + } else { + return input.split(delim).unique().join(delim); + } + } + +} + +export default Unique; diff --git a/plugins/srktoolbox/src/core/operations/Untar.mjs b/plugins/srktoolbox/src/core/operations/Untar.mjs new file mode 100644 index 00000000..253f5292 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Untar.mjs @@ -0,0 +1,111 @@ +/** + * @author tlwr [toby@toby.codes] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import Stream from "../lib/Stream.mjs"; + +/** + * Untar operation + */ +class Untar extends Operation { + + /** + * Untar constructor + */ + constructor() { + super(); + + this.name = "Untar"; + this.module = "Compression"; + this.description = "解包 tarball 并按文件展示内容。"; + this.infoURL = "https://wikipedia.org/wiki/Tar_(computing)"; + this.inputType = "ArrayBuffer"; + this.outputType = "List"; + this.presentType = "html"; + this.args = []; + this.checks = [ + { + "pattern": "^.{257}\\x75\\x73\\x74\\x61\\x72", + "flags": "", + "args": [] + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {List} + */ + run(input, args) { + input = new Uint8Array(input); + const stream = new Stream(input), + files = []; + + while (stream.hasMore()) { + const dataPosition = stream.position + 512; + + const file = { + fileName: stream.readString(100), + fileMode: stream.readString(8), + ownerUID: stream.readString(8), + ownerGID: stream.readString(8), + size: parseInt(stream.readString(12), 8), // Octal + lastModTime: new Date(1000 * parseInt(stream.readString(12), 8)), // Octal + checksum: stream.readString(8), + type: stream.readString(1), + linkedFileName: stream.readString(100), + USTARFormat: stream.readString(6).indexOf("ustar") >= 0, + }; + + if (file.USTARFormat) { + file.version = stream.readString(2); + file.ownerUserName = stream.readString(32); + file.ownerGroupName = stream.readString(32); + file.deviceMajor = stream.readString(8); + file.deviceMinor = stream.readString(8); + file.filenamePrefix = stream.readString(155); + } + + stream.position = dataPosition; + + if (file.type === "0") { + // File + let endPosition = stream.position + file.size; + if (file.size % 512 !== 0) { + endPosition += 512 - (file.size % 512); + } + + file.bytes = stream.getBytes(file.size); + files.push(new File([new Uint8Array(file.bytes)], file.fileName)); + stream.position = endPosition; + } else if (file.type === "5") { + // Directory + files.push(new File([new Uint8Array(file.bytes)], file.fileName)); + } else { + // Symlink or empty bytes + } + } + + return files; + } + + /** + * Displays the files in HTML for web apps. + * + * @param {File[]} files + * @returns {html} + */ + async present(files) { + return await Utils.displayFilesAsHTML(files); + } + +} + +export default Untar; diff --git a/plugins/srktoolbox/src/core/operations/Unzip.mjs b/plugins/srktoolbox/src/core/operations/Unzip.mjs new file mode 100644 index 00000000..11366128 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Unzip.mjs @@ -0,0 +1,85 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import unzip from "zlibjs/bin/unzip.min.js"; + +const Zlib = unzip.Zlib; + +/** + * Unzip operation + */ +class Unzip extends Operation { + + /** + * Unzip constructor + */ + constructor() { + super(); + + this.name = "Unzip"; + this.module = "Compression"; + this.description = "使用PKZIP算法解压缩并按文件显示内容,支持密码。"; + this.infoURL = "https://wikipedia.org/wiki/Zip_(file_format)"; + this.inputType = "ArrayBuffer"; + this.outputType = "List"; + this.presentType = "html"; + this.args = [ + { + name: "密码", + type: "binaryString", + value: "" + }, + { + name: "验证结果", + type: "boolean", + value: false + } + ]; + this.checks = [ + { + pattern: "^\\x50\\x4b(?:\\x03|\\x05|\\x07)(?:\\x04|\\x06|\\x08)", + flags: "", + args: ["", false] + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {File[]} + */ + run(input, args) { + const options = { + password: Utils.strToByteArray(args[0]), + verify: args[1] + }, + unzip = new Zlib.Unzip(new Uint8Array(input), options), + filenames = unzip.getFilenames(); + + return filenames.map(fileName => { + const bytes = unzip.decompress(fileName); + return new File([bytes], fileName); + }); + } + + /** + * Displays the files in HTML for web apps. + * + * @param {File[]} files + * @returns {html} + */ + async present(files) { + return await Utils.displayFilesAsHTML(files); + } + +} + +export default Unzip; diff --git a/plugins/srktoolbox/src/core/operations/VarIntDecode.mjs b/plugins/srktoolbox/src/core/operations/VarIntDecode.mjs new file mode 100644 index 00000000..c036eb2c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/VarIntDecode.mjs @@ -0,0 +1,59 @@ +/** + * @author GCHQ Contributor [3] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Protobuf from "../lib/Protobuf.mjs"; + +/** + * VarInt Decode operation + */ +class VarIntDecode extends Operation { + + /** + * VarIntDecode constructor + */ + constructor() { + super(); + + this.name = "VarInt解码"; + this.module = "Default"; + this.description = "把VarInt编码的整数进行解码。VarInt是效率较高的编码变长整数的方式,通常用于Protobuf。"; + this.infoURL = "https://developers.google.com/protocol-buffers/docs/encoding#varints"; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = []; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {number} + */ + run(input, args) { + try { + if (typeof BigInt === "function") { + let result = BigInt(0); + let offset = BigInt(0); + for (let i = 0; i < input.length; i++) { + result |= BigInt(input[i] & 0x7f) << offset; + if (!(input[i] & 0x80)) break; + offset += BigInt(7); + } + return result.toString(); + } else { + return Protobuf.varIntDecode(input).toString(); + } + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default VarIntDecode; diff --git a/plugins/srktoolbox/src/core/operations/VarIntEncode.mjs b/plugins/srktoolbox/src/core/operations/VarIntEncode.mjs new file mode 100644 index 00000000..90fdb79a --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/VarIntEncode.mjs @@ -0,0 +1,60 @@ +/** + * @author GCHQ Contributor [3] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Protobuf from "../lib/Protobuf.mjs"; + +/** + * VarInt Encode operation + */ +class VarIntEncode extends Operation { + + /** + * VarIntEncode constructor + */ + constructor() { + super(); + + this.name = "VarInt编码"; + this.module = "Default"; + this.description = "把整数编码成VarInt。VarInt是效率较高的编码变长整数的方式,通常用于Protobuf。"; + this.infoURL = "https://developers.google.com/protocol-buffers/docs/encoding#varints"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + try { + if (typeof BigInt === "function") { + let value = BigInt(input); + if (value < 0) throw new OperationError("Negative values cannot be represented as VarInt"); + const result = []; + while (value >= 0x80) { + result.push(Number(value & BigInt(0x7f)) | 0x80); + value >>= BigInt(7); + } + result.push(Number(value)); + return result; + } else { + return Protobuf.varIntEncode(Number(input)); + } + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default VarIntEncode; diff --git a/plugins/srktoolbox/src/core/operations/ViewBitPlane.mjs b/plugins/srktoolbox/src/core/operations/ViewBitPlane.mjs new file mode 100644 index 00000000..4aab244b --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ViewBitPlane.mjs @@ -0,0 +1,105 @@ +/** + * @author Ge0rg3 [georgeomnet+cyberchef@gmail.com] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { isImage } from "../lib/FileType.mjs"; +import { toBase64 } from "../lib/Base64.mjs"; +import { Jimp } from "jimp"; + +/** + * View Bit Plane operation + */ +class ViewBitPlane extends Operation { + /** + * ViewBitPlane constructor + */ + constructor() { + super(); + + this.name = "查看位平面"; + this.module = "Image"; + this.description = + "提取并显示任何给定图像的位平面。每张图像显示原图像当中每个像素字节数据的给定一个位,通常用于图像隐写术。"; + this.infoURL = "https://wikipedia.org/wiki/Bit_plane"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.presentType = "html"; + this.args = [ + { + name: "颜色", + type: "option", + value: COLOUR_OPTIONS, + }, + { + name: "位", + type: "number", + value: 0, + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + async run(input, args) { + if (!isImage(input)) + throw new OperationError("请输入合法的图像文件。"); + + const [colour, bit] = args, + parsedImage = await Jimp.read(input), + width = parsedImage.bitmap.width, + height = parsedImage.bitmap.height, + colourIndex = COLOUR_OPTIONS.indexOf(colour), + bitIndex = 7 - bit; + + if (bit < 0 || bit > 7) { + throw new OperationError( + "错误:位参数只能是 0 到 7", + ); + } + + let pixel, bin, newPixelValue; + + parsedImage.scan(0, 0, width, height, function (x, y, idx) { + pixel = this.bitmap.data[idx + colourIndex]; + bin = Utils.bin(pixel); + newPixelValue = 255; + + if (bin.charAt(bitIndex) === "1") newPixelValue = 0; + + for (let i = 0; i < 3; i++) { + this.bitmap.data[idx + i] = newPixelValue; + } + this.bitmap.data[idx + 3] = 255; + }); + + const imageBuffer = await parsedImage.getBuffer(parsedImage.mime); + + return new Uint8Array(imageBuffer).buffer; + } + + /** + * Displays the extracted data as an image for web apps. + * @param {ArrayBuffer} data + * @returns {html} + */ + present(data) { + if (!data.byteLength) return ""; + const type = isImage(data); + + return ``; + } +} + +const COLOUR_OPTIONS = ["Red", "Green", "Blue", "Alpha"]; + +export default ViewBitPlane; diff --git "a/plugins/srktoolbox/src/core/operations/Vigen\347\214\253reDecode.mjs" "b/plugins/srktoolbox/src/core/operations/Vigen\347\214\253reDecode.mjs" new file mode 100644 index 00000000..666465c8 --- /dev/null +++ "b/plugins/srktoolbox/src/core/operations/Vigen\347\214\253reDecode.mjs" @@ -0,0 +1,104 @@ +/** + * @author Matt C [matt@artemisbot.uk] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +/** + * Vigenère Decode operation + */ +class VigenèreDecode extends Operation { + + /** + * VigenèreDecode constructor + */ + constructor() { + super(); + + this.name = "维吉尼亚密码解密"; + this.module = "Ciphers"; + this.description = "维吉尼亚密码(又译维热纳尔密码)是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。"; + this.infoURL = "https://wikipedia.org/wiki/Vigenère_cipher"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Key", + "type": "string", + "value": "" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const alphabet = "abcdefghijklmnopqrstuvwxyz", + key = args[0].toLowerCase(); + let output = "", + fail = 0, + keyIndex, + msgIndex, + chr; + + if (!key) throw new OperationError("未输入Key"); + if (!/^[a-zA-Z]+$/.test(key)) throw new OperationError("Key只能是字母"); + + for (let i = 0; i < input.length; i++) { + if (alphabet.indexOf(input[i]) >= 0) { + chr = key[(i - fail) % key.length]; + keyIndex = alphabet.indexOf(chr); + msgIndex = alphabet.indexOf(input[i]); + // Subtract indexes from each other, add 26 just in case the value is negative, + // modulo to remove if necessary + output += alphabet[(msgIndex - keyIndex + alphabet.length) % 26]; + } else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) { + chr = key[(i - fail) % key.length].toLowerCase(); + keyIndex = alphabet.indexOf(chr); + msgIndex = alphabet.indexOf(input[i].toLowerCase()); + output += alphabet[(msgIndex + alphabet.length - keyIndex) % 26].toUpperCase(); + } else { + output += input[i]; + fail++; + } + } + + return output; + } + + /** + * Highlight Vigenère Decode + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight Vigenère Decode in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default VigenèreDecode; diff --git "a/plugins/srktoolbox/src/core/operations/Vigen\347\214\253reEncode.mjs" "b/plugins/srktoolbox/src/core/operations/Vigen\347\214\253reEncode.mjs" new file mode 100644 index 00000000..84fd6968 --- /dev/null +++ "b/plugins/srktoolbox/src/core/operations/Vigen\347\214\253reEncode.mjs" @@ -0,0 +1,109 @@ +/** + * @author Matt C [matt@artemisbot.uk] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Vigenère Encode operation + */ +class VigenèreEncode extends Operation { + + /** + * VigenèreEncode constructor + */ + constructor() { + super(); + + this.name = "维吉尼亚密码加密"; + this.module = "Ciphers"; + this.description = "维吉尼亚密码(又译维热纳尔密码)是使用一系列凯撒密码组成密码字母表的加密算法,属于多表密码的一种简单形式。"; + this.infoURL = "https://wikipedia.org/wiki/Vigenère_cipher"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "Key", + "type": "string", + "value": "" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const alphabet = "abcdefghijklmnopqrstuvwxyz", + key = args[0].toLowerCase(); + let output = "", + fail = 0, + keyIndex, + msgIndex, + chr; + + if (!key) throw new OperationError("未输入Key"); + if (!/^[a-zA-Z]+$/.test(key)) throw new OperationError("Key只能是字母"); + + for (let i = 0; i < input.length; i++) { + if (alphabet.indexOf(input[i]) >= 0) { + // Get the corresponding character of key for the current letter, accounting + // for chars not in alphabet + chr = key[(i - fail) % key.length]; + // Get the location in the vigenere square of the key char + keyIndex = alphabet.indexOf(chr); + // Get the location in the vigenere square of the message char + msgIndex = alphabet.indexOf(input[i]); + // Get the encoded letter by finding the sum of indexes modulo 26 and finding + // the letter corresponding to that + output += alphabet[(keyIndex + msgIndex) % 26]; + } else if (alphabet.indexOf(input[i].toLowerCase()) >= 0) { + chr = key[(i - fail) % key.length].toLowerCase(); + keyIndex = alphabet.indexOf(chr); + msgIndex = alphabet.indexOf(input[i].toLowerCase()); + output += alphabet[(keyIndex + msgIndex) % 26].toUpperCase(); + } else { + output += input[i]; + fail++; + } + } + + return output; + } + + /** + * Highlight Vigenère Encode + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight Vigenère Encode in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default VigenèreEncode; diff --git a/plugins/srktoolbox/src/core/operations/Whirlpool.mjs b/plugins/srktoolbox/src/core/operations/Whirlpool.mjs new file mode 100644 index 00000000..0c76505c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Whirlpool.mjs @@ -0,0 +1,57 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {runHash} from "../lib/Hash.mjs"; + +/** + * Whirlpool operation + */ +class Whirlpool extends Operation { + + /** + * Whirlpool constructor + */ + constructor() { + super(); + + this.name = "Whirlpool"; + this.module = "Crypto"; + this.description = "Whirlpool是由Vincent Rijmen和Paulo S. L. M. Barreto在2000年公开的加密算法。

存在多个变种:
  • Whirlpool-0是2000年发布的最初版本。
  • Whirlpool-T是在2001年发布的第一个更新版本,改进了s-box的生成过程。
  • Whirlpool是最新版本,于2003年发布,修复了diffusion matrix中的缺陷。
"; + this.infoURL = "https://wikipedia.org/wiki/Whirlpool_(cryptography)"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "变种", + type: "option", + value: ["Whirlpool", "Whirlpool-T", "Whirlpool-0"] + }, + { + name: "轮数", + type: "number", + value: 10, + min: 1, + max: 10 + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const variant = args[0].toLowerCase(); + return runHash(variant, input, {rounds: args[1]}); + } + +} + +export default Whirlpool; diff --git a/plugins/srktoolbox/src/core/operations/WindowsFiletimeToUNIXTimestamp.mjs b/plugins/srktoolbox/src/core/operations/WindowsFiletimeToUNIXTimestamp.mjs new file mode 100644 index 00000000..25f4aad7 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/WindowsFiletimeToUNIXTimestamp.mjs @@ -0,0 +1,92 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2017 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import BigNumber from "bignumber.js"; +import OperationError from "../errors/OperationError.mjs"; + +/** + * Windows Filetime to UNIX Timestamp operation + */ +class WindowsFiletimeToUNIXTimestamp extends Operation { + + /** + * WindowsFiletimeToUNIXTimestamp constructor + */ + constructor() { + super(); + + this.name = "Windows Filetime转UNIX时间戳"; + this.module = "Default"; + this.description = "将Windows Filetime值转换为UNIX时间戳。

Windows Filetime是对应从1601年1月1日(UTC)开始的以100纳秒为单位的64位数值。

UNIX 时间戳是对应从1970年1月1日(UTC)开始的以秒为单位的32位数值。

此操作也支持不同的UNIX时间单位如毫秒、微秒和纳秒。"; + this.infoURL = "https://msdn.microsoft.com/en-us/library/windows/desktop/ms724284(v=vs.85).aspx"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "输出单位", + "type": "option", + "value": ["秒 (s)", "毫秒 (ms)", "微秒 (μs)", "纳秒 (ns)"] + }, + { + "name": "输入格式", + "type": "option", + "value": ["十进制", "十六进制 (大端序)", "十六进制 (小端序)"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [units, format] = args; + + if (!input) return ""; + + if (format === "Hex (小端序)") { + // Swap endianness + let result = ""; + if (input.length % 2 !== 0) { + result += input.charAt(input.length - 1); + } + for (let i = input.length - input.length % 2 - 2; i >= 0; i -= 2) { + result += input.charAt(i); + result += input.charAt(i + 1); + } + input = result; + } + + if (format.startsWith("十六进制")) { + input = new BigNumber(input, 16); + } else { + input = new BigNumber(input); + } + + input = input.minus(new BigNumber("116444736000000000")); + + if (units === "秒 (s)") { + input = input.dividedBy(new BigNumber("10000000")); + } else if (units === "毫秒 (ms)") { + input = input.dividedBy(new BigNumber("10000")); + } else if (units === "微秒 (μs)") { + input = input.dividedBy(new BigNumber("10")); + } else if (units === "纳秒 (ns)") { + input = input.multipliedBy(new BigNumber("100")); + } else { + throw new OperationError("无效单位"); + } + + return input.toFixed(); + } + +} + +export default WindowsFiletimeToUNIXTimestamp; diff --git a/plugins/srktoolbox/src/core/operations/XKCDRandomNumber.mjs b/plugins/srktoolbox/src/core/operations/XKCDRandomNumber.mjs new file mode 100644 index 00000000..ba9b5e27 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/XKCDRandomNumber.mjs @@ -0,0 +1,41 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; + +/** + * XKCD Random Number operation + */ +class XKCDRandomNumber extends Operation { + + /** + * XKCDRandomNumber constructor + */ + constructor() { + super(); + + this.name = "XKCD Random Number"; + this.module = "Default"; + this.description = "RFC 1149.5 specifies 4 as the standard IEEE-vetted random number."; + this.infoURL = "https://xkcd.com/221/"; + this.inputType = "string"; + this.outputType = "number"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {number} + */ + run(input, args) { + return 4; // chosen by fair dice roll. + // guaranteed to be random. + } + +} + +export default XKCDRandomNumber; diff --git a/plugins/srktoolbox/src/core/operations/XMLBeautify.mjs b/plugins/srktoolbox/src/core/operations/XMLBeautify.mjs new file mode 100644 index 00000000..b0987b5c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/XMLBeautify.mjs @@ -0,0 +1,49 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import vkbeautify from "vkbeautify"; +import Operation from "../Operation.mjs"; + +/** + * XML Beautify operation + */ +class XMLBeautify extends Operation { + + /** + * XMLBeautify constructor + */ + constructor() { + super(); + + this.name = "XML美化"; + this.module = "Code"; + this.description = "为eXtensible Markup Language (XML)代码添加缩进与美化。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "缩进", + "type": "binaryShortString", + "value": "\\t" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const indentStr = args[0]; + return vkbeautify.xml(input, indentStr); + } + +} + +export default XMLBeautify; diff --git a/plugins/srktoolbox/src/core/operations/XMLMinify.mjs b/plugins/srktoolbox/src/core/operations/XMLMinify.mjs new file mode 100644 index 00000000..10bd85c0 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/XMLMinify.mjs @@ -0,0 +1,49 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import vkbeautify from "vkbeautify"; +import Operation from "../Operation.mjs"; + +/** + * XML Minify operation + */ +class XMLMinify extends Operation { + + /** + * XMLMinify constructor + */ + constructor() { + super(); + + this.name = "XML压缩"; + this.module = "Code"; + this.description = "压缩eXtensible Markup Language (XML)代码(Minify/Uglify)。"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "保留注释", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const preserveComments = args[0]; + return vkbeautify.xmlmin(input, preserveComments); + } + +} + +export default XMLMinify; diff --git a/plugins/srktoolbox/src/core/operations/XOR.mjs b/plugins/srktoolbox/src/core/operations/XOR.mjs new file mode 100644 index 00000000..2ce1b55c --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/XOR.mjs @@ -0,0 +1,91 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import { bitOp, xor, BITWISE_OP_DELIMS } from "../lib/BitwiseOp.mjs"; + +/** + * XOR operation + */ +class XOR extends Operation { + + /** + * XOR constructor + */ + constructor() { + super(); + + this.name = "XOR"; + this.module = "Default"; + this.description = "用给定的key对输入做异或(XOR)操作。
例: fe023da5

选项:
保留Null:如果当前字节是0x00或者和key相同,则跳过不进行XOR操作。

加密方式:
  • 标准 - key保持不变
  • 输入差分 - key设置为上一个处理前的字节
  • 输出差分 - key设置为上一个处理后的字节
  • 级联 - key设置成输入当前处理位置后移1个字节的内容
"; + this.infoURL = "https://wikipedia.org/wiki/XOR"; + this.inputType = "ArrayBuffer"; + this.outputType = "byteArray"; + this.args = [ + { + "name": "Key", + "type": "toggleString", + "value": "", + "toggleValues": BITWISE_OP_DELIMS + }, + { + "name": "加密方式", + "type": "option", + "value": ["标准", "输入差分", "输出差分", "级联"] + }, + { + "name": "保留Null", + "type": "boolean", + "value": false + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + input = new Uint8Array(input); + const key = Utils.convertToByteArray(args[0].string || "", args[0].option), + [, scheme, nullPreserving] = args; + + return bitOp(input, key, xor, nullPreserving, scheme); + } + + /** + * Highlight XOR + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + return pos; + } + + /** + * Highlight XOR in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + return pos; + } + +} + +export default XOR; diff --git a/plugins/srktoolbox/src/core/operations/XORBruteForce.mjs b/plugins/srktoolbox/src/core/operations/XORBruteForce.mjs new file mode 100644 index 00000000..2d12e428 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/XORBruteForce.mjs @@ -0,0 +1,141 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import { bitOp, xor } from "../lib/BitwiseOp.mjs"; +import { toHex } from "../lib/Hex.mjs"; +import { isWorkerEnvironment } from "../Utils.mjs"; + +/** + * XOR Brute Force operation + */ +class XORBruteForce extends Operation { + + /** + * XORBruteForce constructor + */ + constructor() { + super(); + + this.name = "XOR暴力破解"; + this.module = "Default"; + this.description = "枚举所有的XOR解码结果。受限于浏览器性能,目前仅限key长度不超过2。

你可以输入一个已知的明文字符串来筛选结果(已知明文攻击中称为crib)。"; + this.infoURL = "https://wikipedia.org/wiki/Exclusive_or"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + "name": "Key长度", + "type": "number", + "value": 1 + }, + { + "name": "样本长度", + "type": "number", + "value": 100 + }, + { + "name": "样本偏移量", + "type": "number", + "value": 0 + }, + { + "name": "加密方式", + "type": "option", + "value": ["标准", "输入差分", "输出差分"] + }, + { + "name": "保留Null", + "type": "boolean", + "value": false + }, + { + "name": "输出key", + "type": "boolean", + "value": true + }, + { + "name": "输出十六进制", + "type": "boolean", + "value": false + }, + { + "name": "Crib(已知明文部分)", + "type": "binaryString", + "value": "" + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + input = new Uint8Array(input); + const [ + keyLength, + sampleLength, + sampleOffset, + scheme, + nullPreserving, + printKey, + outputHex, + rawCrib + ] = args, + crib = rawCrib.toLowerCase(), + output = []; + let result, + resultUtf8, + record = ""; + + input = input.slice(sampleOffset, sampleOffset + sampleLength); + + if (isWorkerEnvironment()) + self.sendStatusMessage("正在计算 " + Math.pow(256, keyLength) + " 种结果..."); + + /** + * Converts an integer to an array of bytes expressing that number. + * + * @param {number} int + * @param {number} len - Length of the resulting array + * @returns {array} + */ + const intToByteArray = (int, len) => { + const res = Array(len).fill(0); + for (let i = len - 1; i >= 0; i--) { + res[i] = int & 0xff; + int = int >>> 8; + } + return res; + }; + + for (let key = 1, l = Math.pow(256, keyLength); key < l; key++) { + if (key % 10000 === 0 && isWorkerEnvironment()) { + self.sendStatusMessage("正在计算 " + l + " 种结果... " + Math.floor(key / l * 100) + "%"); + } + + result = bitOp(input, intToByteArray(key, keyLength), xor, nullPreserving, scheme); + resultUtf8 = Utils.byteArrayToUtf8(result); + record = ""; + + if (crib && resultUtf8.toLowerCase().indexOf(crib) < 0) continue; + if (printKey) record += "Key = " + Utils.hex(key, (2*keyLength)) + ": "; + record += outputHex ? toHex(result) : Utils.escapeWhitespace(resultUtf8); + + output.push(record); + } + + return output.join("\n"); + } + +} + +export default XORBruteForce; diff --git a/plugins/srktoolbox/src/core/operations/XORChecksum.mjs b/plugins/srktoolbox/src/core/operations/XORChecksum.mjs new file mode 100644 index 00000000..97408c89 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/XORChecksum.mjs @@ -0,0 +1,61 @@ +/** + * @author Thomas Weißschuh [thomas@t-8ch.de] + * @copyright Crown Copyright 2023 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import { toHex } from "../lib/Hex.mjs"; + +/** + * XOR Checksum operation + */ +class XORChecksum extends Operation { + + /** + * XORChecksum constructor + */ + constructor() { + super(); + + this.name = "XOR校验和"; + this.module = "Crypto"; + this.description = "异或校验和将输入数据按可配置大小的块进行分割,并对这些数据块执行异或运算以生成校验值。"; + this.infoURL = "https://wikipedia.org/wiki/XOR"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "块大小", + type: "number", + value: 4 + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const blocksize = args[0]; + input = new Uint8Array(input); + + const res = Array(blocksize); + res.fill(0); + + for (const chunk of Utils.chunked(input, blocksize)) { + for (let i = 0; i < blocksize; i++) { + res[i] ^= chunk[i]; + } + } + + return toHex(res, ""); + } +} + +export default XORChecksum; diff --git a/plugins/srktoolbox/src/core/operations/XPathExpression.mjs b/plugins/srktoolbox/src/core/operations/XPathExpression.mjs new file mode 100644 index 00000000..29603a42 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/XPathExpression.mjs @@ -0,0 +1,82 @@ +/** + * @author Mikescher (https://github.com/Mikescher | https://mikescher.com) + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import xmldom from "@xmldom/xmldom"; +import xpath from "xpath"; + +/** + * XPath expression operation + */ +class XPathExpression extends Operation { + + /** + * XPathExpression constructor + */ + constructor() { + super(); + + this.name = "XPath表达式"; + this.module = "Code"; + this.description = "从XML文档中使用给定的XPath表达式进行查询并提取内容。"; + this.infoURL = "https://wikipedia.org/wiki/XPath"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "XPath", + "type": "string", + "value": "" + }, + { + "name": "查询结果分隔符", + "type": "binaryShortString", + "value": "\\n" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [query, delimiter] = args; + + let doc; + try { + doc = new xmldom.DOMParser({ + errorHandler: { + fatalError(e) { + throw e; + } + } + }).parseFromString(input, "application/xml"); + } catch (err) { + throw new OperationError("无效的XML。"); + } + + let nodes; + try { + nodes = xpath.parse(query).select({ node: doc, allowAnyNamespaceForNoPrefix: true }); + } catch (err) { + throw new OperationError(`无效的XPath。错误信息:\n${err.message}.`); + } + + const nodeToString = function(node) { + return node.toString(); + }; + + return nodes.map(nodeToString).join(delimiter); + } + +} + +export default XPathExpression; diff --git a/plugins/srktoolbox/src/core/operations/XSalsa20.mjs b/plugins/srktoolbox/src/core/operations/XSalsa20.mjs new file mode 100644 index 00000000..2d479b49 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/XSalsa20.mjs @@ -0,0 +1,158 @@ +/** + * @author joostrijneveld [joost@joostrijneveld.nl] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; +import { toHex } from "../lib/Hex.mjs"; +import { salsa20Block, hsalsa20 } from "../lib/Salsa20.mjs"; + +/** + * XSalsa20 operation + */ +class XSalsa20 extends Operation { + + /** + * XSalsa20 constructor + */ + constructor() { + super(); + + this.name = "XSalsa20"; + this.module = "Ciphers"; + this.description = "XSalsa20是Salsa20流加密算法的变种,由丹尼尔·J·伯恩斯坦设计。XSalsa相比Salsa使用更长的nonce。

密钥: XSalsa20使用16或32字节(128或256位)。

Nonce: XSalsa20使用24字节(192位)长度的nonce。

计数: XSalsa使用8字节(64位)长度的计数。计数在流的起始处为0,每64字节递增。"; + this.infoURL = "https://en.wikipedia.org/wiki/Salsa20#XSalsa20_with_192-bit_nonce"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + "name": "密钥", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + { + "name": "Nonce", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64", "整数"] + }, + { + "name": "计数", + "type": "number", + "value": 0, + "min": 0 + }, + { + "name": "轮数", + "type": "option", + "value": ["20", "12", "8"] + }, + { + "name": "输入", + "type": "option", + "value": ["十六进制", "原始"] + }, + { + "name": "输出", + "type": "option", + "value": ["原始", "十六进制"] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const key = Utils.convertToByteArray(args[0].string, args[0].option), + nonceType = args[1].option, + rounds = parseInt(args[3], 10), + inputType = args[4], + outputType = args[5]; + + if (key.length !== 16 && key.length !== 32) { + throw new OperationError(`无效的密钥长度: ${key.length} 字节。 + +XSalsa20使用16或32字节(128或256位)的密钥。`); + } + + let counter, nonce; + if (nonceType === "整数") { + nonce = Utils.intToByteArray(parseInt(args[1].string, 10), 8, "little"); + } else { + nonce = Utils.convertToByteArray(args[1].string, args[1].option); + if (!(nonce.length === 24)) { + throw new OperationError(`无效的nonce长度: ${nonce.length} 字节。 + +XSalsa20使用24字节(192位)的nonce。`); + } + } + counter = Utils.intToByteArray(args[2], 8, "little"); + + const xsalsaKey = hsalsa20(key, nonce.slice(0, 16), rounds); + + const output = []; + input = Utils.convertToByteArray(input, inputType); + + let counterAsInt = Utils.byteArrayToInt(counter, "little"); + for (let i = 0; i < input.length; i += 64) { + counter = Utils.intToByteArray(counterAsInt, 8, "little"); + const stream = salsa20Block(xsalsaKey, nonce.slice(16, 24), counter, rounds); + for (let j = 0; j < 64 && i + j < input.length; j++) { + output.push(input[i + j] ^ stream[j]); + } + counterAsInt++; + } + + if (outputType === "十六进制") { + return toHex(output); + } else { + return Utils.arrayBufferToStr(Uint8Array.from(output).buffer); + } + } + + /** + * Highlight XSalsa20 + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlight(pos, args) { + const inputType = args[4], + outputType = args[5]; + if (inputType === "原始" && outputType === "原始") { + return pos; + } + } + + /** + * Highlight XSalsa20 in reverse + * + * @param {Object[]} pos + * @param {number} pos[].start + * @param {number} pos[].end + * @param {Object[]} args + * @returns {Object[]} pos + */ + highlightReverse(pos, args) { + const inputType = args[4], + outputType = args[5]; + if (inputType === "原始" && outputType === "原始") { + return pos; + } + } + +} + +export default XSalsa20; diff --git a/plugins/srktoolbox/src/core/operations/XXTEADecrypt.mjs b/plugins/srktoolbox/src/core/operations/XXTEADecrypt.mjs new file mode 100644 index 00000000..5711723f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/XXTEADecrypt.mjs @@ -0,0 +1,59 @@ +/** + * @author devcydo [devcydo@gmail.com] + * @author Ma Bingyao [mabingyao@gmail.com] + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import {decrypt} from "../lib/XXTEA.mjs"; + +/** + * XXTEA Decrypt operation + */ +class XXTEADecrypt extends Operation { + + /** + * XXTEADecrypt constructor + */ + constructor() { + super(); + + this.name = "XXTEA解密"; + this.module = "Ciphers"; + this.description = "纠正后的Block TEA(通常被称为XXTEA)是一种设计用于纠正原始Block TEA中弱点的分组密码。XXTEA操作于可变长度的块,其大小为32位的整数倍(最小64位)。完整的循环次数取决于块的大小,但至少有6次(对于小块大小则上升到32次)。原始的Block TEA对块中的每个字应用XTEA循环函数,并与其最左侧的邻居进行加法组合。解密过程中扩散率较慢被立即利用来破解该密码。纠正后的Block TEA使用了一个更复杂的循环函数,在处理块中的每个字时利用了两个直接邻居。"; + this.infoURL = "https://wikipedia.org/wiki/XXTEA"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + "name": "密钥", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const key = new Uint8Array(Utils.convertToByteArray(args[0].string, args[0].option)); + try { + return decrypt(new Uint8Array(input), key).buffer; + } catch (err) { + throw new OperationError("使用给定的密钥无法解密"); + } + } + +} + +export default XXTEADecrypt; diff --git a/plugins/srktoolbox/src/core/operations/XXTEAEncrypt.mjs b/plugins/srktoolbox/src/core/operations/XXTEAEncrypt.mjs new file mode 100644 index 00000000..c963a73f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/XXTEAEncrypt.mjs @@ -0,0 +1,54 @@ +/** + * @author devcydo [devcydo@gmail.com] + * @author Ma Bingyao [mabingyao@gmail.com] + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2024 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {encrypt} from "../lib/XXTEA.mjs"; + +/** + * XXTEA Encrypt operation + */ +class XXTEAEncrypt extends Operation { + + /** + * XXTEAEncrypt constructor + */ + constructor() { + super(); + + this.name = "XXTEA加密"; + this.module = "Ciphers"; + this.description = "纠正后的Block TEA(通常被称为XXTEA)是一种设计用于纠正原始Block TEA中弱点的分组密码。XXTEA操作于可变长度的块,其大小为32位的整数倍(最小64位)。完整的循环次数取决于块的大小,但至少有6次(对于小块大小则上升到32次)。原始的Block TEA对块中的每个字应用XTEA循环函数,并与其最左侧的邻居进行加法组合。解密过程中扩散率较慢被立即利用来破解该密码。纠正后的Block TEA使用了一个更复杂的循环函数,在处理块中的每个字时利用了两个直接邻居。"; + this.infoURL = "https://wikipedia.org/wiki/XXTEA"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + "name": "密钥", + "type": "toggleString", + "value": "", + "toggleValues": ["十六进制", "UTF8", "Latin1", "Base64"] + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const key = new Uint8Array(Utils.convertToByteArray(args[0].string, args[0].option)); + return encrypt(new Uint8Array(input), key).buffer; + } + +} + +export default XXTEAEncrypt; diff --git a/plugins/srktoolbox/src/core/operations/YAMLToJSON.mjs b/plugins/srktoolbox/src/core/operations/YAMLToJSON.mjs new file mode 100644 index 00000000..1cbe8b1f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/YAMLToJSON.mjs @@ -0,0 +1,47 @@ +/** + * @author ccarpo [ccarpo@gmx.net] + * @copyright Crown Copyright 2021 + * @license Apache-2.0 + * + * Modified by Raka-loah@github + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import jsYaml from "js-yaml"; +/** + * YAML to JSON operation + */ +class YAMLToJSON extends Operation { + + /** + * YAMLToJSON constructor + */ + constructor() { + super(); + + this.name = "YAML转JSON"; + this.module = "Default"; + this.description = "将YAML转换为JSON"; + this.infoURL = "https://en.wikipedia.org/wiki/YAML"; + this.inputType = "string"; + this.outputType = "JSON"; + this.args = []; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {JSON} + */ + run(input, args) { + try { + return jsYaml.load(input); + } catch (err) { + throw new OperationError("无法解析YAML: " + err); + } + } + +} + +export default YAMLToJSON; diff --git a/plugins/srktoolbox/src/core/operations/YARARules.mjs b/plugins/srktoolbox/src/core/operations/YARARules.mjs new file mode 100644 index 00000000..622a5ebb --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/YARARules.mjs @@ -0,0 +1,143 @@ +/** + * @author Matt C [matt@artemisbot.uk] + * @copyright Crown Copyright 2019 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import Yara from "libyara-wasm"; +import { isWorkerEnvironment } from "../Utils.mjs"; + +/** + * YARA Rules operation + */ +class YARARules extends Operation { + + /** + * YARARules constructor + */ + constructor() { + super(); + + this.name = "YARA规则"; + this.module = "Yara"; + this.description = "YARA是VirusTotal制作的一个主要用于恶意软件研究和检测的工具。它提供了一种创建基于文本或二进制模式的恶意软件系列的描述方法。一个描述本质上是一个 YARA 规则名称,其中这些规则由字符串集和一个布尔表达式组成。使用的语言具有与 Perl 兼容的正则表达式的特点。对于规则编写,请参考:YARA文档。"; + this.infoURL = "https://wikipedia.org/wiki/YARA"; + this.inputType = "ArrayBuffer"; + this.outputType = "string"; + this.args = [ + { + name: "规则", + type: "text", + value: "", + rows: 5 + }, + { + name: "显示字符串", + type: "boolean", + value: false + }, + { + name: "显示字符串长度", + type: "boolean", + value: false + }, + { + name: "显示元数据", + type: "boolean", + value: false + }, + { + name: "显示计数", + type: "boolean", + value: true + }, + { + name: "显示规则警告", + type: "boolean", + value: true + }, + { + name: "显示控制台模块消息", + type: "boolean", + value: true + }, + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + if (isWorkerEnvironment()) + self.sendStatusMessage("YARA载入中……"); + const [rules, showStrings, showLengths, showMeta, showCounts, showRuleWarns, showConsole] = args; + return new Promise((resolve, reject) => { + Yara().then(yara => { + if (isWorkerEnvironment()) self.sendStatusMessage("为 YARA 转换数据"); + let matchString = ""; + + const inpArr = new Uint8Array(input); // Turns out embind knows that JS uint8array <==> C++ std::string + + if (isWorkerEnvironment()) self.sendStatusMessage("执行 YARA 匹配"); + + const resp = yara.run(inpArr, rules); + + if (isWorkerEnvironment()) self.sendStatusMessage("处理数据"); + + if (resp.compileErrors.size() > 0) { + for (let i = 0; i < resp.compileErrors.size(); i++) { + const compileError = resp.compileErrors.get(i); + if (!compileError.warning) { + reject(new OperationError(`行 ${compileError.lineNumber} 报错: ${compileError.message}`)); + } else if (showRuleWarns) { + matchString += `行 ${compileError.lineNumber} 警告: ${compileError.message}\n`; + } + } + } + + if (showConsole) { + const consoleLogs = resp.consoleLogs; + for (let i = 0; i < consoleLogs.size(); i++) { + matchString += consoleLogs.get(i) + "\n"; + } + } + + const matchedRules = resp.matchedRules; + for (let i = 0; i < matchedRules.size(); i++) { + const rule = matchedRules.get(i); + const matches = rule.resolvedMatches; + let meta = ""; + if (showMeta && rule.metadata.size() > 0) { + meta += " ["; + for (let j = 0; j < rule.metadata.size(); j++) { + meta += `${rule.metadata.get(j).identifier}: ${rule.metadata.get(j).data}, `; + } + meta = meta.slice(0, -2) + "]"; + } + const countString = matches.size() === 0 ? "" : (showCounts ? ` (${matches.size()} 次)` : ""); + if (matches.size() === 0 || !(showStrings || showLengths)) { + matchString += `输入匹配规则 "${rule.ruleName}"${meta}${countString.length > 0 ? ` ${countString}`: ""}.\n`; + } else { + matchString += `规则 "${rule.ruleName}"${meta} 匹配${countString}:\n`; + for (let j = 0; j < matches.size(); j++) { + const match = matches.get(j); + if (showStrings || showLengths) { + matchString += `位置 ${match.location}, ${showLengths ? `长度 ${match.matchLength}, ` : ""}标识符 ${match.stringIdentifier}${showStrings ? `, 数据: "${match.data}"` : ""}\n`; + } + } + } + } + resolve(matchString); + }); + }); + } + +} + +export default YARARules; diff --git a/plugins/srktoolbox/src/core/operations/Zip.mjs b/plugins/srktoolbox/src/core/operations/Zip.mjs new file mode 100644 index 00000000..0a42921f --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/Zip.mjs @@ -0,0 +1,105 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import Utils from "../Utils.mjs"; +import {COMPRESSION_TYPE, ZLIB_COMPRESSION_TYPE_LOOKUP} from "../lib/Zlib.mjs"; +import zip from "zlibjs/bin/zip.min.js"; + +const Zlib = zip.Zlib; + +const ZIP_COMPRESSION_METHOD_LOOKUP = { + "Deflate": Zlib.Zip.CompressionMethod.DEFLATE, + "无压缩 (Store)": Zlib.Zip.CompressionMethod.STORE +}; + +const ZIP_OS_LOOKUP = { + "MSDOS": Zlib.Zip.OperatingSystem.MSDOS, + "Unix": Zlib.Zip.OperatingSystem.UNIX, + "Macintosh": Zlib.Zip.OperatingSystem.MACINTOSH +}; + +/** + * Zip operation + */ +class Zip extends Operation { + + /** + * Zip constructor + */ + constructor() { + super(); + + this.name = "Zip"; + this.module = "Compression"; + this.description = "将输入数据使用给定的文件名用PKZIP算法进行压缩。

当前不支持多个文件。"; + this.infoURL = "https://wikipedia.org/wiki/Zip_(file_format)"; + this.inputType = "ArrayBuffer"; + this.outputType = "File"; + this.args = [ + { + name: "文件名", + type: "string", + value: "file.txt" + }, + { + name: "注释", + type: "string", + value: "" + }, + { + name: "密码", + type: "binaryString", + value: "" + }, + { + name: "压缩方式", + type: "option", + value: ["Deflate", "无压缩 (Store)"] + }, + { + name: "操作系统", + type: "option", + value: ["MSDOS", "Unix", "Macintosh"] + }, + { + name: "压缩类型", + type: "option", + value: COMPRESSION_TYPE + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {File} + */ + run(input, args) { + const filename = args[0], + password = Utils.strToByteArray(args[2]), + options = { + filename: Utils.strToByteArray(filename), + comment: Utils.strToByteArray(args[1]), + compressionMethod: ZIP_COMPRESSION_METHOD_LOOKUP[args[3]], + os: ZIP_OS_LOOKUP[args[4]], + deflateOption: { + compressionType: ZLIB_COMPRESSION_TYPE_LOOKUP[args[5]] + }, + }, + zip = new Zlib.Zip(); + + if (password.length) + zip.setPassword(password); + zip.addFile(new Uint8Array(input), options); + return new File([zip.compress()], filename); + } + +} + +export default Zip; diff --git a/plugins/srktoolbox/src/core/operations/ZlibDeflate.mjs b/plugins/srktoolbox/src/core/operations/ZlibDeflate.mjs new file mode 100644 index 00000000..f110fd50 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ZlibDeflate.mjs @@ -0,0 +1,55 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {COMPRESSION_TYPE, ZLIB_COMPRESSION_TYPE_LOOKUP} from "../lib/Zlib.mjs"; +import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min.js"; + +const Zlib = zlibAndGzip.Zlib; + +/** + * Zlib Deflate operation + */ +class ZlibDeflate extends Operation { + + /** + * ZlibDeflate constructor + */ + constructor() { + super(); + + this.name = "Zlib Deflate"; + this.module = "Compression"; + this.description = "使用带有Zlib标头的deflate算法压缩数据。"; + this.infoURL = "https://wikipedia.org/wiki/Zlib"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + name: "压缩类型", + type: "option", + value: COMPRESSION_TYPE + } + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const deflate = new Zlib.Deflate(new Uint8Array(input), { + compressionType: ZLIB_COMPRESSION_TYPE_LOOKUP[args[0]] + }); + return new Uint8Array(deflate.compress()).buffer; + } + +} + +export default ZlibDeflate; diff --git a/plugins/srktoolbox/src/core/operations/ZlibInflate.mjs b/plugins/srktoolbox/src/core/operations/ZlibInflate.mjs new file mode 100644 index 00000000..d5d70ea0 --- /dev/null +++ b/plugins/srktoolbox/src/core/operations/ZlibInflate.mjs @@ -0,0 +1,91 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + * + * Modified by Raka-loah@github for zh-CN i18n + */ + +import Operation from "../Operation.mjs"; +import {INFLATE_BUFFER_TYPE} from "../lib/Zlib.mjs"; +import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min.js"; + +const Zlib = zlibAndGzip.Zlib; + +const ZLIB_BUFFER_TYPE_LOOKUP = { + "自适应": Zlib.Inflate.BufferType.ADAPTIVE, + "块": Zlib.Inflate.BufferType.BLOCK, +}; + +/** + * Zlib Inflate operation + */ +class ZlibInflate extends Operation { + + /** + * ZlibInflate constructor + */ + constructor() { + super(); + + this.name = "Zlib Inflate"; + this.module = "Compression"; + this.description = "解压使用带有Zlib标头的deflate算法压缩的数据。"; + this.infoURL = "https://wikipedia.org/wiki/Zlib"; + this.inputType = "ArrayBuffer"; + this.outputType = "ArrayBuffer"; + this.args = [ + { + name: "起始索引", + type: "number", + value: 0 + }, + { + name: "起始输出缓冲区尺寸", + type: "number", + value: 0 + }, + { + name: "缓冲区扩展类型", + type: "option", + value: INFLATE_BUFFER_TYPE + }, + { + name: "解压缩后重置缓冲区尺寸", + type: "boolean", + value: false + }, + { + name: "验证结果", + type: "boolean", + value: false + } + ]; + this.checks = [ + { + pattern: "^\\x78(\\x01|\\x9c|\\xda|\\x5e)", + flags: "", + args: [0, 0, "自适应", false, false] + }, + ]; + } + + /** + * @param {ArrayBuffer} input + * @param {Object[]} args + * @returns {ArrayBuffer} + */ + run(input, args) { + const inflate = new Zlib.Inflate(new Uint8Array(input), { + index: args[0], + bufferSize: args[1], + bufferType: ZLIB_BUFFER_TYPE_LOOKUP[args[2]], + resize: args[3], + verify: args[4] + }); + return new Uint8Array(inflate.decompress()).buffer; + } + +} + +export default ZlibInflate; diff --git a/plugins/srktoolbox/src/core/vendor/DisassembleX86-64.mjs b/plugins/srktoolbox/src/core/vendor/DisassembleX86-64.mjs new file mode 100644 index 00000000..aeae426b --- /dev/null +++ b/plugins/srktoolbox/src/core/vendor/DisassembleX86-64.mjs @@ -0,0 +1,5760 @@ +/*------------------------------------------------------------------------------------------------------------------------- +Created by Damian Recoskie (https://github.com/Recoskie/X86-64-Disassembler-JS) + & exported for CyberChef by Matt [me@mitt.dev] +--------------------------------------------------------------------------------------------------------------------------- +MIT License + +Copyright (c) 2019 Damian Recoskie + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +-------------------------------------------------------------------------------------------------------------------------*/ + + +/*------------------------------------------------------------------------------------------------------------------------- +Binary byte code array. +--------------------------------------------------------------------------------------------------------------------------- +Function ^LoadBinCode()^ takes a string input of hex and loads it into the BinCode array it is recommended that the location +the hex string is read from a file, or sector matches the disassemblers set base address using function ^SetBasePosition()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var BinCode = []; + +/*------------------------------------------------------------------------------------------------------------------------- +When Bit Mode is 2 the disassembler will default to decoding 64 bit binary code possible settings are 0=16 bit, 1=32 bit, 2=64 bit. +-------------------------------------------------------------------------------------------------------------------------*/ + +var BitMode = 2; + +/*------------------------------------------------------------------------------------------------------------------------- +The variable CodePos is the position in the BinCode array starts at 0 for each new section loaded in by ^LoadBinCode()^. +--------------------------------------------------------------------------------------------------------------------------- +The function ^NextByte()^ moves CodePos, and the Disassemblers Base address by one stored in Pos64, Pos32. +The BinCode array is designed for loading in a section of binary that is supposed to be from the set Base address in Pos64, and Pos32. +-------------------------------------------------------------------------------------------------------------------------*/ + +var CodePos = 0x00000000; + +/*------------------------------------------------------------------------------------------------------------------------- +The Pos64, and Pos32 is the actual base address that instructions are supposed to be from in memory when they are loaded +into the BinCode array using the Function ^LoadBinCode()^. +--------------------------------------------------------------------------------------------------------------------------- +The function ^SetBasePosition()^ sets the base location in Pos64, and Pos32, and Code Segment. +-------------------------------------------------------------------------------------------------------------------------*/ + +var Pos64 = 0x00000000, Pos32 = 0x00000000; + +/*------------------------------------------------------------------------------------------------------------------------- +Code Segment is used in 16 bit binaries in which the segment is times 16 (Left Shift 4) added to the 16 bit address position. +This was done to load more programs in 16 bit space at an selected segment location. In 16 bit X86 processors the instruction +pointer register counts from 0000 hex to FFFF hex and starts over at 0000 hex. Allowing a program to be a max length of +65535 bytes long. The Code Segment is multiplied by 16 then is added to the instruction pointer position in memory. +--------------------------------------------------------------------------------------------------------------------------- +In 32 bit, and 64 bit the address combination is large enough that segmented program loading was no longer required. +However 32 bit still supports Segmented addressing if used, but 64 bit binaries do not. Also if the code segment is set +36, or higher in 32 bit binaries this sets SEG:OFFSET address format for each instructions Memory position. +--------------------------------------------------------------------------------------------------------------------------- +In 64 bit mode, an programs instructions are in a 64 bit address using the processors full instruction pointer, but in 32 +bit instructions the first 32 bit of the instruction pointer is used. In 16 bit the first 16 bits of the instruction pointer +is used, but with the code segment. Each instruction is executed in order by the Instruction pointer that goes in sectional sizes +"RIP (64)/EIP (32)/IP (16)" Depending on the Bit mode the 64 bit CPU is set in, or if the CPU is 32 bit to begin with. +-------------------------------------------------------------------------------------------------------------------------*/ + +var CodeSeg = 0x0000; + +/*------------------------------------------------------------------------------------------------------------------------- +The InstructionHex String stores the Bytes of decoded instructions. It is shown to the left side of the disassembled instruction. +-------------------------------------------------------------------------------------------------------------------------*/ + +var InstructionHex = ""; + +/*------------------------------------------------------------------------------------------------------------------------- +The InstructionPos String stores the start position of a decoded binary instruction in memory from the function ^GetPosition()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var InstructionPos = ""; + +/*------------------------------------------------------------------------------------------------------------------------- +Decoding display options. +-------------------------------------------------------------------------------------------------------------------------*/ + +var ShowInstructionHex = true; //setting to show the hex code of the instruction beside the decoded instruction output. +var ShowInstructionPos = true; //setting to show the instruction address position. + +/*------------------------------------------------------------------------------------------------------------------------- +The Opcode, and Opcode map. +--------------------------------------------------------------------------------------------------------------------------- +The first 0 to 255 (Byte) value that is read is the selected instruction code, however some codes are used as Adjustment to +remove limitations that are read by the function ^DecodePrefixAdjustments()^. +--------------------------------------------------------------------------------------------------------------------------- +Because X86 was limited to 255 instructions An number was sacrificed to add more instructions. +By using one of the 0 to 255 instructions like 15 which is "0F" as an hex number the next 0 to 255 value is an hole +new set of 0 to 255 instructions these are called escape code prefixes. +--------------------------------------------------------------------------------------------------------------------------- +Bellow XX is the opcode combined with the adjustment escape codes thus how opcode is used numerically in the disassembler. +--------------------------------------------------------------------------------------------------------------------------- +00,00000000 = 0, lower 8 bit opcode at max 00,11111111 = 255. (First byte opcodes XX) Opcodes values 0 to 255. +01,00000000 = 256, lower 8 bit opcode at max 01,11111111 = 511. (Two byte opcodes 0F XX) Opcodes values 256 to 511. +10,00000000 = 512, lower 8 bit opcode at max 10,11111111 = 767. (Three byte opcodes 0F 38 XX) Opcodes values 512 to 767. +11,00000000 = 768, lower 8 bit opcode at max 11,11111111 = 1023. (Three byte opcodes 0F 3A XX) Opcodes values 768 to 1023. +--------------------------------------------------------------------------------------------------------------------------- +The lower 8 bits is the selectable opcode 0 to 255 plus one from 255 is 1,00000000 = 256 thus 256 acts as the place holder. +The vector adjustment codes contain an map bit selection the map bits go in order to the place holder map bits are in. +This makes it so the map bits can be placed where the place holder bits are. +--------------------------------------------------------------------------------------------------------------------------- +VEX.mmmmm = 000_00b (1-byte map), 000_01b (2-byte map), 000_10b (0Fh,38h), 000_11b (0Fh,3Ah) +EVEX.mm = 00b (1-byte map), 01b (2-byte map), 10b (0Fh,38h), 11b (0Fh,3Ah) +-------------------------------------------------------------------------------------------------------------------------- +Function ^DecodePrefixAdjustments()^ reads opcodes that act as settings it only ends when Opcode is an actual +instruction code value 0 to 1023 inducing escape codes. Opcode is Used by function ^DecodeOpcode()^ with the Mnemonic array. +-------------------------------------------------------------------------------------------------------------------------*/ + +var Opcode = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +Opcode is used as the index for the point in the structure to land on in the "Mnemonics". +--------------------------------------------------------------------------------------------------------------------------- +X86 has an amazing architectural pattern that is like an fractal in many ways. Previously an experiment was done to make +this an one dimensional array, but after testing it proved that it was slower because each of the branches had to be +calculated to an unique index in memory in which lots of combinations map to the same instructions well some changed. +The calculation took more time than comparing if an index is an reference to another array to optionally use an encoding. +--------------------------------------------------------------------------------------------------------------------------- +The first branch is an array 2 in size which separates opcodes that change between register, and memory mode. +--------------------------------------------------------------------------------------------------------------------------- +The second branch is an array 8 in size which uses an register as an 0 to 7 value for the selected instruction code called grouped opcodes. +The second branch can be branched into another array 8 in size this covers the last three bits of the ModR/M byte for static opcodes. +--------------------------------------------------------------------------------------------------------------------------- +The third branch is an array 4 in size which is the SIMD modes. The third branch can branch to an array 4 in size again under +any of the 4 elements in the SIMD modes for instructions that change by vector extension type. +--------------------------------------------------------------------------------------------------------------------------- +The fifth branch is an array 3 in size which branches to encoding's that change by the set size attribute. +--------------------------------------------------------------------------------------------------------------------------- +Each branch can be combined in any combination, but only in order. If we branch to an array 2 in size under an specific opcode +like this ["",""] then decide to branch memory mode to an array 4 in size we end up with ["",["","","",""]] for making it only +active in memory mode and controlled by SIMD modes, but then if we decide to branch one of the 4 SIMD modes to an array 8 +in size for register opcode separation under one SIMD mode, or an few we can't. We can only branch to an array 3 in size +as that comes next after the array 4 in size. WE also do not need the first branch to be an array it can be an single opcode +encoding. We also do not need the first branch to be an array 2 in size it can be any starting branch then the rest must go +in order from that branch point. +--------------------------------------------------------------------------------------------------------------------------- +Opcode is used by the function ^DecodeOpcode()^ after ^DecodePrefixAdjustments()^. +The function ^DecodeOpcode()^ Gives back the instructions name. +--------------------------------------------------------------------------------------------------------------------------*/ + +const Mnemonics = [ + /*------------------------------------------------------------------------------------------------------------------------ + First Byte operations 0 to 255. + ------------------------------------------------------------------------------------------------------------------------*/ + "ADD","ADD","ADD","ADD","ADD","ADD","PUSH ES","POP ES", + "OR","OR","OR","OR","OR","OR","PUSH CS" + , + "" //*Two byte instructions prefix sets opcode 01,000000000 next byte read is added to the lower 8 bit's. + , + "ADC","ADC","ADC","ADC","ADC","ADC","PUSH SS","POP SS", + "SBB","SBB","SBB","SBB","SBB","SBB","PUSH DS","POP DS", + "AND","AND","AND","AND","AND","AND", + "ES:[", //Extra segment override sets SegOveride "ES:[". + "DAA", + "SUB","SUB","SUB","SUB","SUB","SUB", + "CS:[", //Code segment override sets SegOveride "CS:[". + "DAS", + "XOR","XOR","XOR","XOR","XOR","XOR", + "SS:[", //Stack segment override sets SegOveride "SS:[". + "AAA", + "CMP","CMP","CMP","CMP","CMP","CMP", + "DS:[", //Data Segment override sets SegOveride "DS:[". + "AAS", + /*------------------------------------------------------------------------------------------------------------------------ + Start of Rex Prefix adjustment setting uses opcodes 40 to 4F. These opcodes are only decoded as adjustment settings + by the function ^DecodePrefixAdjustments()^ while in 64 bit mode. If not in 64 bit mode the codes are not read + by the function ^DecodePrefixAdjustments()^ which allows the opcode to be set 40 to 4F hex in which the defined + instructions bellow are used by ^DecodeOpcode()^. + ------------------------------------------------------------------------------------------------------------------------*/ + "INC","INC","INC","INC","INC","INC","INC","INC", + "DEC","DEC","DEC","DEC","DEC","DEC","DEC","DEC", + /*------------------------------------------------------------------------------------------------------------------------ + End of the Rex Prefix adjustment setting opcodes. + ------------------------------------------------------------------------------------------------------------------------*/ + "PUSH","PUSH","PUSH","PUSH","PUSH","PUSH","PUSH","PUSH", + "POP","POP","POP","POP","POP","POP","POP","POP", + ["PUSHA","PUSHAD",""],["POPA","POPAD",""], + ["BOUND","BOUND",""], //EVEX prefix adjustment settings only if used in register to register, or in 64 bit mode, otherwise the defined BOUND instruction is used. + "MOVSXD", + "FS:[","GS:[", //Sets SegOveride "FS:[" next opcode sets "GS:[". + "","", //Operand Size, and Address size adjustment to ModR/M. + "PUSH","IMUL","PUSH","IMUL", + "INS","INS","OUTS","OUTS", + "JO","JNO","JB","JAE","JE","JNE","JBE","JA", + "JS","JNS","JP","JNP","JL","JGE","JLE","JG", + ["ADD","OR","ADC","SBB","AND","SUB","XOR","CMP"], //Group opcode uses the ModR/M register selection 0 though 7 giving 8 instruction in one opcode. + ["ADD","OR","ADC","SBB","AND","SUB","XOR","CMP"], + ["ADD","OR","ADC","SBB","AND","SUB","XOR","CMP"], + ["ADD","OR","ADC","SBB","AND","SUB","XOR","CMP"], + "TEST","TEST","XCHG","XCHG", + "MOV","MOV","MOV","MOV","MOV", + ["LEA","???"], //*ModR/M Register, and memory mode separation. + "MOV", + ["POP","???","???","???","???","???","???","???"], + [["NOP","","",""],["NOP","","",""],["PAUSE","","",""],["NOP","","",""]], + "XCHG","XCHG","XCHG","XCHG","XCHG","XCHG","XCHG", + ["CWDE","CBW","CDQE"], //*Opcode 0 to 3 for instructions that change name by size setting. + ["CDQ","CWD","CQO"], + "CALL","WAIT", + ["PUSHFQ","PUSHF","PUSHFQ"], + ["POPFQ","POPF","POPFQ"], + "SAHF","LAHF", + "MOV","MOV","MOV","MOV", + "MOVS","MOVS", + "CMPS","CMPS", + "TEST","TEST", + "STOS","STOS", + "LODS","LODS", + "SCAS","SCAS", + "MOV","MOV","MOV","MOV","MOV","MOV","MOV","MOV", + "MOV","MOV","MOV","MOV","MOV","MOV","MOV","MOV", + ["ROL","ROR","RCL","RCR","SHL","SHR","SAL","SAR"], + ["ROL","ROR","RCL","RCR","SHL","SHR","SAL","SAR"], + "RET","RET", + "LES", //VEX prefix adjustment settings only if used in register to register, or in 64 bit mode, otherwise the defined instruction is used. + "LDS", //VEX prefix adjustment settings only if used in register to register, or in 64 bit mode, otherwise the defined instruction is used. + [ + "MOV","???","???","???","???","???","???", + ["XABORT","XABORT","XABORT","XABORT","XABORT","XABORT","XABORT","XABORT"] + ], + [ + "MOV","???","???","???","???","???","???", + ["XBEGIN","XBEGIN","XBEGIN","XBEGIN","XBEGIN","XBEGIN","XBEGIN","XBEGIN"] + ], + "ENTER","LEAVE","RETF","RETF","INT","INT","INTO", + ["IRETD","IRET","IRETQ"], + ["ROL","ROR","RCL","RCR","SHL","SHR","SAL","SAR"], + ["ROL","ROR","RCL","RCR","SHL","SHR","SAL","SAR"], + ["ROL","ROR","RCL","RCR","SHL","SHR","SAL","SAR"], + ["ROL","ROR","RCL","RCR","SHL","SHR","SAL","SAR"], + "AAMB","AADB","???", + "XLAT", + /*------------------------------------------------------------------------------------------------------------------------ + X87 FPU. + ------------------------------------------------------------------------------------------------------------------------*/ + [ + ["FADD","FMUL","FCOM","FCOMP","FSUB","FSUBR","FDIV","FDIVR"], + ["FADD","FMUL","FCOM","FCOMP","FSUB","FSUBR","FDIV","FDIVR"] + ], + [ + ["FLD","???","FST","FSTP","FLDENV","FLDCW","FNSTENV","FNSTCW"], + [ + "FLD","FXCH", + ["FNOP","???","???","???","???","???","???","???"], + "FSTP1", + ["FCHS","FABS","???","???","FTST","FXAM","???","???"], + ["FLD1","FLDL2T","FLDL2E","FLDPI","FLDLG2","FLDLN2","FLDZ","???"], + ["F2XM1","FYL2X","FPTAN","FPATAN","FXTRACT","FPREM1","FDECSTP","FINCSTP"], + ["FPREM","FYL2XP1","FSQRT","FSINCOS","FRNDINT","FSCALE","FSIN","FCOS"] + ] + ], + [ + ["FIADD","FIMUL","FICOM","FICOMP","FISUB","FISUBR","FIDIV","FIDIVR"], + [ + "FCMOVB","FCMOVE","FCMOVBE","FCMOVU","???", + ["???","FUCOMPP","???","???","???","???","???","???"], + "???","???" + ] + ], + [ + ["FILD","FISTTP","FIST","FISTP","???","FLD","???","FSTP"], + [ + "CMOVNB","FCMOVNE","FCMOVNBE","FCMOVNU", + ["FENI","FDISI","FNCLEX","FNINIT","FSETPM","???","???","???"], + "FUCOMI","FCOMI","???" + ] + ], + [ + ["FADD","FMUL","FCOM","DCOMP","FSUB","FSUBR","FDIV","FDIVR"], + ["FADD","FMUL","FCOM2","FCOMP3","FSUBR","FSUB","FDIVR","FDIV"] + ], + [ + ["FLD","FISTTP","FST","FSTP","FRSTOR","???","FNSAVE","FNSTSW"], + ["FFREE","FXCH4","FST","FSTP","FUCOM","FUCOMP","???","???"] + ], + [ + ["FIADD","FIMUL","FICOM","FICOMP","FISUB","FISUBR","FIDIV","FIDIVR"], + [ + "FADDP","FMULP","FCOMP5", + ["???","FCOMPP","???","???","???","???","???","???"], + "FSUBRP","FSUBP","FDIVRP","FDIVP" + ] + ], + [ + ["FILD","FISTTP","FIST","FISTP","FBLD","FILD","FBSTP","FISTP"], + [ + "FFREEP","FXCH7","FSTP8","FSTP9", + ["FNSTSW","???","???","???","???","???","???","???"], + "FUCOMIP","FCOMIP","???" + ] + ], + /*------------------------------------------------------------------------------------------------------------------------ + End of X87 FPU. + ------------------------------------------------------------------------------------------------------------------------*/ + "LOOPNE","LOOPE","LOOP","JRCXZ", + "IN","IN","OUT","OUT", + "CALL","JMP","JMP","JMP", + "IN","IN","OUT","OUT", + /*------------------------------------------------------------------------------------------------------------------------ + The Repeat, and lock prefix opcodes apply to the next opcode. + ------------------------------------------------------------------------------------------------------------------------*/ + "LOCK", //Adds LOCK to the start of instruction. When Opcode F0 hex is read by function ^DecodePrefixAdjustments()^ sets PrefixG2 to LOCK. + "ICEBP", //Instruction ICEBP. + "REPNE", //Adds REPNE (Opcode F2 hex) to the start of instruction. Read by function ^DecodePrefixAdjustments()^ sets PrefixG1 to REPNE. + "REP", //Adds REP (Opcode F3 hex) to the start of instruction. Read by function ^DecodePrefixAdjustments()^ sets PrefixG1 to REP. + /*------------------------------------------------------------------------------------------------------------------------ + End of Repeat, and lock instruction adjustment codes. + ------------------------------------------------------------------------------------------------------------------------*/ + "HLT","CMC", + ["TEST","???","NOT","NEG","MUL","IMUL","DIV","IDIV"], + ["TEST","???","NOT","NEG","MUL","IMUL","DIV","IDIV"], + "CLC","STC","CLI","STI","CLD","STD", + ["INC","DEC","???","???","???","???","???","???"], + [ + ["INC","DEC","CALL","CALL","JMP","JMP","PUSH","???"], + ["INC","DEC","CALL","???","JMP","???","PUSH","???"] + ], + /*------------------------------------------------------------------------------------------------------------------------ + Two Byte Opcodes 256 to 511. Opcodes plus 256 goes to 511 used by escape code "0F", Or + set directly by adding map bits "01" because "01 00000000" bin = 256 plus opcode. + ------------------------------------------------------------------------------------------------------------------------*/ + [ + ["SLDT","STR","LLDT","LTR","VERR","VERW","JMPE","???"], + ["SLDT","STR","LLDT","LTR","VERR","VERW","JMPE","???"] + ], + [ + ["SGDT","SIDT","LGDT","LIDT","SMSW","???","LMSW","INVLPG"], + [ + ["???","VMCALL","VMLAUNCH","VMRESUME","VMXOFF","???","???","???"], + ["MONITOR","MWAIT","CLAC","STAC","???","???","???","ENCLS"], + ["XGETBV","XSETBV","???","???","VMFUNC","XEND","XTEST","ENCLU"], + ["VMRUN","VMMCALL","VMLOAD","VMSAVE","STGI","CLGI","SKINIT","INVLPGA"], + "SMSW","???","LMSW", + ["SWAPGS","RDTSCP","MONITORX","MWAITX","???","???","???","???"] + ] + ], + ["LAR","LAR"],["LSL","LSL"],"???", + "SYSCALL","CLTS","SYSRET","INVD", + "WBINVD","???","UD2","???", + [["PREFETCH","PREFETCHW","???","???","???","???","???","???"],"???"], + "FEMMS", + "", //3DNow Instruction name is encoded by the IMM8 operand. + [ + ["MOVUPS","MOVUPD","MOVSS","MOVSD"], + ["MOVUPS","MOVUPD","MOVSS","MOVSD"] + ], + [ + ["MOVUPS","MOVUPD","MOVSS","MOVSD"], + ["MOVUPS","MOVUPD","MOVSS","MOVSD"] + ], + [ + ["MOVLPS","MOVLPD","MOVSLDUP","MOVDDUP"], + ["MOVHLPS","???","MOVSLDUP","MOVDDUP"] + ], + [["MOVLPS","MOVLPD","???","???"],"???"], + ["UNPCKLPS","UNPCKLPD","???","???"], //An instruction with 4 operations uses the 4 SIMD modes as an Vector instruction. + ["UNPCKHPS","UNPCKHPD","???","???"], + [["MOVHPS","MOVHPD","MOVSHDUP","???"],["MOVLHPS","???","MOVSHDUP","???"]], + [["MOVHPS","MOVHPD","???","???"],"???"], + [["PREFETCHNTA","PREFETCHT0","PREFETCHT1","PREFETCHT2","???","???","???","???"],"???"], + "???", + [[["BNDLDX","","",""],["BNDMOV","","",""],["BNDCL","","",""],["BNDCU","","",""]], + ["???",["BNDMOV","","",""],["BNDCL","","",""],["BNDCU","","",""]]], + [[["BNDSTX","","",""],["BNDMOV","","",""],["BNDMK","","",""],["BNDCN","","",""]], + ["???",["BNDMOV","","",""],"???",["BNDCN","","",""]]], + "???","???","???", + "NOP", + ["???","MOV"],["???","MOV"], //CR and DR register Move + ["???","MOV"],["???","MOV"], //CR and DR register Move + ["???","MOV"],"???", //TR (TEST REGISTER) register Move + ["???","MOV"],"???", //TR (TEST REGISTER) register Move + [ + ["MOVAPS","MOVAPS","MOVAPS","MOVAPS"], + ["MOVAPD","MOVAPD","MOVAPD","MOVAPD"], + "???","???" + ], + [ + [ + ["MOVAPS","MOVAPS","MOVAPS","MOVAPS"], + ["MOVAPD","MOVAPD","MOVAPD","MOVAPD"], + ["","","",["MOVNRAPS","MOVNRNGOAPS","MOVNRAPS"]], + ["","","",["MOVNRAPD","MOVNRNGOAPD","MOVNRAPD"]] + ], + [ + ["MOVAPS","MOVAPS","MOVAPS","MOVAPS"], + ["MOVAPD","MOVAPD","MOVAPD","MOVAPD"], + "???","???" + ] + ], + [ + ["CVTPI2PS","","",""],["CVTPI2PD","","",""], //Is not allowed to be Vector encoded. + "CVTSI2SS","CVTSI2SD" + ], + [ + [ + "MOVNTPS","MOVNTPD", + ["MOVNTSS","","",""],["MOVNTSD","","",""] //SSE4a can not be vector encoded. + ],"???" + ], + [ + ["CVTTPS2PI","","",""],["CVTTPD2PI","","",""], //Is not allowed to be Vector encoded. + "CVTTSS2SI","CVTTSD2SI" + ], + [ + ["CVTPS2PI","","",""],["CVTPD2PI","","",""], //Is not allowed to be Vector encoded. + "CVTSS2SI","CVTSD2SI" + ], + ["UCOMISS","UCOMISD","???","???"], + ["COMISS","COMISD","???","???"], + "WRMSR","RDTSC","RDMSR","RDPMC", + "SYSENTER","SYSEXIT","???", + "GETSEC", + "", //*Three byte instructions prefix combo 0F 38 (Opcode = 01,00111000) sets opcode 10,000000000 next byte read is added to the lower 8 bit's. + "???", + "", //*Three byte instructions prefix combo 0F 3A (Opcode = 01,00111010) sets opcode 11,000000000 next byte read is added to the lower 8 bit's. + "???","???","???","???","???", + "CMOVO", + [ + ["CMOVNO",["KANDW","","KANDQ"],"",""], + ["CMOVNO",["KANDB","","KANDD"],"",""],"","" + ], + [ + ["CMOVB",["KANDNW","","KANDNQ"],"",""], + ["CMOVB",["KANDNB","","KANDND"],"",""],"","" + ], + [["CMOVAE","KANDNR","",""],"","",""], + [ + ["CMOVE",["KNOTW","","KNOTQ"],"",""], + ["CMOVE",["KNOTB","","KNOTD"],"",""],"","" + ], + [ + ["CMOVNE",["KORW","","KORQ"],"",""], + ["CMOVNE",["KORB","","KORD"],"",""],"","" + ], + [ + ["CMOVBE",["KXNORW","","KXNORQ"],"",""], + ["CMOVBE",["KXNORB","","KXNORD"],"",""],"","" + ], + [ + ["CMOVA",["KXORW","","KXORQ"],"",""], + ["CMOVA",["KXORB","","KXORD"],"",""],"","" + ], + [["CMOVS","KMERGE2L1H","",""],"","",""], + [["CMOVNS","KMERGE2L1L","",""],"","",""], + [ + ["CMOVP",["KADDW","","KADDQ"],"",""], + ["CMOVP",["KADDB","","KADDD"],"",""],"","" + ], + [ + ["CMOVNP",["KUNPCKWD","","KUNPCKDQ"],"",""], + ["CMOVNP",["KUNPCKBW","","???"],"",""],"","" + ], + "CMOVL","CMOVGE","CMOVLE","CMOVG", + [ + "???", + [ + ["MOVMSKPS","MOVMSKPS","",""],["MOVMSKPD","MOVMSKPD","",""], + "???","???" + ] + ], + ["SQRTPS","SQRTPD","SQRTSS","SQRTSD"], + [ + ["RSQRTPS","RSQRTPS","",""],"???", + ["RSQRTSS","RSQRTSS","",""],"???" + ], + [ + ["RCPPS","RCPPS","",""],"???", + ["RCPSS","RCPSS","",""],"???" + ], + ["ANDPS","ANDPD","???","???"], + ["ANDNPS","ANDNPD","???","???"], + ["ORPS","ORPD","???","???"], + ["XORPS","XORPD","???","???"], + [ + ["ADDPS","ADDPS","ADDPS","ADDPS"], + ["ADDPD","ADDPD","ADDPD","ADDPD"], + "ADDSS","ADDSD" + ], + [ + ["MULPS","MULPS","MULPS","MULPS"], + ["MULPD","MULPD","MULPD","MULPD"], + "MULSS","MULSD" + ], + [ + ["CVTPS2PD","CVTPS2PD","CVTPS2PD","CVTPS2PD"], + ["CVTPD2PS","CVTPD2PS","CVTPD2PS","CVTPD2PS"], + "CVTSS2SD","CVTSD2SS" + ], + [["CVTDQ2PS","","CVTQQ2PS"],["CVTPS2DQ","","???"],"CVTTPS2DQ","???"], + [ + ["SUBPS","SUBPS","SUBPS","SUBPS"], + ["SUBPD","SUBPD","SUBPD","SUBPD"], + "SUBSS","SUBSD" + ], + ["MINPS","MINPD","MINSS","MINSD"], + ["DIVPS","DIVPD","DIVSS","DIVSD"], + ["MAXPS","MAXPD","MAXSS","MAXSD"], + [["PUNPCKLBW","","",""],"PUNPCKLBW","",""], + [["PUNPCKLWD","","",""],"PUNPCKLWD","",""], + [["PUNPCKLDQ","","",""],"PUNPCKLDQ","",""], + [["PACKSSWB","","",""],"PACKSSWB","",""], + [["PCMPGTB","","",""],["PCMPGTB","PCMPGTB","PCMPGTB",""],"",""], + [["PCMPGTW","","",""],["PCMPGTW","PCMPGTW","PCMPGTW",""],"",""], + [["PCMPGTD","","",""],["PCMPGTD","PCMPGTD",["PCMPGTD","","???"],["PCMPGTD","","???"]],"",""], + [["PACKUSWB","","",""],"PACKUSWB","",""], + [["PUNPCKHBW","","",""],"PUNPCKHBW","",""], + [["PUNPCKHWD","","",""],"PUNPCKHWD","",""], + [["PUNPCKHDQ","","",""],["PUNPCKHDQ","","???"],"",""], + [["PACKSSDW","","",""],["PACKSSDW","","???"],"",""], + ["???","PUNPCKLQDQ","???","???"], + ["???","PUNPCKHQDQ","???","???"], + [["MOVD","","",""],["MOVD","","MOVQ"],"",""], + [ + [ + ["MOVQ","","",""], + ["MOVDQA","MOVDQA",["MOVDQA32","","MOVDQA64"],["MOVDQA32","","MOVDQA64"]], + ["MOVDQU","MOVDQU",["MOVDQU32","","MOVDQU64"],""], + ["","",["MOVDQU8","","MOVDQU16"],""] + ], + [ + ["MOVQ","","",""], + ["MOVDQA","MOVDQA",["MOVDQA32","","MOVDQA64"],["MOVDQA32","","MOVDQA64"]], + ["MOVDQU","MOVDQU",["MOVDQU32","","MOVDQU64"],""], + ["","",["MOVDQU8","","MOVDQU16"],""] + ] + ], + [ + ["PSHUFW","","",""], + ["PSHUFD","PSHUFD",["PSHUFD","","???"],["PSHUFD","","???"]], + "PSHUFHW", + "PSHUFLW" + ], + [ + "???", + [ + "???","???", + [["PSRLW","","",""],"PSRLW","",""],"???", + [["PSRAW","","",""],"PSRAW","",""],"???", + [["PSLLW","","",""],"PSLLW","",""],"???" + ] + ], + [ + ["???",["","",["PRORD","","PRORQ"],""],"???","???"], + ["???",["","",["PROLD","","PROLQ"],""],"???","???"], + [["PSRLD","","",""],["PSRLD","PSRLD",["PSRLD","","???"],["PSRLD","","???"]],"",""], + "???", + [["PSRAD","","",""],["PSRAD","PSRAD",["PSRAD","","PSRAQ"],["PSRAD","","???"]],"",""], + "???", + [["PSLLD","","",""],["PSLLD","PSLLD",["PSLLD","","???"],["PSLLD","","???"]],"",""], + "???" + ], + [ + "???", + [ + "???","???", + [["PSRLQ","PSRLQ","",""],"PSRLQ","",""],["???","PSRLDQ","???","???"], + "???","???", + [["PSLLQ","PSLLQ","",""],"PSLLQ","",""],["???","PSLLDQ","???","???"] + ] + ], + [["PCMPEQB","","",""],["PCMPEQB","PCMPEQB","PCMPEQB",""],"",""], + [["PCMPEQW","","",""],["PCMPEQW","PCMPEQW","PCMPEQW",""],"",""], + [["PCMPEQD","","",""],["PCMPEQD","PCMPEQD",["PCMPEQD","","???"],["PCMPEQD","","???"]],"",""], + [["EMMS",["ZEROUPPER","ZEROALL",""],"",""],"???","???","???"], + [ + ["VMREAD","",["CVTTPS2UDQ","","CVTTPD2UDQ"],""], + ["EXTRQ","",["CVTTPS2UQQ","","CVTTPD2UQQ"],""], + ["???","","CVTTSS2USI",""], + ["INSERTQ","","CVTTSD2USI",""] + ], + [ + ["VMWRITE","",["CVTPS2UDQ","","CVTPD2UDQ"], ""], + ["EXTRQ","",["CVTPS2UQQ","","CVTPD2UQQ"],""], + ["???","","CVTSS2USI",""], + ["INSERTQ","","CVTSD2USI",""] + ], + [ + "???", + ["","",["CVTTPS2QQ","","CVTTPD2QQ"],""], + ["","",["CVTUDQ2PD","","CVTUQQ2PD"],"CVTUDQ2PD"], + ["","",["CVTUDQ2PS","","CVTUQQ2PS"],""] + ], + [ + "???", + ["","",["CVTPS2QQ","","CVTPD2QQ"],""], + ["","","CVTUSI2SS",""], + ["","","CVTUSI2SD",""] + ], + [ + "???",["HADDPD","HADDPD","",""], + "???",["HADDPS","HADDPS","",""] + ], + [ + "???",["HSUBPD","HSUBPD","",""], + "???",["HSUBPS","HSUBPS","",""] + ], + [["MOVD","","",""],["MOVD","","MOVQ"],["MOVQ","MOVQ",["???","","MOVQ"],""],"???"], + [ + ["MOVQ","","",""], + ["MOVDQA","MOVDQA",["MOVDQA32","","MOVDQA64"],["MOVDQA32","","MOVDQA64"]], + ["MOVDQU","MOVDQU",["MOVDQU32","","MOVDQU64"],""], + ["???","",["MOVDQU8","","MOVDQU16"],""] + ], + "JO","JNO","JB","JAE", + [["JE","JKZD","",""],"","",""],[["JNE","JKNZD","",""],"","",""], //K1OM. + "JBE","JA","JS","JNS","JP","JNP","JL","JGE","JLE","JG", + [ + ["SETO",["KMOVW","","KMOVQ"],"",""], + ["SETO",["KMOVB","","KMOVD"],"",""],"","" + ], + [ + ["SETNO",["KMOVW","","KMOVQ"],"",""], + ["SETNO",["KMOVB","","KMOVD"],"",""],"","" + ], + [ + ["SETB",["KMOVW","","???"],"",""], + ["SETB",["KMOVB","","???"],"",""],"", + ["SETB",["KMOVD","","KMOVQ"],"",""] + ], + [ + ["SETAE",["KMOVW","","???"],"",""], + ["SETAE",["KMOVB","","???"],"",""],"", + ["SETAE",["KMOVD","","KMOVQ"],"",""] + ], + "SETE",[["SETNE","KCONCATH","",""],"","",""], + "SETBE",[["SETA","KCONCATL","",""],"","",""], + [ + ["SETS",["KORTESTW","","KORTESTQ"],"",""], + ["SETS",["KORTESTB","","KORTESTD"],"",""],"","" + ], + [ + ["SETNS",["KTESTW","","KTESTQ"],"",""], + ["SETNS",["KTESTB","","KTESTD"],"",""],"","" + ], + "SETP","SETNP","SETL","SETGE","SETLE","SETG", + "PUSH","POP", + "CPUID", //Identifies the CPU and which Instructions the current CPU can use. + "BT", + "SHLD","SHLD", + "XBTS","IBTS", + "PUSH","POP", + "RSM", + "BTS", + "SHRD","SHRD", + [ + [ + ["FXSAVE","???","FXSAVE64"],["FXRSTOR","???","FXRSTOR64"], + "LDMXCSR","STMXCSR", + ["XSAVE","","XSAVE64"],["XRSTOR","","XRSTOR64"], + ["XSAVEOPT","CLWB","XSAVEOPT64"], + ["CLFLUSHOPT","CLFLUSH",""] + ], + [ + ["???","???",["RDFSBASE","","",""],"???"],["???","???",["RDGSBASE","","",""],"???"], + ["???","???",["WRFSBASE","","",""],"???"],["???","???",["WRGSBASE","","",""],"???"], + "???", + ["LFENCE","???","???","???","???","???","???","???"], + ["MFENCE","???","???","???","???","???","???","???"], + ["SFENCE","???","???","???","???","???","???","???"] + ] + ], + "IMUL", + "CMPXCHG","CMPXCHG", + ["LSS","???"], + "BTR", + ["LFS","???"], + ["LGS","???"], + "MOVZX","MOVZX", + [ + ["JMPE","","",""],"???", + ["POPCNT","POPCNT","",""],"???" + ], + "???", + ["???","???","???","???","BT","BTS","BTR","BTC"], + "BTC", + [ + ["BSF","","",""],"???", + ["TZCNT","TZCNT","",""],["BSF","TZCNTI","",""] + ], + [ + ["BSR","","",""],"???", + ["LZCNT","LZCNT","",""],["BSR","","",""] + ], + "MOVSX","MOVSX", + "XADD","XADD", + [ + ["CMP,PS,","CMP,PS,","CMP,PS,","CMP,PS,"], + ["CMP,PD,","CMP,PD,","CMP,PD,","CMP,PD,"], + ["CMP,SS,","CMP,SS,","CMP,SS,",""], + ["CMP,SD,","CMP,SD,","CMP,SD,",""] + ], + ["MOVNTI","???"], + [["PINSRW","","",""],"PINSRW","",""], + ["???",[["PEXTRW","","",""],"PEXTRW","",""]], + ["SHUFPS","SHUFPD","???","???"], + [ + [ + "???", + ["CMPXCHG8B","","CMPXCHG16B"], + "???", + ["XRSTORS","","XRSTORS64"], + ["XSAVEC","","XSAVEC64"], + ["XSAVES","","XSAVES64"], + ["VMPTRLD","VMCLEAR","VMXON","???"],["VMPTRST","???","???","???"] + ], + [ + "???", + ["SSS","???","???","???","???","???","???","???"], //Synthetic virtual machine operation codes. + "???","???","???","???", + "RDRAND","RDSEED" + ] + ], + "BSWAP","BSWAP","BSWAP","BSWAP","BSWAP","BSWAP","BSWAP","BSWAP", + ["???",["ADDSUBPD","ADDSUBPD","",""],"???",["ADDSUBPS","ADDSUBPS","",""]], + [["PSRLW","","",""],"PSRLW","",""], + [["PSRLD","","",""],["PSRLD","PSRLD",["PSRLD","","???"],""],"",""], + [["PSRLQ","","",""],"PSRLQ","",""], + [["PADDQ","","",""],"PADDQ","",""], + [["PMULLW","","",""],"PMULLW","",""], + [ + ["???","MOVQ","???","???"], + ["???","MOVQ",["MOVQ2DQ","","",""],["MOVDQ2Q","","",""]] + ], + ["???",[["PMOVMSKB","","",""],["PMOVMSKB","PMOVMSKB","",""],"???","???"]], + [["PSUBUSB","","",""],"PSUBUSB","",""], + [["PSUBUSW","","",""],"PSUBUSW","",""], + [["PMINUB","","",""],"PMINUB","",""], + [["PAND","","",""],["PAND","PAND",["PANDD","","PANDQ"],["PANDD","","PANDQ"]],"",""], + [["PADDUSB","","",""],"PADDUSB","",""], + [["PADDUSW","","",""],"PADDUSW","",""], + [["PMAXUB","","",""],"PMAXUB","",""], + [["PANDN","","",""],["PANDN","PANDN",["PANDND","","PANDNQ"],["PANDND","","PANDNQ"]],"",""], + [["PAVGB","","",""],"PAVGB","",""], + [ + [["PSRAW","","",""],["PSRAW","PSRAW","PSRAW",""],"",""], + [["PSRAW","","",""],["PSRAW","PSRAW","PSRAW",""],"",""] + ], + [["PSRAD","","",""],["PSRAD","PSRAD",["PSRAD","","PSRAQ"],""],"",""], + [["PAVGW","","",""],"PAVGW","",""], + [["PMULHUW","","",""],"PMULHUW","",""], + [["PMULHW","","",""],"PMULHW","",""], + [ + "???", + ["CVTTPD2DQ","CVTTPD2DQ","CVTTPD2DQ",""], + ["CVTDQ2PD","CVTDQ2PD",["CVTDQ2PD","CVTDQ2PD","CVTQQ2PD"],"CVTDQ2PD"], + "CVTPD2DQ" + ], + [[["MOVNTQ","","",""],["MOVNTDQ","","???"],"???","???"],"???"], + [["PSUBSB","","",""],"PSUBSB","",""], + [["PSUBSW","","",""],"PSUBSW","",""], + [["PMINSW","","",""],"PMINSW","",""], + [["POR","","",""],["POR","POR",["PORD","","PORQ"],["PORD","","PORQ"]],"",""], + [["PADDSB","","",""],"PADDSB","",""], + [["PADDSW","","",""],"PADDSW","",""], + [["PMAXSW","","",""],"PMAXSW","",""], + [["PXOR","","",""],["PXOR","PXOR",["PXORD","","PXORQ"],["PXORD","","PXORQ"]],"",""], + [["???","???","???",["LDDQU","LDDQU","",""]],"???"], + [["PSLLW","","",""],"PSLLW","",""], + [["PSLLD","","",""],["PSLLD","","???"],"",""], + [["PSLLQ","","",""],"PSLLQ","",""], + [["PMULUDQ","","",""],"PMULUDQ","",""], + [["PMADDWD","","",""],"PMADDWD","",""], + [["PSADBW","","",""],"PSADBW","",""], + ["???",[["MASKMOVQ","","",""],["MASKMOVDQU","MASKMOVDQU","",""],"???","???"]], + [["PSUBB","","",""],"PSUBB","",""], + [["PSUBW","","",""],"PSUBW","",""], + [["PSUBD","","",""],["PSUBD","PSUBD",["PSUBD","","???"],["PSUBD","","???"]],"",""], + [["PSUBQ","","",""],"PSUBQ","",""], + [["PADDB","","",""],"PADDB","",""], + [["PADDW","","",""],"PADDW","",""], + [["PADDD","","",""],["PADDD","PADDD",["PADDD","","???"],["PADDD","","???"]],"",""], + "???", + /*------------------------------------------------------------------------------------------------------------------------ + Three Byte operations 0F38. Opcodes plus 512 goes to 767 used by escape codes "0F,38", Or + set directly by adding map bits "10" because "10 00000000" bin = 512 plus opcode. + ------------------------------------------------------------------------------------------------------------------------*/ + [["PSHUFB","","",""],"PSHUFB","???","???"], + [["PHADDW","","",""],["PHADDW","PHADDW","",""],"???","???"], + [["PHADDD","","",""],["PHADDD","PHADDD","",""],"???","???"], + [["PHADDSW","","",""],["PHADDSW","PHADDSW","",""],"???","???"], + [["PMADDUBSW","","",""],"PMADDUBSW","???","???"], + [["PHSUBW","","",""],["PHSUBW","PHSUBW","",""],"???","???"], + [["PHSUBD","","",""],["PHSUBD","PHSUBD","",""],"???","???"], + [["PHSUBSW","","",""],["PHSUBSW","PHSUBSW","",""],"???","???"], + [["PSIGNB","","",""],["PSIGNB","PSIGNB","",""],"???","???"], + [["PSIGNW","","",""],["PSIGNW","PSIGNW","",""],"???","???"], + [["PSIGND","","",""],["PSIGND","PSIGND","",""],"???","???"], + [["PMULHRSW","","",""],"PMULHRSW","???","???"], + ["???",["","PERMILPS",["PERMILPS","","???"],""],"???","???"], + ["???",["","PERMILPD","PERMILPD",""],"???","???"], + ["???",["","TESTPS","",""],"???","???"], + ["???",["","TESTPD","",""],"???","???"], + ["???",["PBLENDVB","PBLENDVB","PSRLVW",""],["","","PMOVUSWB",""],"???"], + ["???",["","","PSRAVW",""],["","","PMOVUSDB",""],"???"], + ["???",["","","PSLLVW",""],["","","PMOVUSQB",""],"???"], + ["???",["","CVTPH2PS",["CVTPH2PS","","???"],""],["","","PMOVUSDW",""],"???"], + ["???",["BLENDVPS","BLENDVPS",["PRORVD","","PRORVQ"],""],["","","PMOVUSQW",""],"???"], + ["???",["BLENDVPD","BLENDVPD",["PROLVD","","PROLVQ"],""],["","","PMOVUSQD",""],"???"], + ["???",["","PERMPS",["PERMPS","","PERMPD"],""],"???","???"], + ["???",["PTEST","PTEST","",""],"???","???"], + ["???",["","BROADCASTSS",["BROADCASTSS","","???"],["BROADCASTSS","","???"]],"???","???"], + ["???",["","BROADCASTSD",["BROADCASTF32X2","","BROADCASTSD"],["???","","BROADCASTSD"]],"???","???"], + ["???",["","BROADCASTF128",["BROADCASTF32X4","","BROADCASTF64X2"],["BROADCASTF32X4","","???"]],"???","???"], + ["???",["","",["BROADCASTF32X8","","BROADCASTF64X4"],["???","","BROADCASTF64X4"]],"???","???"], + [["PABSB","","",""],"PABSB","???","???"], + [["PABSW","","",""],"PABSW","???","???"], + [["PABSD","","",""],["PABSD","","???"],"???","???"], + ["???",["","","PABSQ",""],"???","???"], + ["???","PMOVSXBW",["","","PMOVSWB",""],"???"], + ["???","PMOVSXBD",["","","PMOVSDB",""],"???"], + ["???","PMOVSXBQ",["","","PMOVSQB",""],"???"], + ["???","PMOVSXWD",["","","PMOVSDW",""],"???"], + ["???","PMOVSXWQ",["","","PMOVSQW",""],"???"], + ["???","PMOVSXDQ",["","","PMOVSQD",""],"???"], + ["???",["","",["PTESTMB","","PTESTMW"],""],["","",["PTESTNMB","","PTESTNMW"],""],"???"], + ["???",["","",["PTESTMD","","PTESTMQ"],["PTESTMD","","???"]],["","",["PTESTNMD","","PTESTNMQ"],""],"???"], + ["???","PMULDQ",["","",["PMOVM2B","","PMOVM2W"],""],"???"], + ["???",["PCMPEQQ","PCMPEQQ","PCMPEQQ",""],["","",["PMOVB2M","","PMOVW2M"],""],"???"], + [["???",["MOVNTDQA","","???"],"???","???"],["???","???",["","",["???","","PBROADCASTMB2Q"],""],"???"]], + ["???",["PACKUSDW","","???"],"???","???"], + ["???",["","MASKMOVPS",["SCALEFPS","","SCALEFPD"],""],"???","???"], + ["???",["","MASKMOVPD",["SCALEFSS","","SCALEFSD"],""],"???","???"], + ["???",["","MASKMOVPS","",""],"???","???"], + ["???",["","MASKMOVPD","",""],"???","???"], + ["???","PMOVZXBW",["","","PMOVWB",""],"???"], + ["???","PMOVZXBD",["","","PMOVDB",""],"???"], + ["???","PMOVZXBQ",["","","PMOVQB",""],"???"], + ["???","PMOVZXWD",["","","PMOVDW",""],"???"], + ["???","PMOVZXWQ",["","","PMOVQW",""],"???"], + ["???","PMOVZXDQ",["","",["PMOVQD","PMOVQD",""],""],"???"], + ["???",["","PERMD",["PERMD","","PERMQ"],["PERMD","","???"]],"???","???"], + ["???",["PCMPGTQ","PCMPGTQ","PCMPGTQ",""],"???","???"], + ["???","PMINSB",["","",["PMOVM2D","","PMOVM2Q"],""],"???"], + ["???",["PMINSD","PMINSD",["PMINSD","","PMINSQ"],["PMINSD","","???"]],["","",["PMOVD2M","","PMOVQ2M"],""],"???"], + ["???","PMINUW",["","","PBROADCASTMW2D",""],"???"], + ["???",["PMINUD","PMINUD",["PMINUD","","PMINUQ"],["PMINUD","","???"]],"???","???"], + ["???","PMAXSB","???","???"], + ["???",["PMAXSD","PMAXSD",["PMAXSD","","PMAXSQ"],["PMAXSD","","???"]],"???","???"], + ["???","PMAXUW","???","???"], + ["???",["PMAXUD","PMAXUD",["PMAXUD","","PMAXUQ"],["PMAXUD","","???"]],"???","???"], + ["???",["PMULLD","PMULLD",["PMULLD","","PMULLQ"],["PMULLD","",""]],"???","???"], + ["???",["PHMINPOSUW",["PHMINPOSUW","PHMINPOSUW",""],"",""],"???","???"], + ["???",["","",["GETEXPPS","","GETEXPPD"],["GETEXPPS","","GETEXPPD"]],"???","???"], + ["???",["","",["GETEXPSS","","GETEXPSD"],""],"???","???"], + ["???",["","",["PLZCNTD","","PLZCNTQ"],""],"???","???"], + ["???",["",["PSRLVD","","PSRLVQ"],["PSRLVD","","PSRLVQ"],["PSRLVD","","???"]],"???","???"], + ["???",["",["PSRAVD","",""],["PSRAVD","","PSRAVQ"],["PSRAVD","","???"]],"???","???"], + ["???",["",["PSLLVD","","PSLLVQ"],["PSLLVD","","PSLLVQ"],["PSLLVD","","???"]],"???","???"], + "???","???","???","???", + ["???",["","",["RCP14PS","","RCP14PD"],""],"???","???"], + ["???",["","",["RCP14SS","","RCP14SD"],""],"???","???"], + ["???",["","",["RSQRT14PS","","RSQRT14PD"],""],"???","???"], + ["???",["","",["RSQRT14SS","","RSQRT14SD"],""],"???","???"], + ["???",["","","",["ADDNPS","","ADDNPD"]],"???","???"], + ["???",["","","",["GMAXABSPS","","???"]],"???","???"], + ["???",["","","",["GMINPS","","GMINPD"]],"???","???"], + ["???",["","","",["GMAXPS","","GMAXPD"]],"???","???"], + "", + ["???",["","","",["FIXUPNANPS","","FIXUPNANPD"]],"???","???"], + "","", + ["???",["","PBROADCASTD",["PBROADCASTD","","???"],["PBROADCASTD","","???"]],"???","???"], + ["???",["","PBROADCASTQ",["BROADCASTI32X2","","PBROADCASTQ"],["???","","PBROADCASTQ"]],"???","???"], + ["???",["","BROADCASTI128",["BROADCASTI32X4","","BROADCASTI64X2"],["BROADCASTI32X4","","???"]],"???","???"], + ["???",["","",["BROADCASTI32X8","","BROADCASTI64X4"],["???","","BROADCASTI64X4"]],"???","???"], + ["???",["","","",["PADCD","","???"]],"???","???"], + ["???",["","","",["PADDSETCD","","???"]],"???","???"], + ["???",["","","",["PSBBD","","???"]],"???","???"], + ["???",["","","",["PSUBSETBD","","???"]],"???","???"], + "???","???","???","???", + ["???",["","",["PBLENDMD","","PBLENDMQ"],["PBLENDMD","","PBLENDMQ"]],"???","???"], + ["???",["","",["BLENDMPS","","BLENDMPD"],["BLENDMPS","","BLENDMPD"]],"???","???"], + ["???",["","",["PBLENDMB","","PBLENDMW"],""],"???","???"], + "???","???","???","???","???", + ["???",["","","",["PSUBRD","","???"]],"???","???"], + ["???",["","","",["SUBRPS","","SUBRPD"]],"???","???"], + ["???",["","","",["PSBBRD","","???"]],"???","???"], + ["???",["","","",["PSUBRSETBD","","???"]],"???","???"], + "???","???","???","???", + ["???",["","","",["PCMPLTD","","???"]],"???","???"], + ["???",["","",["PERMI2B","","PERMI2W"],""],"???","???"], + ["???",["","",["PERMI2D","","PERMI2Q"],""],"???","???"], + ["???",["","",["PERMI2PS","","PERMI2PD"],""],"???","???"], + ["???",["","PBROADCASTB",["PBROADCASTB","","???"],""],"???","???"], + ["???",["","PBROADCASTW",["PBROADCASTW","","???"],""],"???","???"], + ["???",["???",["","",["PBROADCASTB","","???"],""],"???","???"]], + ["???",["???",["","",["PBROADCASTW","","???"],""],"???","???"]], + ["???",["","",["PBROADCASTD","","PBROADCASTQ"],""],"???","???"], + ["???",["","",["PERMT2B","","PERMT2W"],""],"???","???"], + ["???",["","",["PERMT2D","","PERMT2Q"],""],"???","???"], + ["???",["","",["PERMT2PS","","PERMT2PD"],""],"???","???"], + [["???","INVEPT","???","???"],"???"], + [["???","INVVPID","???","???"],"???"], + [["???","INVPCID","???","???"],"???"], + ["???",["???","???","PMULTISHIFTQB","???"],"???","???"], + ["???",["","","",["SCALEPS","","???"]],"???","???"], + "???", + ["???",["","","",["PMULHUD","","???"]],"???","???"], + ["???",["","","",["PMULHD","","???"]],"???","???"], + ["???",["","",["EXPANDPS","","EXPANDPD"],""],"???","???"], + ["???",["","",["PEXPANDD","","PEXPANDQ"],""],"???","???"], + ["???",["","",["COMPRESSPS","","COMPRESSPD"],""],"???","???"], + ["???",["","",["PCOMPRESSD","","PCOMPRESSQ"],""],"???","???"], + "???", + ["???",["","",["PERMB","","PERMW"],""],"???","???"], + "???","???", + ["???",["",["PGATHERDD","","PGATHERDQ"],["PGATHERDD","","PGATHERDQ"],["PGATHERDD","","PGATHERDQ"]],"???","???"], + ["???",["",["PGATHERQD","","PGATHERQQ"],["PGATHERQD","","PGATHERQQ"],""],"???","???"], + ["???",["",["GATHERDPS","","GATHERDPD"],["GATHERDPS","","GATHERDPD"],["GATHERDPS","","GATHERDPD"]],"???","???"], + ["???",["",["GATHERQPS","","GATHERQPD"],["GATHERQPS","","GATHERQPD"],""],"???","???"], + "???","???", + ["???",["",["FMADDSUB132PS","","FMADDSUB132PD"],["FMADDSUB132PS","","FMADDSUB132PD"],""],"???","???"], + ["???",["",["FMSUBADD132PS","","FMSUBADD132PD"],["FMSUBADD132PS","","FMSUBADD132PD"],""],"???","???"], + ["???",["",["FMADD132PS","","FMADD132PD"],["FMADD132PS","","FMADD132PD"],["FMADD132PS","","FMADD132PD"]],"???","???"], + ["???",["",["FMADD132SS","","FMADD132SD"],["FMADD132SS","","FMADD132SD"],""],"???","???"], + ["???",["",["FMSUB132PS","","FMSUB132PD"],["FMSUB132PS","","FMSUB132PD"],["FMSUB132PS","","FMSUB132PD"]],"???","???"], + ["???",["",["FMSUB132SS","","FMSUB132SD"],["FMSUB132SS","","FMSUB132SD"],""],"???","???"], + ["???",["",["FNMADD132PS","","FNMADD132PD"],["FNMADD132PS","","FNMADD132PD"],["NMADD132PS","","FNMADD132PD"]],"???","???"], + ["???",["",["FNMADD132SS","","FNMADD132SD"],["FNMADD132SS","","FNMADD132SD"],""],"???","???"], + ["???",["",["FNMSUB132PS","","FNMSUB132PD"],["FNMSUB132PS","","FNMSUB132PD"],["FNMSUB132PS","","FNMSUB132PS"]],"???","???"], + ["???",["",["FNMSUB132SS","","FNMSUB132SD"],["FNMSUB132SS","","FNMSUB132SD"],""],"???","???"], + ["???",["","",["PSCATTERDD","","PSCATTERDQ"],["PSCATTERDD","","PSCATTERDQ"]],"???","???"], + ["???",["","",["PSCATTERQD","","PSCATTERQQ"],""],"???","???"], + ["???",["","",["SCATTERDPS","","SCATTERDPD"],["SCATTERDPS","","SCATTERDPD"]],"???","???"], + ["???",["","",["SCATTERQPS","","SCATTERQPD"],""],"???","???"], + ["???",["","","",["FMADD233PS","","???"]],"???","???"], + "???", + ["???",["",["FMADDSUB213PS","","FMADDSUB213PD"],["FMADDSUB213PS","","FMADDSUB213PD"],""],"???","???"], + ["???",["",["FMSUBADD213PS","","FMSUBADD213PD"],["FMSUBADD213PS","","FMSUBADD213PD"],""],"???","???"], + ["???",["",["FMADD213PS","","FMADD213PD"],["FMADD213PS","","FMADD213PD"],["FMADD213PS","","FMADD213PD"]],"???","???"], + ["???",["",["FMADD213SS","","FMADD213SD"],["FMADD213SS","","FMADD213SD"],""],"???","???"], + ["???",["",["FMSUB213PS","","FMSUB213PD"],["FMSUB213PS","","FMSUB213PD"],["FMSUB213PS","","FMSUB213PD"]],"???","???"], + ["???",["",["FMSUB213SS","","FMSUB213SD"],["FMSUB213SS","","FMSUB213SD"],""],"???","???"], + ["???",["",["FNMADD213PS","","FNMADD213PD"],["FNMADD213PS","","FNMADD213PD"],["FNMADD213PS","","FNMADD213PD"]],"???","???"], + ["???",["",["FNMADD213SS","","FNMADD213SD"],["FNMADD213SS","","FNMADD213SD"],""],"???","???"], + ["???",["",["FNMSUB213PS","","FNMSUB213PD"],["FNMSUB213PS","","FNMSUB213PD"],["FNMSUB213PS","","FNMSUB213PD"]],"???","???"], + ["???",["",["FNMSUB213SS","","FNMSUB213SD"],["FNMSUB213SS","","FNMSUB213SD"],""],"???","???"], + "???","???","???","???", + ["???",["","","PMADD52LUQ",["PMADD233D","","???"]],"???","???"], + ["???",["","","PMADD52HUQ",["PMADD231D","","???"]],"???","???"], + ["???",["",["FMADDSUB231PS","","FMADDSUB231PD"],["FMADDSUB231PS","","FMADDSUB231PD"],""],"???","???"], + ["???",["",["FMSUBADD231PS","","FMSUBADD231PD"],["FMSUBADD231PS","","FMSUBADD231PD"],""],"???","???"], + ["???",["",["FMADD231PS","","FMADD231PD"],["FMADD231PS","","FMADD231PD"],["FMADD231PS","","FMADD231PD"]],"???","???"], + ["???",["",["FMADD231SS","","FMADD231SD"],["FMADD231SS","","FMADD231SD"],""],"???","???"], + ["???",["",["FMSUB231PS","","FMSUB231PD"],["FMSUB231PS","","FMSUB231PD"],["FMSUB231PS","","FMSUB231PD"]],"???","???"], + ["???",["",["FMSUB231SS","","FMSUB231SD"],["FMSUB231SS","","FMSUB231SD"],""],"???","???"], + ["???",["",["FNMADD231PS","","FNMADD231PD"],["FNMADD231PS","","FNMADD231PD"],["FNMADD231PS","","FNMADD231PD"]],"???","???"], + ["???",["",["FNMADD231SS","","FNMADD231SD"],["FNMADD231SS","","FNMADD231SD"],""],"???","???"], + ["???",["",["FNMSUB231PS","","FNMSUB231PD"],["FNMSUB231PS","","FNMSUB231PD"],["FNMSUB231PS","","FNMSUB231PD"]],"???","???"], + ["???",["",["FNMSUB231SS","","FNMSUB231SD"],["FNMSUB231SS","","FNMSUB231SD"],""],"???","???"], + "???","???","???","???", + ["???",["","",["PCONFLICTD","","PCONFLICTQ"],""],"???","???"], + "???", + [ + [ + ["???",["","","",["GATHERPF0HINTDPS","","GATHERPF0HINTDPD"]],"???","???"], + ["???",["","",["GATHERPF0DPS","","GATHERPF0DPD"],["GATHERPF0DPS","",""]],"???","???"], + ["???",["","",["GATHERPF1DPS","","GATHERPF1DPD"],["GATHERPF1DPS","",""]],"???","???"], + "???", + ["???",["","","",["SCATTERPF0HINTDPS","","SCATTERPF0HINTDPD"]],"???","???"], + ["???",["","",["SCATTERPF0DPS","","SCATTERPF0DPD"],["VSCATTERPF0DPS","",""]],"???","???"], + ["???",["","",["SCATTERPF1DPS","","SCATTERPF1DPD"],["VSCATTERPF1DPS","",""]],"???","???"], + "???" + ],"???" + ], + [ + [ + "???", + ["???",["","",["GATHERPF0QPS","","GATHERPF0QPD"],""],"???","???"], + ["???",["","",["GATHERPF1QPS","","GATHERPF1QPD"],""],"???","???"], + "???","???", + ["???",["","",["SCATTERPF0QPS","","SCATTERPF0QPD"],""],"???","???"], + ["???",["","",["SCATTERPF1QPS","","SCATTERPF1QPD"],""],"???","???"], + "???" + ],"???" + ], + [["SHA1NEXTE","","",""],["","",["EXP2PS","","EXP2PD"],["EXP223PS","","???"]],"???","???"], + [["SHA1MSG1","","",""],["","","",["LOG2PS","","???"]],"???","???"], + [["SHA1MSG2","","",""],["","",["RCP28PS","","RCP28PD"],["RCP23PS","","???"]],"???","???"], + [["SHA256RNDS2","","",""],["","",["RCP28SS","","RCP28SD"],["RSQRT23PS","","???"]],"???","???"], + [["SHA256MSG1","","",""],["","",["RSQRT28PS","","RSQRT28PD"],["ADDSETSPS","","???"]],"???","???"], + [["SHA256MSG2","","",""],["","",["RSQRT28SS","","RSQRT28SD"],["PADDSETSD","","???"]],"???","???"], + "???","???", + [[["","","",["LOADUNPACKLD","","LOADUNPACKLQ"]],["","","",["PACKSTORELD","","PACKSTORELQ"]],"???","???"],"???"], + [[["","","",["LOADUNPACKLPS","","LOADUNPACKLPD"]],["","","",["PACKSTORELPS","","PACKSTORELPD"]],"???","???"],"???"], + "???","???", + [[["","","",["LOADUNPACKHD","","LOADUNPACKHQ"]],["","","",["PACKSTOREHD","","PACKSTOREHQ"]],"???","???"],"???"], + [[["","","",["LOADUNPACKHPS","","LOADUNPACKHPD"]],["","","",["PACKSTOREHPS","","PACKSTOREHPD"]],"???","???"],"???"], + "???","???","???","???","???", + ["???",["AESIMC","AESIMC","",""],"???","???"], + ["???",["AESENC","AESENC","",""],"???","???"], + ["???",["AESENCLAST","AESENCLAST","",""],"???","???"], + ["???",["AESDEC","AESDEC","",""],"???","???"], + ["???",["AESDECLAST","AESDECLAST","",""],"???","???"], + "???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???", + [ + ["MOVBE","","",""], + ["MOVBE","","",""],"???", + ["CRC32","","",""] + ], + [ + ["MOVBE","","",""], + ["MOVBE","","",""],"???", + ["CRC32","","",""] + ], + ["???",["","ANDN","",""],"???","???"], + [ + "???", + ["???",["","BLSR","",""],"???","???"], + ["???",["","BLSMSK","",""],"???","???"], + ["???",["","BLSI","",""],"???","???"], + "???","???","???","???" + ],"???", + [ + ["","BZHI","",""],"???", + ["","PEXT","",""], + ["","PDEP","",""] + ], + [ + "???", + ["ADCX","","",""], + ["ADOX","","",""], + ["","MULX","",""] + ], + [ + ["","BEXTR","",""], + ["","SHLX","",""], + ["","SARX","",""], + ["","SHRX","",""] + ], + "???","???","???","???","???","???","???","???", + /*------------------------------------------------------------------------------------------------------------------------ + Three Byte operations 0F38. Opcodes plus 768 goes to 767 used by escape codes "0F, 3A", Or + set directly by adding map bits "11" because "11 00000000" bin = 768 plus opcode. + ------------------------------------------------------------------------------------------------------------------------*/ + ["???",["","PERMQ","PERMQ",""],"???","???"], + ["???",["","PERMPD","PERMPD",""],"???","???"], + ["???",["",["PBLENDD","",""],"",""],"???","???"], + ["???",["","",["ALIGND","","ALIGNQ"],["ALIGND","","???"]],"???","???"], + ["???",["","PERMILPS",["PERMILPS","","???"],""],"???","???"], + ["???",["","PERMILPD","PERMILPD",""],"???","???"], + ["???",["","PERM2F128","",""],"???","???"], + ["???",["","","",["PERMF32X4","","???"]],"???","???"], + ["???",["ROUNDPS","ROUNDPS",["RNDSCALEPS","","???"],""],"???","???"], + ["???",["ROUNDPD","ROUNDPD","RNDSCALEPD",""],"???","???"], + ["???",["ROUNDSS","ROUNDSS",["RNDSCALESS","","???"],""],"???","???"], + ["???",["ROUNDSD","ROUNDSD","RNDSCALESD",""],"???","???"], + ["???",["BLENDPS","BLENDPS","",""],"???","???"], + ["???",["BLENDPD","BLENDPD","",""],"???","???"], + ["???",["PBLENDW","PBLENDW","",""],"???","???"], + [["PALIGNR","","",""],"PALIGNR","???","???"], + "???","???","???","???", + [["???","PEXTRB","???","???"],["???","PEXTRB","???","???"]], + [["???","PEXTRW","???","???"],["???","PEXTRW","???","???"]], + ["???",["PEXTRD","","PEXTRQ"],"???","???"], + ["???","EXTRACTPS","???","???"], + ["???",["","INSERTF128",["INSERTF32X4","","INSERTF64X2"],""],"???","???"], + ["???",["","EXTRACTF128",["EXTRACTF32X4","","EXTRACTF64X2"],""],"???","???"], + ["???",["","",["INSERTF32X8","","INSERTF64X4"],""],"???","???"], + ["???",["","",["EXTRACTF32X8","","EXTRACTF64X4"],""],"???","???"], + "???", + ["???",["","CVTPS2PH",["CVTPS2PH","","???"],""],"???","???"], + ["???",["","",["PCMP,UD,","","PCMP,UQ,"],["PCMP,UD,","","???"]],"???","???"], + ["???",["","",["PCM,PD,","","PCM,PQ,"],["PCM,PD,","","???"]],"???","???"], + ["???","PINSRB","???","???"], + ["???",["INSERTPS","","???"],"???","???"], + ["???",["",["PINSRD","","PINSRQ"],["PINSRD","","PINSRQ"],""],"???","???"], + ["???",["","",["SHUFF32X4","","SHUFF64X2"],""],"???","???"], + "???", + ["???",["","",["PTERNLOGD","","PTERNLOGQ"],""],"???","???"], + ["???",["","",["GETMANTPS","","GETMANTPD"],["GETMANTPS","","GETMANTPD"]],"???","???"], + ["???",["","",["GETMANTSS","","GETMANTSD"],""],"???","???"], + "???","???","???","???","???","???","???","???", + ["???",["",["KSHIFTRB","","KSHIFTRW"],"",""],"???","???"], + ["???",["",["KSHIFTRD","","KSHIFTRQ"],"",""],"???","???"], + ["???",["",["KSHIFTLB","","KSHIFTLW"],"",""],"???","???"], + ["???",["",["KSHIFTLD","","KSHIFTLQ"],"",""],"???","???"], + "???","???","???","???", + ["???",["","INSERTI128",["INSERTI32X4","","INSERTI64X2"],""],"???","???"], + ["???",["","EXTRACTI128",["EXTRACTI32X4","","EXTRACTI64X2"],""],"???","???"], + ["???",["","",["INSERTI32X8","","INSERTI64X4"],""],"???","???"], + ["???",["","",["EXTRACTI32X8","","EXTRACTI64X4"],""],"???","???"], + "???","???", + ["???",["","KEXTRACT",["PCMP,UB,","","PCMP,UW,"],""],"???","???"], + ["???",["","",["PCM,PB,","","PCM,PW,"],""],"???","???"], + ["???",["DPPS","DPPS","",""],"???","???"], + ["???",["DPPD","DPPD","",""],"???","???"], + ["???",["MPSADBW","MPSADBW",["DBPSADBW","","???"],""],"???","???"], + ["???",["","",["SHUFI32X4","","SHUFI64X2"],""],"???","???"], + ["???",["PCLMULQDQ","PCLMULQDQ","",""],"???","???"], + "???", + ["???",["","PERM2I128","",""],"???","???"], + "???", + ["???",["",["PERMIL2PS","","PERMIL2PS"],"",""],"???","???"], + ["???",["",["PERMIL2PD","","PERMIL2PD"],"",""],"???","???"], + ["???",["","BLENDVPS","",""],"???","???"], + ["???",["","BLENDVPD","",""],"???","???"], + ["???",["","PBLENDVB","",""],"???","???"], + "???","???","???", + ["???",["","",["RANGEPS","","RANGEPD"],""],"???","???"], + ["???",["","",["RANGESS","","RANGESD"],""],"???","???"], + ["???",["","","",["RNDFXPNTPS","","RNDFXPNTPD"]],"???","???"], + "???", + ["???",["","",["FIXUPIMMPS","","FIXUPIMMPD"],""],"???","???"], + ["???",["","",["FIXUPIMMSS","","FIXUPIMMSD"],""],"???","???"], + ["???",["","",["REDUCEPS","","REDUCEPD"],""],"???","???"], + ["???",["","",["REDUCESS","","REDUCESD"],""],"???","???"], + "???","???","???","???", + ["???",["",["FMADDSUBPS","","FMADDSUBPS"],"",""],"???","???"], + ["???",["",["FMADDSUBPD","","FMADDSUBPD"],"",""],"???","???"], + ["???",["",["FMSUBADDPS","","FMSUBADDPS"],"",""],"???","???"], + ["???",["",["FMSUBADDPD","","FMSUBADDPD"],"",""],"???","???"], + ["???",["PCMPESTRM","PCMPESTRM","",""],"???","???"], + ["???",["PCMPESTRI","PCMPESTRI","",""],"???","???"], + ["???",["PCMPISTRM","PCMPISTRM","",""],"???","???"], + ["???",["PCMPISTRI","PCMPISTRI","",""],"???","???"], + "???","???", + ["???",["","",["FPCLASSPS","","FPCLASSPD"],""],"???","???"], + ["???",["","",["FPCLASSSS","","FPCLASSSD"],""],"???","???"], + ["???",["",["FMADDPS","","FMADDPS"],"",""],"???","???"], + ["???",["",["FMADDPD","","FMADDPD"],"",""],"???","???"], + ["???",["",["FMADDSS","","FMADDSS"],"",""],"???","???"], + ["???",["",["FMADDSD","","FMADDSD"],"",""],"???","???"], + ["???",["",["FMSUBPS","","FMSUBPS"],"",""],"???","???"], + ["???",["",["FMSUBPD","","FMSUBPD"],"",""],"???","???"], + ["???",["",["FMSUBSS","","FMSUBSS"],"",""],"???","???"], + ["???",["",["FMSUBSD","","FMSUBSD"],"",""],"???","???"], + "???","???","???","???","???","???","???","???", + ["???",["",["FNMADDPS","","FNMADDPS"],"",""],"???","???"], + ["???",["",["FNMADDPD","","FNMADDPD"],"",""],"???","???"], + ["???",["",["FNMADDSS","","FNMADDSS"],"",""],"???","???"], + ["???",["",["FNMADDSD","","FNMADDSD"],"",""],"???","???"], + ["???",["",["FNMSUBPS","","FNMSUBPS"],"",""],"???","???"], + ["???",["",["FNMSUBPD","","FNMSUBPD"],"",""],"???","???"], + ["???",["",["FNMSUBSS","","FNMSUBSS"],"",""],"???","???"], + ["???",["",["FNMSUBSD","","FNMSUBSD"],"",""],"???","???"], + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???", + [["","","","CVTFXPNTUDQ2PS"],["","","",["CVTFXPNTPS2UDQ","","???"]],"???",["","","","CVTFXPNTPD2UDQ"]], + [["","","","CVTFXPNTDQ2PS"],["","","",["CVTFXPNTPS2DQ","","???"]],"???","???"], + "SHA1RNDS4", + "???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + ["???",["AESKEYGENASSIST","AESKEYGENASSIST","",""],"???","???"], + "???","???","???","???","???","???", + ["???","???","???",["","","","CVTFXPNTPD2DQ"]], + "???","???","???","???","???","???","???","???","???", + ["???","???","???",["","RORX","",""]], + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + /*------------------------------------------------------------------------------------------------------------------------ + AMD XOP 8. + ------------------------------------------------------------------------------------------------------------------------*/ + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "VPMACSSWW","VPMACSSWD","VPMACSSDQL","???","???","???","???","???","???", + "VPMACSSDD","VPMACSSDQH","???","???","???","???","???","VPMACSWW","VPMACSWD","VPMACSDQL", + "???","???","???","???","???","???","VPMACSDD","VPMACSDQH", + "???","???",["VPCMOV","","VPCMOV"],["VPPERM","","VPPERM"],"???","???","VPMADCSSWD", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "VPMADCSWD","???","???","???","???","???","???","???","???","???", + "VPROTB","VPROTW","VPROTD","VPROTQ","???","???","???","???","???","???","???","???", + "VPCOM,B,","VPCOM,W,","VPCOM,D,","VPCOM,Q,","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "VPCOM,UB,","VPCOM,UW,","VPCOM,UD,","VPCOM,UQ,", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + /*------------------------------------------------------------------------------------------------------------------------ + AMD XOP 9. + ------------------------------------------------------------------------------------------------------------------------*/ + "???", + ["???","BLCFILL","BLSFILL","BLCS","TZMSK","BLCIC","BLSIC","T1MSKC"],["???","BLCMSK","???","???","???","???","BLCI","???"], + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + ["???",["LLWPCB","SLWPCB","???","???","???","???","???","???"]], + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "VFRCZPS","VFRCZPD","VFRCZSS","VFRCZSD","???","???","???","???","???","???","???","???","???","???","???","???", + ["VPROTB","","VPROTB"],["VPROTW","","VPROTW"],["VPROTD","","VPROTD"],["VPROTQ","","VPROTQ"], + ["VPSHLB","","VPSHLB"],["VPSHLW","","VPSHLW"],["VPSHLD","","VPSHLD"],["VPSHLQ","","VPSHLQ"], + ["VPSHAB","","VPSHAB"],["VPSHAW","","VPSHAW"],["VPSHAD","","VPSHAD"],["VPSHAQ","","VPSHAQ"], + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "VPHADDBW","VPHADDBD","VPHADDBQ","???","???","VPHADDWD","VPHADDWQ","???","???","???","VPHADDDQ","???","???","???","???","???", + "VPHADDUBWD","VPHADDUBD","VPHADDUBQ","???","???","VPHADDUWD","VPHADDUWQ","???","???","???","VPHADDUDQ","???","???","???","???","???", + "VPHSUBBW","VPHSUBWD","VPHSUBDQ","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???", + /*------------------------------------------------------------------------------------------------------------------------ + AMD XOP A. + ------------------------------------------------------------------------------------------------------------------------*/ + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "BEXTR","???",["LWPINS","LWPVAL","???","???","???","???","???","???"], + "???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + /*------------------------------------------------------------------------------------------------------------------------- + L1OM Vector. + -------------------------------------------------------------------------------------------------------------------------*/ + "???","???","???","???","DELAY","???","???","???","???","???","???","???","???","???","???","???", + [["VLOADD","VLOADQ","",""],"???"],"???", + [["VLOADUNPACKLD","VLOADUNPACKLQ","",""],"???"], + [["VLOADUNPACKHD","VLOADUNPACKHQ","",""],"???"], + [["VSTORED","VSTOREQ","",""],"???"],"???", + [["VPACKSTORELD","VPACKSTORELQ","",""],"???"], + [["VPACKSTOREHD","VPACKSTOREHQ","",""],"???"], + ["VGATHERD","???"],["VGATHERPFD","???"],"???",["VGATHERPF2D","???"], + ["VSCATTERD","???"],["VSCATTERPFD","???"],"???",["VSCATTERPF2D","???"], + ["VCMP,PS,","VCMP,PD,","",""],"VCMP,PI,","VCMP,PU,","???", + ["VCMP,PS,","VCMP,PD,","",""],"VCMP,PI,","VCMP,PU,","???", + "???","???","???","???","???","???","???","???", + "VTESTPI","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + ["VADDPS","VADDPD","",""],"VADDPI","???","VADDSETCPI","???","VADCPI","VADDSETSPS","VADDSETSPI", + ["VADDNPS","VADDNPD","",""],"???","???","???","???","???","???","???", + ["VSUBPS","VSUBPD","",""],"VSUBPI","???","VSUBSETBPI","???","VSBBPI","???","???", + ["VSUBRPS","VSUBRPD","",""],"VSUBRPI","???","VSUBRSETBPI","???","VSBBRPI","???","???", + ["VMADD231PS","VMADD231PD","",""],"VMADD231PI", + ["VMADD213PS","VMADD213PD","",""],"???", + ["VMADD132PS","VMADD132PD","",""],"???", + "VMADD233PS","VMADD233PI", + ["VMSUB231PS","VMSUB231PD","",""],"???", + ["VMSUB213PS","VMSUB213PD","",""],"???", + ["VMSUB132PS","VMSUB132PD","",""],"???","???","???", + ["VMADDN231PS","VMADDN231PD","",""],"???", + ["VMADDN213PS","VMADDN213PD","",""],"???", + ["VMADDN132PS","VMADDN132PD","",""],"???","???","???", + ["VMSUBR231PS","VMSUBR231PD","",""],"???", + ["VMSUBR213PS","VMSUBR213PD","",""],"???", + ["VMSUBR132PS","VMSUBR132PD","",""],"???", + ["VMSUBR23C1PS","VMSUBR23C1PD","",""],"???", + ["VMULPS","VMULPD","",""],"VMULHPI","VMULHPU","VMULLPI","???","???","VCLAMPZPS","VCLAMPZPI", + ["VMAXPS","VMAXPD","",""],"VMAXPI","VMAXPU","???", + ["VMINPS","VMINPD","",""],"VMINPI","VMINPU","???", + ["???","VCVT,PD2PS,","",""],["VCVTPS2PI","VCVT,PD2PI,","",""],["VCVTPS2PU","VCVT,PD2PU,","",""],"???", + ["???","VCVT,PS2PD,","",""],["VCVTPI2PS","VCVT,PI2PD,","",""],["VCVTPU2PS","VCVT,PU2PD,","",""],"???", + "VROUNDPS","???","VCVTINSPS2U10","VCVTINSPS2F11","???","VCVTPS2SRGB8","VMAXABSPS","???", + "VSLLPI","VSRAPI","VSRLPI","???", + ["VANDNPI","VANDNPQ","",""],["VANDPI","VANDPQ","",""], + ["VORPI","VORPQ","",""],["VXORPI","VXORPQ","",""], + "VBINTINTERLEAVE11PI","VBINTINTERLEAVE21PI","???","???","???","???","???","???", + "VEXP2LUTPS","VLOG2LUTPS","VRSQRTLUTPS","???","VGETEXPPS","???","???","???", + "VSCALEPS","???","???","???","???","???","???","???", + "VRCPRESPS","???","VRCPREFINEPS","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "???","???","???","???","???","???","???","???","???","???","???","???","???","???","???","???", + "VFIXUPPS","VSHUF128X32","VINSERTFIELDPI","VROTATEFIELDPI","???","???","???","???", + "???","???","???","???","???","???","???","???", + /*------------------------------------------------------------------------------------------------------------------------- + L1OM Mask, Mem, and bit opcodes. + -------------------------------------------------------------------------------------------------------------------------*/ + ["???","BSFI"],["???","BSFI"],["???","BSFI"],["???","BSFI"], + ["???","BSRI"],["???","BSRI"],["???","BSRI"],["???","BSRI"], + ["???","BSFF"],["???","BSFF"],["???","BSFF"],["???","BSFF"], + ["???","BSRF"],["???","BSRF"],["???","BSRF"],["???","BSRF"], + ["???","BITINTERLEAVE11"],["???","BITINTERLEAVE11"],["???","BITINTERLEAVE11"],["???","BITINTERLEAVE11"], + ["???","BITINTERLEAVE21"],["???","BITINTERLEAVE21"],["???","BITINTERLEAVE21"],["???","BITINTERLEAVE21"], + ["???","INSERTFIELD"],["???","INSERTFIELD"],["???","INSERTFIELD"],["???","INSERTFIELD"], + ["???","ROTATEFIELD"],["???","ROTATEFIELD"],["???","ROTATEFIELD"],["???","ROTATEFIELD"], + ["???","COUNTBITS"],["???","COUNTBITS"],["???","COUNTBITS"],["???","COUNTBITS"], + ["???","QUADMASK16"],["???","QUADMASK16"],["???","QUADMASK16"],["???","QUADMASK16"], + "???","???","???","???", + "VKMOVLHB", + [["CLEVICT1","CLEVICT2","LDVXCSR","STVXCSR","???","???","???","???"],"???"], + [["VPREFETCH1","VPREFETCH2","???","???","???","???","???","???"],"???"], + [["VPREFETCH1","VPREFETCH2","???","???","???","???","???","???"],"???"], + "VKMOV","VKMOV","VKMOV","VKMOV", + "VKNOT","VKANDNR","VKANDN","VKAND", + "VKXNOR","VKXOR","VKORTEST","VKOR", + "???","VKSWAPB", + ["???",["DELAY","SPFLT","???","???","???","???","???","???"]], + ["???",["DELAY","SPFLT","???","???","???","???","???","???"]] +]; + +/*------------------------------------------------------------------------------------------------------------------------- +The Operand type array each operation code can use different operands that must be decoded after the select Opcode. +Basically some instruction may use the ModR/M talked about above while some may use an Immediate, or Both. +An Immediate input uses the byte after the opcode as a number some instructions combine a number and an ModR/M address selection +By using two bytes for each encoding after the opcode. X86 uses very few operand types for input selections to instructions, but +there are many useful combinations. The order the operands are "displayed" is the order they are in the Operands string for the +operation code. +--------------------------------------------------------------------------------------------------------------------------- +The first 2 digits is the selected operand type, and for if the operand can change size. Again more opcodes where sacrificed +to make this an setting Opcode "66" goes 16 bit this is explained in detail in the SizeAttrSelect variable section that is +adjusted by the function ^DecodePrefixAdjustments()^. The Variable SizeAttrSelect effects all operand formats that are decoded by +different functions except for single size. Don't forget X86 uses very few operand types in which different prefix adjustments +are used to add extra functionality to each operand type. The next two numbers is the operands size settings. +If the operand number is set to the operand version that can not change size then the next two numbers act as a single size for +faster decoding. Single size is also used to select numbers that are higher than the max size to select special registers that +are used by some instructions like Debug Registers. +--------------------------------------------------------------------------------------------------------------------------- +Registers have 8, 16, 32, 64, 128, 256, 512 names. The selected ModR/M address location uses a pointer name that shows it's select +size then it's location in left, and right brackets like "QWORD PTR[Address]". The pointer name changes by sizes 8, 16, 64, 128, 256, 512. +--------------------------------------------------------------------------------------------------------------------------- +Used by function ^DecodeOpcode()^ after ^DecodePrefixAdjustments()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +const Operands = [ + //------------------------------------------------------------------------------------------------------------------------ + //First Byte operations. + //------------------------------------------------------------------------------------------------------------------------ + "06000A000003","070E0B0E0003","0A0006000003","0B0E070E0003","16000C000003","170E0DE60003","","", + "06000A000003","070E0B0E0003","0A0006000003","0B0E070E0003","16000C000003","170E0DE60003","","", + "06000A000003","070E0B0E0003","0A0006000003","0B0E070E0003","16000C000003","170E0DE60003","","", + "06000A000003","070E0B0E0003","0A0006000003","0B0E070E0003","16000C000003","170E0DE60003","","", + "06000A000003","070E0B0E0003","0A0006000003","0B0E070E0003","16000C000003","170E0DE60003","","", + "06000A000003","070E0B0E0003","0A0006000003","0B0E070E0003","16000C000003","170E0DE60003","","", + "06000A000003","070E0B0E0003","0A0006000003","0B0E070E0003","16000C000003","170E0DE60003","","", + "06000A00","070E0B0E","0A000600","0B0E070E","16000C00","170E0DE6","","", + "03060003","03060003","03060003","03060003","03060003","03060003","03060003","03060003", + "03060003","03060003","03060003","03060003","03060003","03060003","03060003","03060003", + "030A","030A","030A","030A","030A","030A","030A","030A", + "030A","030A","030A","030A","030A","030A","030A","030A", + ["","",""],["","",""], + ["0A020606","0A010604",""], + "0B0E0704", + "","","","", + "0DE6","0B0E070E0DE6", + "0DA1","0B0E070E0DE1", + "22001A01","230E1A01","1A012000","1A01210E", + "10000002000C","10000002000C","10000002000C","10000002000C","10000002000C","10000002000C","10000002000C","10000002000C", + "10000002000C","10000002000C","10000002000C","10000002000C","10000002000C","10000002000C","10000002000C","10000002000C", + ["06000C000003","06000C000003","06000C000003","06000C000003","06000C000003","06000C000003","06000C000003","06000C00"], + ["070E0DE60003","070E0DE60003","070E0DE60003","070E0DE60003","070E0DE60003","070E0DE60003","070E0DE60003","070E0DE6"], + ["06000C000003","06000C000003","06000C000003","06000C000003","06000C000003","06000C000003","06000C000003","06000C00"], + ["070E0DE10003","070E0DE10003","070E0DE10003","070E0DE10003","070E0DE10003","070E0DE10003","070E0DE10003","070E0DE1"], + "06000A00","070E0B0E", + "0A0006000003","0B0E070E0003", + "06000A000001","070E0B0E0001", + "0A0006000001","0B0E070E0001", + "06020A080001", + ["0B0E0601",""], + "0A0806020001", + ["070A","","","","","","",""], + [["","","",""],["","","",""],["","","",""],["","","",""]], + "170E030E0003","170E030E0003","170E030E0003","170E030E0003","170E030E0003","170E030E0003","170E030E0003", + ["","",""],["","",""], + "0D060C01", //CALL Ap (w:z). + "", + ["","",""],["","",""], + "","", + "160004000001","170E050E0001", + "040016000001","050E170E0001", + "22002000","230E210E", + "22002000","230E210E", + "16000C00","170E0DE6", + "22001600","230E170E","16002000","170E210E","16002200","170E230E", + "02000C000001","02000C000001","02000C000001","02000C000001","02000C000001","02000C000001","02000C000001","02000C000001", + "030E0D0E0001","030E0D0E0001","030E0D0E0001","030E0D0E0001","030E0D0E0001","030E0D0E0001","030E0D0E0001","030E0D0E0001", + ["06000C00","06000C00","06000C00","06000C00","06000C00","06000C00","06000C00","06000C00"], + ["070E0C00","070E0C00","070E0C00","070E0C00","070E0C00","070E0C00","070E0C00","070E0C00"], + "0C010008","0008", + "0B060906","0B060906", + [ + "06000C000001","","","","","","", + ["0C00","0C00","0C00","0C00","0C00","0C00","0C00","0C00"] + ], + [ + "070E0D060001","","","","","","", + ["1002","1002","1002","1002","1002","1002","1002","1002"] + ], + "0C010C00","", + "0C01","","2C00", + "0C00","", + ["","",""], + ["06002A00","06002A00","06002A00","06002A00","06002A00","06002A00","06002A00","06002A00"], + ["070E2A00","070E2A00","070E2A00","070E2A00","070E2A00","070E2A00","070E2A00","070E2A00"], + ["06001800","06001800","06001800","06001800","06001800","06001800","06001800","06001800"], + ["070E1800","070E1800","070E1800","070E1800","070E1800","070E1800","070E1800","070E1800"], + "0C00","0C00","", + "1E00", + /*------------------------------------------------------------------------------------------------------------------------ + X87 FPU. + ------------------------------------------------------------------------------------------------------------------------*/ + [ + ["0604","0604","0604","0604","0604","0604","0604","0604"], + ["24080609","24080609","0609","0609","24080609","24080609","24080609","24080609"] + ], + [ + ["0604","","0604","0604","0601","0602","0601","0602"], + [ + "0609","0609", + ["","","","","","","",""], + "0609", + ["","","","","","","",""], + ["","","","","","","",""], + ["","","","","","","",""], + ["","","","","","","",""] + ] + ], + [ + ["0604","0604","0604","0604","0604","0604","0604","0604"], + [ + "24080609","24080609","24080609","24080609","", + ["","","","","","","",""],"","" + ] + ], + [ + ["0604","0604","0604","0604","","0607","","0607",""], + [ + "24080609","24080609","24080609","24080609", + ["","","","","","","",""], + "24080609","24080609","" + ] + ], + [ + ["0606","0606","0606","0606","0606","0606","0606","0606"], + ["06092408","06092408","0609","0609","06092408","06092408","06092408","06092408"] + ], + [ + ["0606","0606","0606","0606","0606","","0601","0602"], + ["0609","0609","0609","0609","0609","0609","",""] + ], + [ + ["0602","0602","0602","0602","0602","0602","0602","0602"], + [ + "06092408","06092408","0609", + ["","","","","","","",""], + "06092408","06092408","06092408","06092408" + ] + ], + [ + ["0602","0602","0602","0602","0607","0606","0607","0606"], + [ + "0609","0609","0609","0609", + ["1601","","","","","","",""], + "24080609","24080609", + "" + ] + ], + /*------------------------------------------------------------------------------------------------------------------------ + End of X87 FPU. + ------------------------------------------------------------------------------------------------------------------------*/ + "10000004","10000004","10000004","10000004", + "16000C00","170E0C00","0C001600","0C00170E", + "110E0008", + "110E0008", + "0D060C01", //JMP Ap (w:z). + "100000040004", + "16001A01","170E1A01", + "1A011600","1A01170E", + "","","","","","", + ["06000C00","","06000003","06000003","16000600","0600","16000600","0600"], + ["070E0D06","","070E0003","070E0003","170E070E","070E","170E070E","170E070E"], + "","","","","","", + ["06000003","06000003","","","","","",""], + [ + ["070E0003","070E0003","070A0004","090E0008","070A0008","090E0008","070A",""], + ["070E0003","070E0003","070A0008","","070A0008","","070A",""] + ], + /*------------------------------------------------------------------------------------------------------------------------ + Two Byte operations. + ------------------------------------------------------------------------------------------------------------------------*/ + [ + ["0602","0602","0602","0602","0602","0602","070E",""], + ["070E","070E","0601","0601","0601","0601","070E",""] + ], + [ + ["0908","0908","0908","0908","0602","","0602","0601"], + [ + ["","","","","","","",""], + ["170819081B08","17081908","","","","","",""], + ["","","","","","","",""], + ["1708","","1708","1708","","","1602","17081802"], + "070E","","0601", + ["","","170819081B08","170819081B08","","","",""] + ] + ], + ["0B0E0612","0B0E070E"],["0B0E0612","0B0E070E"],"", + "","","","", + "","","","", + [["0601","0601","","","","","",""],""], + "", + "0A0A06A9", //3DNow takes ModR/M, IMM8. + [ + ["0B700770","0B700770","0A040603","0A040609"], + ["0B700770","0B700770","0A0412040604","0A0412040604"] + ], + [ + ["07700B70","07700B70","06030A04","06090A04"], + ["07700B70","07700B70","060412040A04","060412040A04"] + ], + [ + ["0A0412040606","0A0412040606","0B700770","0B700768"], + ["0A0412040604","","0B700770","0B700770"] + ], + [["06060A04","06060A04","",""],""], + ["0B70137007700140","0B70137007700140","",""], + ["0B70137007700140","0B70137007700140","",""], + [["0A0412040606","0A0412040606","0B700770",""],["0A0412040604","","0B700770",""]], + [["06060A04","06060A04","",""],""], + [["0601","0601","0601","0601","","","",""],""], + "", + [[["0A0B07080180","","",""],["0A0B07100180","","",""],["0A0B07080180","","",""],["0A0B07080180","","",""]], + ["",["0A0B060B","","",""],["0A0B07080180","","",""],["0A0B07080180","","",""]]], + [[["07080A0B0180","","",""],["07100A0B0180","","",""],["0A0B07080180","","",""],["0A0B07080180","","",""]], + ["",["0A0B060B","","",""],"",["0A0B07080180","","",""]]], + "","","", + "070E", + ["","07080A0C0001"],["","07080A0D0001"], + ["","0A0C07080001"],["","0A0D07080001"], + ["","07080A0E0001"],"", + ["","0A0E07080001"],"", + [ + ["0A040648","0B300730","0B700770","0A06066C0130"], + ["0A040648","0B300730","0B700770","0A06066C0130"], + "","" + ], + [ + [ + ["06480A04","07300B30","07700B70","066C0A060130"], + ["06480A04","07300B30","07700B70","066C0A060130"], + ["","","",["066C0A060138","066C0A060138","066C0A060138"]], + ["","","",["066C0A060138","066C0A060138","066C0A060138"]] + ], + [ + ["06480A04","07300B30","07700B70","066C0A06"], + ["06480A04","07300B30","07700B70","066C0A06"], + "","" + ] + ], + [ + ["0A0406A9","","",""],["0A0406A9","","",""], //Not Allowed to be Vector encoded. + "0A041204070C010A","0A041204070C010A" + ], + [ + [ + "07700B70","07700B70", + ["06030A04","","",""],["06060A04","","",""] //SSE4a can not be vector encoded. + ],"" + ], + [ + ["0A0A0649","","",""],["0A0A0648","","",""], //Not allowed to be Vector encoded. + "0B0C06430109","0B0C06490109" + ], + [ + ["0A0A0649","","",""],["0A0A0648","","",""], //Not allowed to be vector encoded. + "0B0C0643010A","0B0C0649010A" + ], + ["0A0406430101","0A0406490101","",""], + ["0A0406430101","0A0406490101","",""], + "","","","", + "","","", + "", + "",//Three byte opcodes 0F38 + "", + "",//Three byte opcodes 0F3A + "","","","","", + "0B0E070E", + [ + ["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""], + ["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],"","" + ], + [ + ["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""], + ["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],"","" + ], + [["0B0E070E0180","0A0F06FF","",""],"","",""], + [ + ["0B0E070E0180",["0A0F06FF","","0A0F06FF"],"",""], + ["0B0E070E0180",["0A0F06FF","","0A0F06FF"],"",""],"","" + ], + [ + ["0A02070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""], + ["0A02070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],"","" + ], + [ + ["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""], + ["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],"","" + ], + [ + ["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""], + ["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],"","" + ], + [["0B0E070E0180","0A0F06FF","",""],"","",""], + [["0B0E070E0180","0A0F06FF","",""],"","",""], + [ + ["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""], + ["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],"","" + ], + [ + ["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""], + ["0B0E070E0180",["0A0F120F06FF","",""],"",""],"","" + ], + "0B0E070E","0B0E070E","0B0E070E","0B0E070E", + ["",[["0B0C0648","0B0C0730","",""],["0B0C0648","0B0C0730","",""],"",""]], + ["0B7007700142","0B7007700142","0A04120406430102","0A04120406490102"], + [ + ["0A040648","0A040648","",""],"", + ["0A040643","0A0412040643","",""],"" + ], + [ + ["0A040648","0A040648","",""],"", + ["0A040643","0A0412040643","",""],"" + ], + ["0B70137007700140","0B70137007700140","",""], + ["0B70137007700140","0B70137007700140","",""], + ["0B70137007700140","0B70137007700140","",""], + ["0B70137007700140","0B70137007700140","",""], + [ + ["0A040648","0B3013300730","0B70137007700152","0A061206066C0152"], + ["0A040648","0B3013300730","0B70137007700152","0A061206066C0152"], + "0A04120406430102","0A04120406460102" + ], + [ + ["0A040648","0B3013300730","0B70137007700152","0A061206066C0152"], + ["0A040648","0B3013300730","0B70137007700152","0A061206066C0152"], + "0A04120406430102","0A04120406460102" + ], + [ + ["0A040648","0B300718","0B7007380151","0A06065A0171"], + ["0A040648","0B180730","0B3807700152","0A05066C0152"], + "0A04120406430101","0A04120406460102" + ], + [["0B7007700142","","0B380770014A"],["0B700770014A","",""],"0B7007700141",""], + [ + ["0A040648","0B3013300730","0B70137007700152","0A061206066C0152"], + ["0A040648","0B3013300730","0B70137007700152","0A061206066C0152"], + "0A04120406430102","0A04120406460102" + ], + ["0B70137007700141","0B70137007700141","0A04120406430101","0A04120406460101"], + ["0B70137007700142","0B70137007700142","0A04120406430102","0A04120406460102"], + ["0B70137007700141","0B70137007700141","0A04120406430101","0A04120406460101"], + [["0A0A06A3","","",""],"0B70137007700108","",""], + [["0A0A06A3","","",""],"0B70137007700108","",""], + [["0A0A06A3","","",""],"0B701370077001400108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730","0A0F137007700108",""],"",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730","0A0F137007700108",""],"",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730",["0A0F137007700148","",""],["0A0F1206066C0148","",""]],"",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],["0B70137007700148","",""],"",""], + [["0A0A06A9","","",""],["0B70137007700148","",""],"",""], + ["","0B70137007700140","",""], + ["","0B70137007700140","",""], + [["0A0A070C","","",""],["0A04070C0108","","0A04070C0108"],"",""], + [ + [ + ["0A0A06A9","", "",""], + ["0B700770","0B700770",["0B7007700108","","0B700770"],["0A06066C0128","","0A06066C0120"]], + ["0A040710","0B700770",["0B700770","","0B7007700108"],""], + ["","",["0B7007700108","","0B700770"],""] + ], + [ + ["0A0A06A9","", "",""], + ["0B700770","0B700770",["0B7007700108","","0B700770"],["0A06066C0148","","0A06066C0140"]], + ["0A040710","0B700770",["0B700770","","0B7007700108"],""], + ["","",["0B7007700108","","0B700770"],""] + ] + ], + [ + ["0A0A06A90C00","","",""], + ["0A0406480C00","0B3007300C00",["0B7007700C000108","",""],["0A06066C0C000108","",""]], + "0B7007700C000108", + "0B7007700C000108" + ], + [ + "", + [ + "","", + [["060A0C00","","",""],"137007700C000108","",""],"", + [["060A0C00","","",""],"137007700C000108","",""],"", + [["060A0C00","","",""],"137007700C000108","",""],"" + ] + ], + [ + ["",["","",["137007700C000148","","137007700C000140"],""],"",""], + ["",["","",["137007700C000148","","137007700C000140"],""],"",""], + [["060A0C00","","",""],["06480C00","133007300C00",["137007700C000148","",""],["1206066C0C000148","",""]],"",""], + "", + [["060A0C00","","",""],["06480C00","133007300C00",["137007700C000148","","137007700C000140"],["1206066C0C000148","",""]],"",""], + "", + [["060A0C00","","",""],["06480C00","133007300C00",["137007700C000148","",""],["1206066C0C000148","",""]],"",""], + "" + ], + [ + "", + [ + "","", + [["137007700C00","137007700C00","",""],"137007700C000140","",""],["","137007700C000108","",""], + "","", + [["137007700C00","137007700C00","",""],"137007100C000140","",""],["","137007700C000108","",""] + ] + ], + [["0A0A06A9","","",""],["0A040710","13300B300730","0A0F137007700108",""],"",""], + [["0A0A06A9","","",""],["0A040710","13300B300730","0A0F137007700108",""],"",""], + [["0A0A06A9","","",""],["0A040710","13300B300730",["0A0F137007700148","",""],["0A0F1206066C0148","",""]],"",""], + [["",["","",""],"",""],"","",""], + [ + ["07080B080180","",["0B7007700141","","0B3807700149"],""], + ["064F0C000C00","",["0B7007380149","","0B7007700141"],""], + ["","","0B0C06440109",""], + ["0A04064F0C000C00","","0B0C06460109",""] + ], + [ + ["0B0807080180","",["0B7007700142","","0B380770014A"],""], + ["0A04064F","",["0B700738014A","","0B7007700142"],""], + ["","","0B0C0644010A",""], + ["0A04064F","","0B0C0646010A",""] + ], + [ + "", + ["","",["0B7007380149","","0B7007700141"],""], + ["","",["0B7007380142","","0B700770014A"],"0A06065A0170"], + ["","",["0B700770014A","","0B3807700142"],""] + ], + [ + "", + ["","",["0B700738014A","","0B7007700142"],""], + ["","","0A041204070C010A",""], + ["","","0A041204070C010A",""] + ], + [ + "",["0A040604","0B7013700770","",""], + "",["0A040604","0B7013700770","",""] + ], + [ + "",["0A040604","0B7013700770","",""], + "",["0A040604","0B7013700770","",""] + ], + [["070C0A0A","","",""],["06240A040108","","06360A040108"],["0A040646","0A040646",["","","0A0406460108"],""],""], + [ + ["06A90A0A","","",""], + ["06480A04","07300B30",["07700B700108","","07700B70"],["066C0A060128","","066C0A060120"]], + ["06480A04","07300B30",["07700B70","","07700B700108"],""], + ["","",["07700B700108","","07700B70"],""] + ], + "1106000C","1106000C","1106000C","1106000C", + [["1106000C","120F1002","",""],"","",""],[["1106000C","120F1002","",""],"","",""], + "1106000C","1106000C","1106000C","1106000C","1106000C","1106000C","1106000C","1106000C","1106000C","1106000C", + [ + ["0600",["0A0F06F2","","0A0F06F6"],"",""], + ["0600",["0A0F06F0","","0A0F06F4"],"",""],"","" + ], + [ + ["0600",["06120A0F","","06360A0F"],"",""], + ["0600",["06000A0F","","06240A0F"],"",""],"","" + ], + [ + ["0600",["0A0F062F","",""],"",""], + ["0600",["0A0F062F","",""],"",""],"", + ["0600",["0A0F062F","","0A0F063F"],"",""] + ], + [ + ["0600",["062F0A0F","",""],"",""], + ["0600",["062F0A0F","",""],"",""],"", + ["0600",["062F0A0F","","063F0A0F"],"",""] + ], + "0600",[["0600","0A03120F06FF","",""],"","",""], + "0600",[["0600","0A03120F06FF","",""],"","",""], + [ + ["0600",["0A0F06FF","","0A0F06FF"],"",""], + ["0600",["0A0F06FF","","0A0F06FF"],"",""],"","" + ], + [ + ["0600",["0A0F06FF","","0A0F06FF"],"",""], + ["0600",["0A0F06FF","","0A0F06FF"],"",""],"","" + ], + "0600","0600","0600","0600","0600","0600", + "2608","2608", + "", + "070E0B0E0003", + "070E0B0E0C00","070E0B0E1800", + "0B0E070E","070E0B0E", + "2808","2808", + "", + "070E0B0E0003", + "070E0B0E0C00","070E0B0E1800", + [ + [ + ["0601","","0601"],["0601","","0601"], + "0603","0603", + ["0601","","0601"],["0601","","0601"], + ["0601","0601","0601"], + ["0601","0601",""] + ], + [ + ["","",["0602","","",""],""],["","",["0602","","",""],""], + ["","",["0602","","",""],""],["","",["0602","","",""],""], + "", + ["","","","","","","",""], + ["","","","","","","",""], + ["","","","","","","",""] + ] + ], + "0B0E070E", + "06000A000003","070E0B0E0003", + ["0B0E090E",""], + "070E0B0E0003", + ["0B0E090E",""], + ["0B0E090E",""], + "0B0E0600","0B0E0602", + [ + ["1002","","",""],"", + ["0B060706","0A020602","",""],"" + ],"", + ["","","","","070E0C000003","070E0C000003","070E0C000003","070E0C000003"], + "0B0E070E0003", + [ + ["0B0E070E0180","","",""],"", + ["0B0E070E0180","0A020602","",""],["0B0E070E0180","0A020602","",""] + ], + [ + ["0B0E070E0180","","",""],"", + ["0B0E070E0180","0A020602","",""],["0B0E070E0180","","",""] + ], + "0B0E0600","0B0E0602", + "06000A000003","070E0B0E0003", + [ + ["0A0406480C00","0B30133007300C00","0A0F137007700C000151","0A0F066C0C000151"], + ["0A0406480C00","0B30133007300C00","0A0F137007700C000151","0A0F066C0C000151"], + ["0A0406440C00","0A04120406480C00","0A0F120406440C000151",""], + ["0A0406490C00","0A04120406480C00","0A0F120406460C000151",""] + ], + ["06030A02",""], + [["0A0A06220C00","","",""],"0A04120406220C000108","",""], + ["",[["06020A0A0C00","","",""],"06020A040C000108","",""]], + ["0B70137007700C000140","0B70137007700C000140","",""], + [ + [ + "", + ["06060003","","060B0003"], + "", + ["0601","","0601"], + ["0601","","0601"], + ["0601","","0601"], + ["0606","0606","0606",""],["0606","","",""] + ], + [ + "", + ["","","","","","","",""], + "","","","", + "070E","070E" + ] + ], + "030E","030E","030E","030E","030E","030E","030E","030E", + ["",["0A040648","0B3013300730","",""],"",["0A040648","0B3013300730","",""]], + [["0A0A06A9","","",""],"0B70137006480108","",""], + [["0A0A06A9","","",""],["0A040648","0B3013300648",["0B70137006480108","",""],""],"",""], + [["0A0A06A9","","",""],"0B70137006480100","",""], + [["0A0A06A9","","",""],"0B70137007700140","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [ + ["","06490A040100","",""], + ["","06490A040100",["0A040649","","",""],["0A040649","","",""]] + ], + ["",[["0B0C06A0","","",""],["0B0C0640","0B0C0730","",""],"",""]], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730",["0B70137007700148","","0B70137007700140"],["0A061206066C0148","","0A061206066C0140"]],"",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730",["0B70137007700148","","0B70137007700140"],["0A061206066C0148","","0A061206066C0140"]],"",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [ + [["0A0A06A9","","",""],["0A040648","0B3013300648","0B70137006480108",""],"",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730","0B70137006480108",""],"",""] + ], + [["0A0A06A9","","",""],["0A040648","0B3013300648",["0B70137006480108","","0B7013700648"],""],"",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [ + "", + ["0A040648","0A040730","0B3807700141",""], + ["0A040649","0B300738",["0A0406480140","0B7007380140","0B700770014A"],"0A06065A0170"], + "0B3807700142" + ], + [[["06090A0A","","",""],["07700B700108","",""],"",""],""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730",["0B70137007700148","","0B70137007700140"],["0A061206066C0148","","0A061206066C0140"]],"",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730",["0B70137007700148","","0B70137007700140"],["0A061206066C0148","","0A061206066C0140"]],"",""], + [["","","",["0A040648","0A040730","",""]],"0000"], + [["0A0A06A9","","",""],"0B70137006480108","",""], + [["0A0A06A9","","",""],["0B70137006480108","",""],"",""], + [["0A0A06A9","","",""],"0B7013700648","",""], + [["0A0A06A9","","",""],"0B70137007700140","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + ["",[["0A0A060A","","",""],["0B040648","0B040648","",""],"",""]], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730",["0B70137007700148","",""],["0A061206066C0148","",""]],"",""], + [["0A0A06A9","","",""],"0B70137007700140","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730",["0B70137007700148","",""],["0A061206066C0148","",""]],"",""], + "", + /*------------------------------------------------------------------------------------------------------------------------ + Three Byte operations 0F38. + ------------------------------------------------------------------------------------------------------------------------*/ + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730","",""],"",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730","",""],"",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730","",""],"",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730","",""],"",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730","",""],"",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730","",""],"",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730","",""],"",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730","",""],"",""], + [["0A0A06A9","","",""],["0A040648","0B3013300730","",""],"",""], + [["0A0A06A9","","",""],"0B70137007700108","",""], + ["",["","0B3013300730",["0B70137007700148","",""],""],"",""], + ["",["","0B3013300730","0B70137007700140",""],"",""], + ["",["","0B300730","",""],"",""], + ["",["","0B300730","",""],"",""], + ["",["0A0406482E00","0B30133007301530","0B7013700770",""],["","","07380B70",""],""], + ["",["","","0B7013700770",""],["","","071C0B70",""],""], + ["",["","","0B7013700770",""],["","","070E0B70",""],""], + ["",["","0B300718",["0B7007380109","",""],""],["","","07380B70",""],""], + ["",["0A0407102E00","0B30133007301530",["0B70137007700148","","0B70137007700140"],""],["","","071C0B70",""],""], + ["",["0A0407102E00","0B30133007301530",["0B70137007700148","","0B70137007700140"],""],["","","07380B70",""],""], + ["",["","0B3013300730",["0B70137007700148","","0B70137007700140"],""],"",""], + ["",["0A040648","0B300730","",""],"",""], + ["",["","0B300644",["0B7006440138","",""],["0A0606440138","",""]],"",""], + ["",["","0A050646",["0B6806460108","","0B700646"],["","","0A060646"]],"",""], + ["",["","0A050648",["0B6806480138","","0B680648"],["0A0606480138","",""]],"",""], + ["",["","",["0A06065A0108","","0A06065A"],["","","0A06065A"]],"",""], + [["0A0A06A9","","",""],"0B7007700108","",""], + [["0A0A06A9","","",""],"0B7007700108","",""], + [["0A0A06A9","","",""],["0B7007700148","",""],"",""], + ["",["","","0B7007700140",""],"",""], + ["","0B7007380108",["","","07380B70",""],""], + ["","0B70071C0108",["","","071C0B70",""],""], + ["","0B70070E0108",["","","070E0B70",""],""], + ["","0B7007380108",["","","07380B70",""],""], + ["","0B70071C0108",["","","071C0B70",""],""], + ["","0B7007380108",["","","07380B70",""],""], + ["",["","",["0A0F137007700108","","0A0F13700770"],""],["","",["0A0F13700770","","0A0F137007700108"],""],""], + ["",["","",["0A0F137007700148","","0A0F137007700140"],["0A0F1206066C0148","",""]],["","",["0A0F137007700140","","0A0F137007700148"],""],""], + ["","0B70137007700140",["","",["0B7006FF","","0B7006FF0108"],""],""], + ["",["0A040648","0B3013300730","0A0F137007700140",""],["","",["0A0F0770","","0A0F07700108"],""],""], + [["",["0B7007700108","",""],"",""],["","",["","",["","","0B7006FF0108"],""],""]], + ["",["0B70137007700148","",""],"",""], + ["",["","0B3013300730",["0B7013700770014A","","0B70137007700142"],""],"",""], + ["",["","0B3013300730",["0A0412040644014A","","0A04120406480142"],""],"",""], + ["",["","073013300B30","",""],"",""], + ["",["","0B3013300730","",""],"",""], + ["","0B7007380108",["","","07380B70",""],""], + ["","0B70071C0108",["","","071C0B70",""],""], + ["","0B70070E0108",["","","070E0B70",""],""], + ["","0B7007380108",["","","07380B70",""],""], + ["","0B70071C0108",["","","071C0B70",""],""], + ["","0B7007380108",["","",["06480A04","07380B70",""],""],""], + ["",["","0A051205065A",["0B70137007700148","","0B70137007700140"],["0A061206066C0108","",""]],"",""], + ["",["0A040710","0B3013300730","0A0F137007700140",""],"",""], + ["","0B70137007700108",["","",["0B7006FF","","0B7006FF0108"],""],""], + ["",["0A0412040648","0B3013300730",["0B70137007700148","","0B70137007700140"],["0A061206066C0148","",""]],["","",["0A0F0770","","0A0F07700108"],""],""], + ["","0B70137007700108",["","","0B7006FF0100",""],""], + ["",["0A0412040648","0B3013300730",["0B70137007700148","","0B70137007700140"],["0A061206066C0148","",""]],"",""], + ["","0B70137007700108","",""], + ["",["0A0412040648","0B3013300730",["0B70137007700148","","0B70137007700140"],["0A061206066C0148","",""]],"",""], + ["","0B70137007700108","",""], + ["",["0A0412040648","0B3013300730",["0B70137007700148","","0B70137007700140"],["0A061206066C0148","",""]],"",""], + ["",["0A0412040648","0B3013300730",["0B70137007700148","","0B70137007700140"],["0A061206066C0148","",""]],"",""], + ["",["0A040648",["0A040648","0A040648","",""],"",""],"",""], + ["",["","",["0B7007700159","","0B7007700151"],["0A06066C0159","","0A06066C0151"]],"",""], + ["",["","",["0A0412040644010A","","0A04120406460102"],""],"",""], + ["",["","",["0B7007700148","","0B7007700140"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B70137007700148","","0B70137007700140"],["0A061206066C0148","",""]],"",""], + ["",["",["0B3013300730","",""],["0B70137007700148","","0B70137007700140"],["0A061206066C0148","",""]],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B70137007700148","","0B70137007700140"],["0A061206066C0148","",""]],"",""], + "","","","", + ["",["","",["0B7007700148","","0B7007700140"],""],"",""], + ["",["","",["0A04120406440108","","0A0412040646"],""],"",""], + ["",["","",["0B7007700148","","0B7007700140"],""],"",""], + ["",["","",["0A04120406440108","","0A0412040646"],""],"",""], + ["",["","","",["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["","","",["0A061206066C0159","",""]],"",""], + ["",["","","",["0A061206066C0159","","0A061206066C0151"]],"",""], + ["",["","","",["0A061206066C0159","","0A061206066C0151"]],"",""], + "", + ["",["","","",["0A061206066C0149","","0A061206066C0141"]],"",""], + "","", + ["",["","0B300644",["0B7006440128","",""],["0A0606440128","",""]],"",""], + ["",["","0B300646",["0B7006460128","","0B7006460120"],["","","0A0606460120"]],"",""], + ["",["","0A050648",["0B6806480128","","0B6806480120"],["0A0606480128","",""]],"",""], + ["",["","",["0A06065A0128","","0A06065A0120"],["","","0A06065A0120"]],"",""], + ["",["","","",["0A06120F066C0148","",""]],"",""], + ["",["","","",["0A06120F066C0148","",""]],"",""], + ["",["","","",["0A06120F066C0148","",""]],"",""], + ["",["","","",["0A06120F066C0148","",""]],"",""], + "","","","", + ["",["","",["0B70137007700148","","0B70137007700140"],["0A061206066C0148","","0A061206066C0140"]],"",""], + ["",["","",["0B70137007700158","","0B70137007700150"],["0A061206066C0158","","0A061206066C0150"]],"",""], + ["",["","",["0B70137007700108","","0B7013700770"],""],"",""], + "","","","","", + ["",["","","",["0A061206066C0148","",""]],"",""], + ["",["","","",["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["","","",["0A06120F066C0148","",""]],"",""], + ["",["","","",["0A06120F066C0148","",""]],"",""], + "","","","", + ["",["","","",["0A0F1206066C0148","",""]],"",""], + ["",["","",["0B70137007700108","","0B7013700770"],""],"",""], + ["",["","",["0B70137007700148","","0B70137007700140"],""],"",""], + ["",["","",["0B70137007700148","","0B70137007700140"],""],"",""], + ["",["","0B300640",["0B7006400108","",""],""],"",""], + ["",["","0B300642",["0B7006420108","",""],""],"",""], + ["",["",["","",["0B7006000108","",""],""],"",""]], + ["",["",["","",["0B7006100108","",""],""],"",""]], + ["",["","",["0B70062F0108","","0B70063F"],""],"",""], + ["",["","",["0B70137007700108","","0B7013700770"],""],"",""], + ["",["","",["0B70137007700148","","0B70137007700140"],""],"",""], + ["",["","",["0B70137007700148","","0B70137007700140"],""],"",""], + [["","0B0C060B0180","",""],""], + [["","0B0C060B0180","",""],""], + [["","0B0C060B0180","",""],""], + ["",["","","0B70137007700140",""],"",""], + ["",["","","",["0A061206066C014A","",""]],"",""], + "", + ["",["","","",["0A061206066C0148","",""]],"",""], + ["",["","","",["0A061206066C0148","",""]],"",""], + ["",["","",["0B7007700108","","0B700770"],""],"",""], + ["",["","",["0B7007700108","","0B700770"],""],"",""], + ["",["","",["07700B700108","","07700B70"],""],"",""], + ["",["","",["07700B700108","","07700B70"],""],"",""], + "", + ["",["","",["0B70137007700108","","0B7013700770"],""],"",""], + "","", + ["",["",["0B30073013300124","","0B30064813300124"],["0B700770012C","","0B7007380124"],["0A06066C012C","","0A06065A0124"]],"",""], + ["",["",["0A04073012040104","","0B30073013300104"],["0B380770010C","","0B7007700104"],""],"",""], + ["",["",["0B30073013300134","","0B30064813300134"],["0B700770013C","","0B7007380134"],["0A06066C013C","","0A06065A0104"]],"",""], + ["",["",["0A04073012040104","","0B30073013300104"],["0B380770010C","","0B7007700104"],""],"",""], + "","", + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["",["0A0412040714","","0A0412040718"],["0A0412040644010A","","0A04120406460102"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["",["0A0412040714","","0A0412040718"],["0A0412040644010A","","0A04120406460102"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["",["0A0412040714","","0A0412040718"],["0A0412040644010A","","0A04120406460102"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["",["0A0412040714","","0A0412040718"],["0A0412040644010A","","0A04120406460102"],""],"",""], + ["",["","",["07700B70010C","","07380B700104"],["066C0A06012C","","065A0A060124"]],"",""], + ["",["","",["07700B38010C","","07700B700104"],""],"",""], + ["",["","",["07700B70013C","","07380B700134"],["066C0A06013C","","065A0A060134"]],"",""], + ["",["","",["07700B38010C","","07700B700104"],""],"",""], + ["",["","","",["0A061206066C011A","",""]],"",""], + "", + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["",["0A0412040644","","0A0412040646"],["0A0412040644010A","","0A04120406460102"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["",["0A0412040644","","0A0412040646"],["0A0412040644010A","","0A04120406460102"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["",["0A0412040644","","0A0412040646"],["0A0412040644010A","","0A04120406460102"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["",["0A0412040644","","0A0412040646"],["0A0412040644010A","","0A04120406460102"],""],"",""], + "","","","", + ["",["","","0B70137007700140",["0A061206066C0118","",""]],"",""], + ["",["","","0B70137007700140",["0A061206066C0148","",""]],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["",["0A0412040644","","0A0412040646"],["0A0412040644010A","","0A04120406460102"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["",["0A0412040644","","0A0412040646"],["0A0412040644010A","","0A04120406460102"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["",["0A0412040644","","0A0412040646"],["0A0412040644010A","","0A04120406460102"],""],"",""], + ["",["",["0B3013300730","","0B3013300730"],["0B7013700770014A","","0B70137007700142"],["0A061206066C015A","","0A061206066C0152"]],"",""], + ["",["",["0A0412040644","","0A0412040646"],["0A0412040644010A","","0A04120406460102"],""],"",""], + "","","","", + ["",["","",["0B7007700148","","0B7007700140"],""],"",""], + "", + [ + [ + ["",["","","",["060C013C","","060A0134"]],"",""], + ["",["","",["060C013C","","060A0134"],["060C013C","",""]],"",""], + ["",["","",["060C013C","","070A0134"],["060C013C","",""]],"",""], + "", + ["",["","","",["060C013C","","060A0134"]],"",""], + ["",["","",["060C013C","","060A0134"],["060C013C","",""]],"",""], + ["",["","",["060C013C","","060A0134"],["060C013C","",""]],"",""], + "" + ],"" + ], + [ + [ + "", + ["",["","",["060C010C","","060C0104"],""],"",""], + ["",["","",["060C010C","","060C0104"],""],"",""], + "","", + ["",["","",["060C010C","","060C0104"],""],"",""], + ["",["","",["060C010C","","060C0104"],""],"",""], + "" + ],"" + ], + [["0A040648","","",""],["","",["0A06066C0159","","0A06066C0151"],["0A06066C0109","",""]],"",""], + [["0A040648","","",""],["","","",["0A06066C0109","",""]],"",""], + [["0A040648","","",""],["","",["0A06066C0159","","0A06066C0151"],["0A06066C0109","",""]],"",""], + [["0A0406482E00","","",""],["","",["0A04120406440109","","0A04120406460101"],["0A06066C0109","",""]],"",""], + [["0A040648","","",""],["","",["0A06066C0159","","0A06066C0151"],["0A06066C015A","",""]],"",""], + [["0A040648","","",""],["","",["0A04120406440109","","0A04120406460101"],["0A06066C0148","",""]],"",""], + "","", + [[["","","",["0A06060C0120","","0A06060C0128"]],["","","",["060C0A060128","","060C0A060120"]],"",""],""], + [[["","","",["0A06060C0130","","0A06060C0138"]],["","","",["060C0A060138","","060C0A060130"]],"",""],""], + "","", + [[["","","",["0A06060C0120","","0A06060C0128"]],["","","",["060C0A060128","","060C0A060120"]],"",""],""], + [[["","","",["0A06060C0130","","0A06060C0138"]],["","","",["060C0A060138","","060C0A060130"]],"",""],""], + "","","","","", + ["",["0A040648","0A040648","",""],"",""], + ["",["0A040648","0A0412040648","",""],"",""], + ["",["0A040648","0A0412040648","",""],"",""], + ["",["0A040648","0A0412040648","",""],"",""], + ["",["0A040648","0A0412040648","",""],"",""], + "","","","","","","","","","","","","","","","", + [ + ["0B0E070E0180","","",""], + ["0B0E070E0180","","",""],"", + ["0B0C06000180","","",""] + ], + [ + ["070E0B0E0180","","",""], + ["070E0B0E0180","","",""],"", + ["0B0C070E0180","","",""] + ], + ["",["","0B0C130C070C","",""],"",""], + [ + "", + ["",["","130C070C","",""],"",""], + ["",["","130C070C","",""],"",""], + ["",["","130C070C","",""],"",""], + "","","","" + ],"", + [ + ["","0B0C070C130C","",""],"", + ["","0B0C130C070C","",""], + ["","0B0C130C070C","",""] + ], + [ + "", + ["0B0C070C","","",""], + ["0B0C070C","","",""], + ["","0B0C130C070C1B0C","",""] + ], + [ + ["","0B0C130C070C","",""], + ["","0B0C130C070C","",""], + ["","0B0C130C070C","",""], + ["","0B0C130C070C","",""] + ], + "","","","","","","","", + /*------------------------------------------------------------------------------------------------------------------------ + Three Byte operations 0F3A. + ------------------------------------------------------------------------------------------------------------------------*/ + ["",["","0A05065A0C00","0B7007700C000140",""],"",""], + ["",["","0A05065A0C00","0B7007700C000140",""],"",""], + ["",["",["0B30133007300C00","",""],"",""],"",""], + ["",["","",["0B70137007700C000148","","0B70137007700C000140"],["0A061206066C0C000108","",""]],"",""], + ["",["","0B3007300C00",["0B7007700C000148","",""],""],"",""], + ["",["","0B3007300C00","0B7007700C000140",""],"",""], + ["",["","0A051205065A0C00","",""],"",""], + ["",["","","",["0A06066C0C000108","",""]],"",""], + ["",["0A0406480C00","0B3007300C00",["0B7007700C000149","",""],""],"",""], + ["",["0A0406480C00","0B3007300C00","0B7007700C000141",""],"",""], + ["",["0A0406440C00","0A04120406440C00",["0A04120406440C000109","",""],""],"",""], + ["",["0A0406460C00","0A04120406460C00","0A04120406460C000101",""],"",""], + ["",["0A0406480C00","0B30133007300C00","",""],"",""], + ["",["0A0406480C00","0B30133007300C00","",""],"",""], + ["",["0A0406480C00","0B30133007300C00","",""],"",""], + [["0A0A06A90C00","","",""],"0B70137007700C000108","",""], + "","","","", + [["","06000A040C000108","",""],["","070C0A040C000108","",""]], + [["","06020A040C000108","",""],["","070C0A040C000108","",""]], + ["",["06240A040C000108","","06360A040C00"],"",""], + ["","070C0A040C000108","",""], + ["",["","0A05120506480C00",["0B70137006480C000108","","0B70137006480C00"],""],"",""], + ["",["","06480A050C00",["06480B700C000108","","06480B700C00"],""],"",""], + ["",["","",["0A061206065A0C000108","","0A061206065A0C00"],""],"",""], + ["",["","",["065A0A060C000108","","065A0A060C00"],""],"",""], + "", + ["",["","07180B300C00",["07380B700C000109","",""],""],"",""], + ["",["","",["0A0F137007700C000148","","0A0F137007700C000140"],["0A0F1206066C0C000148","",""]],"",""], + ["",["","",["0A0F137007700C000148","","0A0F137007700C000140"],["0A0F1206066C0C000148","",""]],"",""], + ["","0A04120406200C000108","",""], + ["",["0A04120406440C000108","",""],"",""], + ["",["",["0A04120406240C00","","0A04120406360C00"],["0A04120406240C000108","","0A04120406360C00"],""],"",""], + ["",["","",["0B70137007700C000148","","0B70137007700C000140"],""],"",""], + "", + ["",["","",["0B70137007700C000148","","0B70137007700C000140"],""],"",""], + ["",["","",["0B7007700C000149","","0B7007700C000141"],["0A06066C0C000159","","0A06066C0C000151"]],"",""], + ["",["","",["0A04120406440C000109","","0A04120406460C000101"],""],"",""], + "","","","","","","","", + ["",["",["0A0F06FF0C00","","0A0F06FF0C00"],"",""],"",""], + ["",["",["0A0F06FF0C00","","0A0F06FF0C00"],"",""],"",""], + ["",["",["0A0F06FF0C00","","0A0F06FF0C00"],"",""],"",""], + ["",["",["0A0F06FF0C00","","0A0F06FF0C00"],"",""],"",""], + "","","","", + ["",["","0A05120506480C00",["0B70137006480C000108","","0B70137006480C00"],""],"",""], + ["",["","06480A050C00",["06480B700C000108","","06480B700C00"],""],"",""], + ["",["","",["0A061206065A0C000108","","0A061206065A0C00"],""],"",""], + ["",["","",["065A0A060C000108","","065A0A060C00"],""],"",""], + "","", + ["",["","0A0F063F0C00",["0A0F137007700C000108","","0A0F137007700C00"],""],"",""], + ["",["","",["0A0F137007700C000108","","0A0F137007700C00"],""],"",""], + ["",["0A0406480C00","0B30133007300C00","",""],"",""], + ["",["0A0406480C00","0A04120406480C00","",""],"",""], + ["",["0A0406480C00","0B30133007300C00",["0B70137007700C000108","",""],""],"",""], + ["",["","",["0B70137007700C000148","","0B70137007700C000140"],""],"",""], + ["",["0A0406480C00","0A04120406480C00","",""],"",""], + "", + ["",["","0A051205065A0C00","",""],"",""], + "", + ["",["",["0B301330073015300E00","","0B301330153007300E00"],"",""],"",""], + ["",["",["0B301330073015300E00","","0B301330153007300E00"],"",""],"",""], + ["",["","0B30133007301530","",""],"",""], + ["",["","0B30133007301530","",""],"",""], + ["",["","0A051205065A1505","",""],"",""], + "","","", + ["",["","",["0B70137007700C000149","","0B70137007700C000141"],""],"",""], + ["",["","",["0A04120406440C000109","","0A04120406460C000101"],""],"",""], + ["",["","","",["0A06066C0C000159","","0A06066C0C000151"]],"",""], + "", + ["",["","",["0B70137007700C000149","","0B70137007700C000141"],""],"",""], + ["",["","",["0A04120406440C000109","","0A04120406460C000101"],""],"",""], + ["",["","",["0B7007700C000149","","0B7007700C000141"],""],"",""], + ["",["","",["0A04120406440C000109","","0A04120406460C000101"],""],"",""], + "","","","", + ["",["",["0B30133007301530","","0B30133015300730"],"",""],"",""], + ["",["",["0B30133007301530","","0B30133015300730"],"",""],"",""], + ["",["",["0B30133007301530","","0B30133015300730"],"",""],"",""], + ["",["",["0B30133007301530","","0B30133015300730"],"",""],"",""], + ["",["0A0406480C00","0A0406480C00","",""],"",""], + ["",["0A0406480C00","0A0406480C00","",""],"",""], + ["",["0A0406480C00","0A0406480C00","",""],"",""], + ["",["0A0406480C00","0A0406480C00","",""],"",""], + "","", + ["",["","",["0A0F07700C000148","","0A0F07700C000140"],""],"",""], + ["",["","",["0A0F06440C000108","","0A0F06460C00"],""],"",""], + ["",["",["0B30133007301530","","0B30133015300730"],"",""],"",""], + ["",["",["0B30133007301530","","0B30133015300730"],"",""],"",""], + ["",["",["0A04120406441530","","0A04120415300644"],"",""],"",""], + ["",["",["0A04120406461530","","0A04120415300646"],"",""],"",""], + ["",["",["0B30133007301530","","0B30133015300730"],"",""],"",""], + ["",["",["0B30133007301530","","0B30133015300730"],"",""],"",""], + ["",["",["0A04120406441530","","0A04120415300644"],"",""],"",""], + ["",["",["0A04120406461530","","0A04120415300646"],"",""],"",""], + "","","","","","","","", + ["",["",["0B30133007301530","","0B30133015300730"],"",""],"",""], + ["",["",["0B30133007301530","","0B30133015300730"],"",""],"",""], + ["",["",["0A04120406441530","","0A04120415300644"],"",""],"",""], + ["",["",["0A04120406461530","","0A04120415300646"],"",""],"",""], + ["",["",["0B30133007301530","","0B30133015300730"],"",""],"",""], + ["",["",["0B30133007301530","","0B30133015300730"],"",""],"",""], + ["",["",["0A04120406441530","","0A04120415300644"],"",""],"",""], + ["",["",["0A04120406461530","","0A04120415300646"],"",""],"",""], + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","", + [["","","","0A06066C0C000141"],["","","",["0A06066C0C000159","",""]],"",["","","","0A06066C0C000151"]], + [["","","","0A06066C0C000141"],["","","",["0A06066C0C000159","",""]],"",""], + "0A0406480C00","","","", + "","","","","","","","","","","","","","","", + ["",["0A0406480C00","0A0406480C00","",""],"",""], + "","","","","","", + ["","","",["","","","0A06066C0C000151"]], + "","","","","","","","","", + ["","","",["","0B0C070C0C00","",""]], + "","","","","","","","","","","","","","","", + /*------------------------------------------------------------------------------------------------------------------------ + AMD XOP 8. + ------------------------------------------------------------------------------------------------------------------------*/ + "","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","", + "0A04120406481404","0A04120406481404","0A04120406481404","","","","","","", + "0A04120406481404","0A04120406481404","","","","","","0A04120406481404","0A04120406481404","0A04120406481404", + "","","","","","","0A04120406481404","0A04120406481404", + "","",["0B30133007301530","","0B30133015300730"],["0A04120406481404","","0A04120414040648"],"","","0A04120406481404", + "","","","","","","","","","","","","","","", + "0A04120406481404","","","","","","","","","","0A0406480C00","0A0406480C00","0A0406480C00","0A0406480C00", + "","","","","","","","", + "0A04120406480C00","0A04120406480C00","0A04120406480C00","0A04120406480C00", + "","","","","","","","","","","","","","","","","","","","","","","","","","","","", + "0A04120406480C00","0A04120406480C00","0A04120406480C00","0A04120406480C00", + "","","","","","","","","","","","","","","","", + /*------------------------------------------------------------------------------------------------------------------------ + AMD XOP 9. + ------------------------------------------------------------------------------------------------------------------------*/ + "", + ["","130C070C","130C070C","130C070C","130C070C","130C070C","130C070C","130C070C"], + ["","130C070C","","","","","130C070C",""], + "","","","","","","","","","","","","","","", + ["",["070C","070C","","","","","",""]], + "","","","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","","","", + "0B300730","0B300730","0B300730","0B300730", + "","","","","","","","","","","","", + ["0A0406481204","","0A0412040648"],["0A0406481204","","0A0412040648"],["0A0406481204","","0A0412040648"],["0A0406481204","","0A0412040648"], + ["0A0406481204","","0A0412040648"],["0A0406481204","","0A0412040648"],["0A0406481204","","0A0412040648"],["0A0406481204","","0A0412040648"], + ["0A0406481204","","0A0412040648"],["0A0406481204","","0A0412040648"],["0A0406481204","","0A0412040648"],["0A0406481204","","0A0412040648"], + "","","","","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","","","", + "0A040648","0A040648","0A040648","","","0A040648","0A040648","","","","0A040648","","","","","", + "0A040648","0A040648","0A040648","","","0A040648","0A040648","","","","0A040648","","","","","", + "0A040648","0A040648","0A040648","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","", + /*------------------------------------------------------------------------------------------------------------------------ + AMD XOP A. + ------------------------------------------------------------------------------------------------------------------------*/ + "","","","","","","","","","","","","","","","", + "0B0C070C0C020180","",["130C06240C020180","130C06240C020180","","","","","",""], + "","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + /*------------------------------------------------------------------------------------------------------------------------- + L1OM Vector. + -------------------------------------------------------------------------------------------------------------------------*/ + "","","","","1206","","","","","","","","","","","", + [["0A0606610120","0A0606610120","",""],""],"", + [["0A0606610120","0A0606610120","",""],""], + [["0A0606610120","0A0606610120","",""],""], + [["0A0606610100","0A0606610100","",""],""],"", + [["0A0606610100","0A0606610100","",""],""], + [["0A0606610100","0A0606610100","",""],""], + ["0A06066C0124",""],["066C0124",""],"",["066C0124",""], + ["066C0A060104",""],["066C0104",""],"",["066C0104",""], + ["0A0F120606610150","0A0F120606610150","",""],"0A0F120606610140","0A0F120606610140","", + ["0A0F120606610150","0A0F120606610150","",""],"0A0F120606610140","0A0F120606610140","", + "","","","","","","","", + "0A0F120606610140","","","","","","","","","","","","","","","", + ["0A06120606610150","0A06120606610150","",""],"0A06120606610140","","0A06120F06610140","","0A06120F06610140","0A06120606610150","0A06120606610140", + ["0A06120606610150","0A06120606610150","",""],"","","","","","","", + ["0A06120606610150","0A06120606610150","",""],"0A06120606610140","","0A06120F06610140","","0A06120F06610140","","", + ["0A06120606610150","0A06120606610150","",""],"0A06120606610140","","0A06120F06610140","","0A06120F06610140","","", + ["0A06120606610150","0A06120606610150","",""],"0A06120606610140", + ["0A06120606610150","0A06120606610150","",""],"", + ["0A06120606610150","0A06120606610150","",""],"", + "0A06120606610150","0A06120606610140", + ["0A06120606610150","0A06120606610150","",""],"", + ["0A06120606610150","0A06120606610150","",""],"", + ["0A06120606610150","0A06120606610150","",""],"","","", + ["0A06120606610150","0A06120606610150","",""],"", + ["0A06120606610150","0A06120606610150","",""],"", + ["0A06120606610150","0A06120606610150","",""],"","","", + ["0A06120606610150","0A06120606610150","",""],"", + ["0A06120606610150","0A06120606610150","",""],"", + ["0A06120606610150","0A06120606610150","",""],"", + ["0A06120606610150","0A06120606610150","",""],"", + ["0A06120606610150","0A06120606610150","",""],"0A06120606610140","0A06120606610140","0A06120606610140","","","0A06120606610150","0A06120606610140", + ["0A06120606610150","0A06120606610150","",""],"0A06120606610140","0A06120606610140","", + ["0A06120606610150","0A06120606610150","",""],"0A06120606610140","0A06120606610140","", + ["","0A0606610152","",""],["0A0606610153","0A0606610152","",""],["0A0606610153","0A0606610152","",""],"", + ["","0A0606610158","",""],["0A0606610141","0A0606610148","",""],["0A0606610141","0A0606610148","",""],"", + "0A0606610153","","0A0606610150","0A0606610152","","0A0606610150","0A0606610150","", + "0A06120606610140","0A06120606610140","0A06120606610140","", + ["0A06120606610140","0A06120606610140","",""],["0A06120606610140","0A06120606610140","",""], + ["0A06120606610140","0A06120606610140","",""],["0A06120606610140","0A06120606610140","",""], + "0A06120606610140","0A06120606610140","","","","","","", + "0A0606610140","0A0606610150","0A0606610150","","0A0606610150","","","", + "0A06120606610140","","","","","","","", + "0A0606610150","","0A06120606610150","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "0A0606610C010150","0A0606610C000C00","0A06120606610C010140","0A0606610C010140","","","","", + "","","","","","","","", + /*------------------------------------------------------------------------------------------------------------------------- + L1OM Mask, Mem, and bit opcodes. + -------------------------------------------------------------------------------------------------------------------------*/ + ["","0B0E070E"],["","0B0E070E"],["","0B0E070E"],["","0B0E070E"], + ["","0B0E070E"],["","0B0E070E"],["","0B0E070E"],["","0B0E070E"], + ["","0B0E070E"],["","0B0E070E"],["","0B0E070E"],["","0B0E070E"], + ["","0B0E070E"],["","0B0E070E"],["","0B0E070E"],["","0B0E070E"], + ["","0B0E070E"],["","0B0E070E"],["","0B0E070E"],["","0B0E070E"], + ["","0B0E070E"],["","0B0E070E"],["","0B0E070E"],["","0B0E070E"], + ["","0B0E070E0C010C000C00"],["","0B0E070E0C010C000C00"],["","0B0E070E0C010C000C00"],["","0B0E070E0C010C000C00"], + ["","0B0E070E0C010C000C00"],["","0B0E070E0C010C000C00"],["","0B0E070E0C010C000C00"],["","0B0E070E0C010C000C00"], + ["","0B0E070E"],["","0B0E070E"],["","0B0E070E"],["","0B0E070E"], + ["","0B0E070E"],["","0B0E070E"],["","0B0E070E"],["","0B0E070E"], + "","","","", + "06FF0A0F", + [["0601","0601","0604","0604","","","",""],""], + [["0601","0601","","","","","",""],""], + [["0601","0601","","","","","",""],""], + "06FF0A0F","06FF0B06","07060A0F","06FF0B06", + "06FF0A0F","06FF0A0F","06FF0A0F","06FF0A0F", + "06FF0A0F","06FF0A0F","06FF0A0F","06FF0A0F", + "","06FF0A0F", + ["",["0B07","0B07","","","","","",""]], + ["",["0B07","0B07","","","","","",""]] +]; + +/*------------------------------------------------------------------------------------------------------------------------- +3DNow uses the byte after the operands as the select instruction code, so in the Mnemonics there is no instruction name, but +in the Operands array the operation code 0F0F which is two byte opcode 0x10F (using the disassemblers opcode value system) +automatically takes operands ModR/M, and MM register. Once the operands are decoded the byte value after the operands is +the selected instruction code for 3DNow. The byte value is an 0 to 255 value so the listing is 0 to 255. +--------------------------------------------------------------------------------------------------------------------------- +At the very end of the function ^DecodeInstruction()^ an undefined instruction name with the operands MM, and MM/MMWORD is +compared for if the operation code is 0x10F then the next byte is read and is used as the selected 3DNow instruction. +-------------------------------------------------------------------------------------------------------------------------*/ + +const M3DNow = [ + "","","","","","","","","","","","","PI2FW","PI2FD","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","PFNACC","","","","PFPNACC","", + "PFCMPGE","","","","PFMIN","","PFRCP","PFRSQRT","","","FPSUB","","","","FPADD","", + "PFCMPGT","","","","PFMAX","","PFRCPIT1","PFRSQIT1","","","PFSUBR","","","","PFACC","", + "PFCMPEQ","","","","PFMUL","","PFRCPIT2","PMULHRW","","","","PSWAPD","","","","PAVGUSB", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","", + "","","","","","","","","","","","","","","","" +]; + +/*------------------------------------------------------------------------------------------------------------------------- +Virtual machine synthetic operation codes is under two byte operation code 0FC7 which is opcode 0x1C7 using the disassemblers +opcode value system. The operation code 0x1C7 is an group opcode containing 3 operation codes, but only one of the codes +is used in the ModR/M grouped opcode for synthetic virtual machine operation codes. The ModR/M byte has to be in register mode +using register code 001 for the virtual machine synthetic operation codes. The effective address has to be set 000 which uses +the full ModR/M byte as an static opcode encoding under the group opcode 001. This makes the operation code 0F C7 C8. +The resulting instruction name in the Mnemonics map is "SSS", and takes no Operands in the Operands array. The two bytes after +0F C7 C8 are used as the select synthetic operation code. Only the first 4 values of both bytes have an select operation code, +so an 5x5 map is used to keep the mapping small. +--------------------------------------------------------------------------------------------------------------------------- +When the operation code is 0F C7 and takes the ModR/M byte value C8 the operation code is "SSS" with no operands. +At the very end of the function ^DecodeInstruction()^ an instruction that is "SSS" is compared if it is instruction "SSS". +If it is operation "SSS" then the two bytes are then read as two codes which are used as the selected operation code in the 5x5 map. +--------------------------------------------------------------------------------------------------------------------------- +link to the patent https://www.google.com/patents/US7552426 +-------------------------------------------------------------------------------------------------------------------------*/ + +const MSynthetic = [ + "VMGETINFO","VMSETINFO","VMDXDSBL","VMDXENBL","", + "VMCPUID","VMHLT","VMSPLAF","","", + "VMPUSHFD","VMPOPFD","VMCLI","VMSTI","VMIRETD", + "VMSGDT","VMSIDT","VMSLDT","VMSTR","", + "VMSDTE","","","","" +]; + +/*------------------------------------------------------------------------------------------------------------------------- +Condition codes Note that the SSE, and MVEX versions are limited to the first 7 condition codes. +XOP condition codes map differently. +-------------------------------------------------------------------------------------------------------------------------*/ + +const ConditionCodes = [ + "EQ","LT","LE","UNORD","NEQ","NLT","NLE","ORD", //SSE/L1OM/MVEX. + "EQ_UQ","NGE","NGT","FALSE","NEQ_OQ","GE","GT","TRUE", //VEX/EVEX. + "EQ_OS","LT_OQ","LE_OQ","UNORD_S","NEQ_US","NLT_UQ","NLE_UQ","ORD_S", //VEX/EVEX. + "EQ_US","NGE_UQ","NGT_UQ","FALSE_OS","NEQ_OS","GE_OQ","GT_OQ","TRUE_US", //VEX/EVEX. + "LT","LE","GT","GE","EQ","NEQ","FALSE","TRUE" //XOP. +]; + +/*------------------------------------------------------------------------------------------------------------------------- +The Decoded operation name. +-------------------------------------------------------------------------------------------------------------------------*/ + +var Instruction = ""; + +/*------------------------------------------------------------------------------------------------------------------------- +The Instructions operands. +-------------------------------------------------------------------------------------------------------------------------*/ + +var InsOperands = ""; + +/*------------------------------------------------------------------------------------------------------------------------- +This object stores a single decoded Operand, and gives it an number in OperandNum (Operand Number) for the order they are +read in the operand string. It also stores all of the Settings for the operand. +--------------------------------------------------------------------------------------------------------------------------- +Each Operand is sorted into an decoder array in the order they are decoded by the CPU in series. +--------------------------------------------------------------------------------------------------------------------------- +Used by function ^DecodeOperandString()^ Which sets the operands active and gives them there settings along the X86Decoder array. +--------------------------------------------------------------------------------------------------------------------------- +The following X86 patent link might help http://www.google.com/patents/US7640417 +-------------------------------------------------------------------------------------------------------------------------*/ + +var Operand = function(){ + return( + { + Type:0, //The operand type some operands have different formats like DecodeImmediate() which has a type input. + BySizeAttrubute:false, //Effects how size is used depends on which operand type for which operand across the decoder array. + /*------------------------------------------------------------------------------------------------------------------------- + How Size is used depends on the operand it is along the decoder array for which function it uses to + decode Like DecodeRegValue(), or Decode_ModRM_SIB_Address(), and lastly DecodeImmediate() as they all take the BySize. + -------------------------------------------------------------------------------------------------------------------------*/ + Size:0x00, //The Setting. + OperandNum:0, //The operand number basically the order each operand is read in the operand string. + Active:false, //This is set by the set function not all operand are used across the decoder array. + //set the operands attributes then set it active in the decoder array. + set:function(T, BySize, Settings, OperandNumber) + { + this.Type = T; + this.BySizeAttrubute = BySize; + this.Size = Settings; + this.OpNum = OperandNumber; //Give the operand the number it was read in the operand string. + this.Active = true; //set the operand active so it's settings are decoded by the ^DecodeOperands()^ function. + }, + //Deactivates the operand after they are decoded by the ^DecodeOperands()^ function. + Deactivate:function(){ this.Active = false; } + } + ); +}; + +/*------------------------------------------------------------------------------------------------------------------------- +The Decoder array is the order each operand is decoded after the select opcode if used. They are set during the decoding of +the operand string using the function ^DecodeOperandString()^ which also gives each operand an number for the order they are +read in. Then they are decoded by the Function ^DecodeOperands()^ which decodes each set operand across the X86Decoder in order. +The number the operands are set during the decoding of the operand string is the order they will be positioned after decoding. +As the operands are decoded they are also Deactivated so the next instruction can be decoded using different operands. +--------------------------------------------------------------------------------------------------------------------------- +The following X86 patent link might help http://www.google.com/patents/US7640417 +--------------------------------------------------------------------------------------------------------------------------- +Used by functions ^DecodeOperandString()^, and ^DecodeOperands()^, after function ^DecodeOpcode()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var X86Decoder = [ + /*------------------------------------------------------------------------------------------------------------------------- + First operand that is always decoded is "Reg Opcode" if used. + Uses the function ^DecodeRegValue()^ the input RValue is the three first bits of the opcode. + -------------------------------------------------------------------------------------------------------------------------*/ + new Operand(), //Reg Opcode if used. + /*------------------------------------------------------------------------------------------------------------------------- + The Second operand that is decoded in series is the ModR/M address if used. + Reads a byte using function ^Decode_ModRM_SIB_Value()^ gives it to the function ^Decode_ModRM_SIB_Address()^ which only + reads the Mode, and Base register for the address, and then decodes the SIB byte if base register is "100" binary in value. + does not use the Register value in the ModR/M because the register can also be used as a group opcode used by the + function ^DecodeOpcode()^, or uses a different register in single size with a different address pointer. + -------------------------------------------------------------------------------------------------------------------------*/ + new Operand(), //ModR/M address if used. + /*------------------------------------------------------------------------------------------------------------------------- + The third operand that is decoded if used is for the ModR/M reg bits. + Uses the already decoded byte from ^Decode_ModRM_SIB_Value()^ gives the three bit reg value to the function ^DecodeRegValue()^. + The ModR/M address, and reg are usually used together, but can also change direction in the encoding string. + -------------------------------------------------------------------------------------------------------------------------*/ + new Operand(), //ModR/M reg bits if used. + /*------------------------------------------------------------------------------------------------------------------------- + The fourth operand that is decoded in sequence is the first Immediate input if used. + The function ^DecodeImmediate()^ starts reading bytes as a number for input to instruction. + -------------------------------------------------------------------------------------------------------------------------*/ + new Operand(), //First Immediate if used. + /*------------------------------------------------------------------------------------------------------------------------- + The fifth operand that is decoded in sequence is the second Immediate input if used. + The function ^DecodeImmediate()^ starts reading bytes as a number for input to instruction. + -------------------------------------------------------------------------------------------------------------------------*/ + new Operand(), //Second Immediate if used (Note that the instruction "Enter" uses two immediate inputs). + /*------------------------------------------------------------------------------------------------------------------------- + The sixth operand that is decoded in sequence is the third Immediate input if used. + The function ^DecodeImmediate()^ starts reading bytes as a number for input to instruction. + -------------------------------------------------------------------------------------------------------------------------*/ + new Operand(), //Third Immediate if used (Note that the Larrabee vector instructions can use three immediate inputs). + /*------------------------------------------------------------------------------------------------------------------------- + Vector adjustment codes allow the selection of the vector register value that is stored into variable + VectorRegister that applies to the selected SSE instruction that is read after that uses it. + The adjusted vector value is given to the function ^DecodeRegValue()^. + -------------------------------------------------------------------------------------------------------------------------*/ + new Operand(), //Vector register if used. And if vector adjustments are applied to the SSE instruction. + /*------------------------------------------------------------------------------------------------------------------------- + Immediate Register encoding if used. + During the decoding of the immediate operands the ^DecodeImmediate()^ function stores the read IMM into an variable called + IMMValue. The upper four bits of IMMValue is given to the input RValue to the function ^DecodeRegValue()^. + -------------------------------------------------------------------------------------------------------------------------*/ + new Operand(), //Immediate Register encoding if used. + /*------------------------------------------------------------------------------------------------------------------------- + It does not matter which order the explicit operands decode as they do not require reading another byte after the opcode. + Explicit operands are selected internally in the cpu for instruction codes that only use one register, or pointer, or number input. + -------------------------------------------------------------------------------------------------------------------------*/ + new Operand(), //Explicit Operand one. + new Operand(), //Explicit Operand two. + new Operand(), //Explicit Operand three. + new Operand() //Explicit Operand four. +]; + +/*------------------------------------------------------------------------------------------------------------------------- +SizeAttrSelect controls the General arithmetic extended sizes "8/16/32/64", and SIMD Vector register extended sizes "128/256/512/1024". +--------------------------------------------------------------------------------------------------------------------------- +General arithmetic sizes "8/16/32/64" change by operand override which makes all operands go 16 bit. +The width bit which is in the REX prefix makes operands go all 64 bits the changes depend on the instructions adjustable size. +The value system goes as follows: 0=8, or 16, then 1=Default32, then 2=Max64. Smallest to largest in order. +Changeable from prefixes. Code 66 hex is operand override, 48 hex is the REX.W setting. By default operands are 32 bit +in size in both 32 bit mode, and 64 bit modes so by default the Size attribute setting is 1 in value so it lines up with 32. +In the case of fewer size settings the size system aligns in order to the correct prefix settings. +--------------------------------------------------------------------------------------------------------------------------- +If in 16 bit mode the 16 bit operand size trades places with 32, so when the operand override is used it goes from 16 to 32. +Also in 32 bit mode any size that is 64 changes to 32, but except for operands that do not use the BySize system. +--------------------------------------------------------------------------------------------------------------------------- +During Vector instructions size settings "128/256/512" use the SizeAttrSelect as the vector length setting as a 0 to 3 value from +smallest to largest Note 1024 is Reserved the same system used for General arithmetic sizes "8/16/32/64" that go in order. +If an operand is used that is 32/64 in size the Width bit allows to move between Sizes 32/64 separately. +--------------------------------------------------------------------------------------------------------------------------- +Used by the function ^GetOperandSize()^ which uses a fast base 2 logarithm system. +The function ^DecodeOpcode()^ also uses the current size setting for operation names that change name by size, Or +In vector instructions the select instruction by size is used to Add additional instructions between the width bit (W=0), and (W=1). +-------------------------------------------------------------------------------------------------------------------------*/ + +var SizeAttrSelect = 1; + +/*------------------------------------------------------------------------------------------------------------------------- +The Width bit is used in combination with SizeAttrSelect only with Vector instructions. +-------------------------------------------------------------------------------------------------------------------------*/ + +var WidthBit = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +Pointer size plus 16 bit's used by FAR JUMP and other instructions. +For example FAR JUMP is size attributes 16/32/64 normally 32 is the default size, but it is 32+16=48 FWORD PTR. +In 16 bit CPU mode the FAR jump defaults to 16 bits, but because it is a far jump it is 16+16=32 which is DWORD PTR. +Set by the function ^DecodeOperandString()^ for if the ModR/M operand type is far pointer address. +--------------------------------------------------------------------------------------------------------------------------- +Used by the function ^Decode_ModRM_SIB_Address()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var FarPointer = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +AddressOverride is hex opcode 67 then when used with any operation that uses the ModR/M in address mode the ram address +goes down one in bit mode. Switches 64 address mode to 32 bit address mode, and in 32 bit mode the address switches to +16 bit address mode which uses a completely different ModR/M format. When in 16 bit mode the address switches to 32 bit. +Set true when Opcode 67 is read by ^DecodePrefixAdjustments()^ which effects the next opcode that is not a prefix opcode +then is set false after instruction decodes. +--------------------------------------------------------------------------------------------------------------------------- +Used by the function ^Decode_ModRM_SIB_Address()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var AddressOverride = false; + +/*------------------------------------------------------------------------------------------------------------------------- +Extended Register value changes by the "R bit" in the REX prefix, or by the "Double R bit" settings in EVEX Extension +which makes the Register operand reach to a max value of 32 registers along the register array. +Normally the Register selection in ModR/M, is limited to three bits in binary 000 = 0 to 111 = 7. +RegExtend stores the two binary bits that are added onto the three bit register selection. +--------------------------------------------------------------------------------------------------------------------------- +When RegExtend is 00,000 the added lower three bits is 00,000 = 0 to 00,111 = 7. +When RegExtend is 01,000 the added lower three bits is 01,000 = 8 to 01,111 = 15. +When RegExtend is 10,000 the added lower three bits is 10,000 = 16 to 10,111 = 23. +When RegExtend is 11,000 the added lower three bits is 11,000 = 24 to 10,111 = 31. +--------------------------------------------------------------------------------------------------------------------------- +The Register expansion bits make the binary number from a 3 bit number to a 5 bit number by combining the EVEX.R'R bits. +The REX opcode, and EVEX opcode 62 hex are decoded with function ^DecodePrefixAdjustments()^ which contain R bit settings. +--------------------------------------------------------------------------------------------------------------------------- +Used by function ^DecodeRegValue()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var RegExtend = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +The base register is used in ModR/M address mode, and Register mode and can be extended to 8 using the "B bit" setting +from the REX prefix, or VEX Extension, and EVEX Extension, however in EVEX the tow bits "X, and B" are used together to +make the base register reach 32 in register value if the ModR/M is in Register mode. +--------------------------------------------------------------------------------------------------------------------------- +The highest the Base Register can be extended is from a 3 bit number to a 5 bit number. +--------------------------------------------------------------------------------------------------------------------------- +Used by the function ^Decode_ModRM_SIB_Address()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var BaseExtend = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +The index register is used in ModR/M memory address mode if the base register is "100" bin in the ModR/M which sets SIB mode. +The Index register can be extended to 8 using the "X bit" setting when the Index register is used. +The X bit setting is used in the REX prefix settings, and also the VEX Extension, and EVEX Extension. +--------------------------------------------------------------------------------------------------------------------------- +The highest the Index Register can be extended is from a 3 bit number to a 4 bit number. +--------------------------------------------------------------------------------------------------------------------------- +Used by the function ^Decode_ModRM_SIB_Address()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var IndexExtend = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +SegOverride is the bracket that is added onto the start of the decoded address it is designed this way so that if a segment +Override Prefix is used it is stored with the segment. +--------------------------------------------------------------------------------------------------------------------------- +used by function ^Decode_ModRM_SIB_Address()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var SegOverride = "["; + +/*------------------------------------------------------------------------------------------------------------------------- +This may seem confusing, but the 8 bit high low registers are used all in "low order" when any REX prefix is used. +Set RexActive true when the REX Prefix is used, for the High, and low Register separation. +--------------------------------------------------------------------------------------------------------------------------- +Used by function ^DecodeRegValue()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var RexActive = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +The SIMD value is set according to SIMD MODE by prefixes (none, 66, F2, F3), or by the value of VEX.pp, and EVEX.pp. +Changes the selected instruction in ^DecodeOpcode()^ only for SSE vector opcodes that have 4 possible instructions in +one instruction for the 4 modes otherwise 66 is Operand override, and F2 is REPNE, and F3 is REP prefix adjustments. +By reusing some of the already used Prefix adjustments more opcodes did not have to be sacrificed. +--------------------------------------------------------------------------------------------------------------------------- +SIMD is set 00 in binary by default, SIMD is set 01 in binary when opcode 66 is read by ^DecodePrefixAdjustments()^, +SIMD is set 10 in binary when opcode F2 is read by ^DecodePrefixAdjustments()^, and SIMD is set 11 in binary when F3 is read +by ^DecodePrefixAdjustments()^. +--------------------------------------------------------------------------------------------------------------------------- +The VEX, and EVEX adjustment codes contain SIMD mode adjustment bits in which each code that is used to change the mode go +in the same order as SIMD. This allows SIMD to be set directly by the VEX.pp, and EVEX.pp bit value. +--------------------------------------------------------------------------------------------------------------------------- +VEX.pp = 00b (None), 01b (66h), 10b (F2h), 11b (F3h) +EVEX.pp = 00b (None), 01b (66h), 10b (F2h), 11b (F3h) +--------------------------------------------------------------------------------------------------------------------------- +Used by the function ^DecodeOpcode()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var SIMD = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +Vect is set true during the decoding of an instruction code. If the instruction is an Vector instruction 4 in length for +the four modes then Vect is set true. When Vect is set true the Function ^Decode_ModRM_SIB_Address()^ Will decode the +ModR/M as a Vector address. +--------------------------------------------------------------------------------------------------------------------------- +Set By function ^DecodeOpcode()^, and used by function ^Decode_ModRM_SIB_Address()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var Vect = false; + +/*------------------------------------------------------------------------------------------------------------------------- +In AVX512 The width bit can be ignored, or used. The width bit relates to the SIMD mode for size of the numbers in the vector. +Modes N/A, F3 are 32 bit, while 66, F2 are 64 bit. The width bit has to be set for the extend data size for +most AVX512 instructions unless the width bit is ignored. Some AVX512 vectors can also broadcast round to there extend data size +controlled by the width bit extend size and SIMD mode. +-------------------------------------------------------------------------------------------------------------------------*/ + +var IgnoresWidthbit = false; + +/*------------------------------------------------------------------------------------------------------------------------- +The VSIB setting is used for vectors that multiply the displacement by the Element size of the vectors, and use index as an vector pointer. +-------------------------------------------------------------------------------------------------------------------------*/ + +var VSIB = false; + +/*------------------------------------------------------------------------------------------------------------------------- +EVEX also has error suppression modes {ER} controlled by vector length, and if the broadcast round is active in register mode, +or {SAE} suppresses all exceptions then it can not change rounding mode by vector length. +MVEX also has error suppression modes {ER} controlled by conversion mode, and if the MVEX.E bit is set to round in register mode, +or {SAE} suppresses all exceptions then it can not change rounding mode by vector length. +L1OM vectors use {ER} as round control, and {SEA} as exponent adjustment. +-------------------------------------------------------------------------------------------------------------------------*/ + +var RoundingSetting = 0; //1 = SAE, and 2 = ER. + +/*------------------------------------------------------------------------------------------------------------------------- +The MVEX prefix can Integer convert, and Float convert, and Broadcast round using Swizzle. +The EVEX prefix can only Broadcast round using an "b" control which sets the Broadcast round option for Swizzle. +-------------------------------------------------------------------------------------------------------------------------*/ + +var Swizzle = false; //Swizzle based instruction. If false then Up, or Down conversion. +var Up = false; //Only used if Swizzle is false. If set false then it is an down conversion. +var Float = false; //If False Integer data is used. +var VectS = 0x00; //Stores the three vector settings Swizzle, Up, and Float, for faster comparison to special cases. + +/*------------------------------------------------------------------------------------------------------------------------- +The Extension is set 2 during opcode 62 hex for EVEX in which the ^DecodePrefixAdjustments()^ decodes the settings, but if +the bit that must be set 0 for EVEX is set 1 then Extension is set 3 for MVEX. +The Extension is set 1 during opcodes C4, and C5 hex in which the ^DecodePrefixAdjustments()^ decodes the settings for the VEX prefixes. +--------------------------------------------------------------------------------------------------------------------------- +An instruction that has 4 opcode combinations based on SIMD can use another 4 in length separator in the select SIMD mode +which selects the opcode based on extension used. This is used to separate codes that can be Vector adjusted, and not. +Some codes can only be used in VEX, but not EVEX, and not all EVEX can be MVEX encoded as the EVEX versions were introduced after, +also MMX instruction can not be used with vector adjustments. +--------------------------------------------------------------------------------------------------------------------------- +By default Extension is 0 for decoding instructions normally. +--------------------------------------------------------------------------------------------------------------------------- +Used by function ^DecodeOpcode()^ adds the letter "V" to the instruction name to show it uses Vector adjustments. +When the Function ^DecodeOpcode()^ completes if Vect is not true and an Extension is active the instruction is invalid. +Used By function ^DecodeOperandString()^ which allows the Vector operand to be used if existent in the operand string. +-------------------------------------------------------------------------------------------------------------------------*/ + +var Extension = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +MVEX/EVEX conversion modes. MVEX can directly set the conversion mode between float, or integer, to broadcast round using option bits. +The EVEX Extension only has the broadcast rounding control. In which some instructions support "]{1to16}" (B32), or "]{1to8}" (B64) +Based on the data size using the width bit setting. EVEX only can use the 1ToX broadcast round control. +--------------------------------------------------------------------------------------------------------------------------- +Used by function ^Decode_ModRM_SIB_Address()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var ConversionMode = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +MVEX/EVEX rounding modes. In EVEX if the ModR/M is used in register mode and Bround Is active. +The EVEX Error Suppression type is set by the RoundingSetting {ER}, and {SAE} settings for if the instruction supports it. +The MVEX version allows the use of both rounding modes. MVEX can select the rounding type using option bits if the +"MVEX.E" control is set in an register to register operation. +--------------------------------------------------------------------------------------------------------------------------- +The function ^Decode_ModRM_SIB_Address()^ sets RoundMode. +The function DecodeInstruction() adds the error Suppression to the end of the instruction. +-------------------------------------------------------------------------------------------------------------------------*/ + +var RoundMode = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +MVEX/EVEX register round modes. +--------------------------------------------------------------------------------------------------------------------------- +Some instructions use SAE which suppresses all errors, but if an instruction uses {er} the 4 others are used by vector length. +-------------------------------------------------------------------------------------------------------------------------*/ + +const RoundModes = [ + "","","","","","","","", //First 8 No rounding mode. + /*------------------------------------------------------------------------------------------------------------------------- + MVEX/EVEX round Modes {SAE} Note MVEX (1xx) must be set 4 or higher, while EVEX uses upper 4 in rounding mode by vector length. + -------------------------------------------------------------------------------------------------------------------------*/ + ", {Error}", ", {Error}", ", {Error}", ", {Error}", ", {SAE}", ", {SAE}", ", {SAE}", ", {SAE}", + /*------------------------------------------------------------------------------------------------------------------------- + L1OM/MVEX/EVEX round modes {ER}. L1OM uses the first 4, and EVEX uses the upper 4, while MVEX can use all 8. + -------------------------------------------------------------------------------------------------------------------------*/ + ", {RN}", ", {RD}", ", {RU}", ", {RZ}", ", {RN-SAE}", ", {RD-SAE}", ", {RU-SAE}", ", {RZ-SAE}", + /*------------------------------------------------------------------------------------------------------------------------- + MVEX/EVEX round modes {SAE}, {ER} Both rounding modes can not possibly be set both at the same time. + -------------------------------------------------------------------------------------------------------------------------*/ + "0B", "4B", "5B", "8B", "16B", "24B", "31B", "32B" //L1OM exponent adjustments. +]; + +/*------------------------------------------------------------------------------------------------------------------------- +L1OM/MVEX register swizzle modes. When an swizzle operation is done register to register. +Note L1OM skips swizzle type DACB thus the last swizzle type is an repeat of the DACB as the last L1OM swizzle. +-------------------------------------------------------------------------------------------------------------------------*/ + +const RegSwizzleModes = [ "", "CDAB", "BADC", "DACB", "AAAA", "BBBB", "CCCC", "DDDD", "DACB" ]; + +/*------------------------------------------------------------------------------------------------------------------------- +EVEX does not support conversion modes. Only broadcast round of 1To16, or 1To8 controlled by the data size. +--------------------------------------------------------------------------------------------------------------------------- +MVEX.sss permits the use of conversion types by value without relating to the Swizzle conversion type. +However During Up, and Down conversion MVEX does not allow Broadcast round control. +--------------------------------------------------------------------------------------------------------------------------- +L1OM.CCCCC can only be used with Up, and Down conversion data types, and L1OM.sss can only be used with broadcast round. +L1OM.SSS can only be used with swizzle conversions. +--------------------------------------------------------------------------------------------------------------------------- +The Width bit relates to the data size of broadcast round as 32 bit it is X=16, and 64 bit number are larger and are X=8 in the "(1, or 4)ToX". +The Width bit also relates to the Up conversion, and down conversion data size. +Currently in K1OM, and L1OM there are no 64 bit Up, or Down conversions. +--------------------------------------------------------------------------------------------------------------------------- +Note 66 hex is used as data size 64 in L1OM. +--------------------------------------------------------------------------------------------------------------------------- +The element to grab from the array bellow is calculated mathematically. +Note each element is an multiple of 2 in which the first element is the 32 size, and second element is 64 size. +Lastly the elements are in order to the "CCCCC" value, and "SSS" value times 2, and plus 1 if 64 data size. +-------------------------------------------------------------------------------------------------------------------------*/ + +const ConversionModes = [ + //------------------------------------------------------------------------ + "", "", //Not used. + //------------------------------------------------------------------------ + "1To16", "1To8", //Settable as L1OM.sss/MVEX.sss = 001. Settable using EVEX broadcast round. + "4To16", "4To8", //Settable as L1OM.sss/MVEX.sss = 010. Settable using EVEX broadcast round. + //------------------------------------------------------------------------ + "Float16", "Error", //Settable as "MVEX.sss = 011", and "L1OM.sss = 110 , L1OM.CCCCC = 00001". + //------------------------------------------------------------------------ + "Float16RZ", "Error", //Settable only as L1OM.CCCCC = 00010. + //------------------------------------------------------------------------ + "SRGB8", "Error", //Settable only as L1OM.CCCCC = 00011. + /*------------------------------------------------------------------------ + MVEX/L1OM Up conversion, and down conversion types. + ------------------------------------------------------------------------*/ + "UInt8", "Error", //Settable as L1OM.sss/MVEX.sss = 100, and L1OM.CCCCC = 00100. + "SInt8", "Error", //Settable as L1OM.sss/MVEX.sss = 101, and L1OM.CCCCC = 00101. + //------------------------------------------------------------------------ + "UNorm8", "Error", //Settable as L1OM.sss = 101, or L1OM.CCCCC = 00110. + "SNorm8", "Error", //Settable as L1OM.CCCCC = 00111. + //------------------------------------------------------------------------ + "UInt16", "Error", //Settable as L1OM.sss/MVEX.sss = 110, and L1OM.CCCCC = 01000 + "SInt16", "Error", //Settable as L1OM.sss/MVEX.sss = 111, and L1OM.CCCCC = 01001 + //------------------------------------------------------------------------ + "UNorm16", "Error", //Settable as L1OM.CCCCC = 01010. + "SNorm16", "Error", //Settable as L1OM.CCCCC = 01011. + "UInt8I", "Error", //Settable as L1OM.CCCCC = 01100. + "SInt8I", "Error", //Settable as L1OM.CCCCC = 01101. + "UInt16I", "Error", //Settable as L1OM.CCCCC = 01110. + "SInt16I", "Error", //Settable as L1OM.CCCCC = 01111. + /*------------------------------------------------------------------------ + L1OM Up conversion, and field conversion. + ------------------------------------------------------------------------*/ + "UNorm10A", "Error", //Settable as L1OM.CCCCC = 10000. Also Usable as Integer Field control. + "UNorm10B", "Error", //Settable as L1OM.CCCCC = 10001. Also Usable as Integer Field control. + "UNorm10C", "Error", //Settable as L1OM.CCCCC = 10010. Also Usable as Integer Field control. + "UNorm2D", "Error", //Settable as L1OM.CCCCC = 10011. Also Usable as Integer Field control. + //------------------------------------------------------------------------ + "Float11A", "Error", //Settable as L1OM.CCCCC = 10100. Also Usable as Float Field control. + "Float11B", "Error", //Settable as L1OM.CCCCC = 10101. Also Usable as Float Field control. + "Float10C", "Error", //Settable as L1OM.CCCCC = 10110. Also Usable as Float Field control. + "Error", "Error", //Settable as L1OM.CCCCC = 10111. Also Usable as Float Field control. + /*------------------------------------------------------------------------ + Unused Conversion modes. + ------------------------------------------------------------------------*/ + "Error", "Error", //Settable as L1OM.CCCCC = 11000. + "Error", "Error", //Settable as L1OM.CCCCC = 11001. + "Error", "Error", //Settable as L1OM.CCCCC = 11010. + "Error", "Error", //Settable as L1OM.CCCCC = 11011. + "Error", "Error", //Settable as L1OM.CCCCC = 11100. + "Error", "Error", //Settable as L1OM.CCCCC = 11101. + "Error", "Error", //Settable as L1OM.CCCCC = 11110. + "Error", "Error" //Settable as L1OM.CCCCC = 11111. +]; + +/*------------------------------------------------------------------------------------------------------------------------- +The VEX Extension, and MVEX/EVEX Extension have an Vector register selection built in for Vector operation codes that use the +vector register. This operand is only read in the "operand string" if an VEX, or EVEX prefix was decoded by the +function ^DecodePrefixAdjustments()^, and making Extension 1 for VEX, or 2 for EVEX instead of 0 by default. +During a VEX, or EVEX version of the SSE instruction the vector bits are a 4 bit binary value of 0 to 15, and are extended +in EVEX and MVEX to 32 by adding the EVEX.V, or MVEX.V bit to the vector register value. +--------------------------------------------------------------------------------------------------------------------------- +Used with the function ^DecodeRegValue()^ to decode the Register value. +-------------------------------------------------------------------------------------------------------------------------*/ + +var VectorRegister = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +The MVEX/EVEX Extension has an mask Register value selection for {K0-K7} mask to destination operand. +The K mask register is always displayed to the destination operand in any Vector instruction used with MVEX/EVEX settings. +--------------------------------------------------------------------------------------------------------------------------- +The {K} is added onto the first operand in OpNum before returning the decoded operands from the function ^DecodeOperands()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var MaskRegister = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +The EVEX Extension has an zero mask bit setting for {z} zeroing off the registers. +--------------------------------------------------------------------------------------------------------------------------- +The {z} is added onto the first operand in OpNum before returning the decoded operands from the function ^DecodeOperands()^. +--------------------------------------------------------------------------------------------------------------------------- +In L1OM/MVEX this is used as the {NT}/{EH} control which when used with an memory address that supports it will prevent +the data from going into the cache memory. Used as Hint control in the function ^Decode_ModRM_SIB_Address()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var HInt_ZeroMerg = false; + +/*------------------------------------------------------------------------------------------------------------------------- +Some operands use the value of the Immediate operand as an opcode, or upper 4 bits as Another register, or condition codes. +The Immediate is decoded normally, but this variable stores the integer value of the first IMM byte for the other byte +encodings if used. +--------------------------------------------------------------------------------------------------------------------------- +Used By the function ^DecodeOpcode()^ for condition codes, and by ^DecodeOperands()^ using the upper four bits as a register. +-------------------------------------------------------------------------------------------------------------------------*/ + +var IMMValue = 0; + +/*------------------------------------------------------------------------------------------------------------------------- +Prefix G1, and G2 are used with Intel HLE, and other prefix codes such as repeat the instruction Codes F2, F3 which can be +applied to any instruction unless it is an SIMD instruction which uses F2, and F3 as the SIMD Mode. +-------------------------------------------------------------------------------------------------------------------------*/ + +var PrefixG1 = "", PrefixG2 = ""; + +/*------------------------------------------------------------------------------------------------------------------------- +Intel HLE is used with basic arithmetic instructions like Add, and subtract, and shift operations. +Intel HLE instructions replace the Repeat F2, and F3, also lock F0 with XACQUIRE, and XRELEASE. +--------------------------------------------------------------------------------------------------------------------------- +This is used by function ^DecodeInstruction()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var XRelease = false, XAcquire = false; + +/*------------------------------------------------------------------------------------------------------------------------- +Intel HLE flip "G1 is used as = REP (XACQUIRE), or RENP (XRELEASE)", and "G2 is used as = LOCK" if the lock prefix was +not read first then G1, and G2 flip. Also XACQUIRE, and XRELEASE replace REP, and REPNE if the LOCK prefix is used with +REP, or REPNE if the instruction supports Intel HLE. +--------------------------------------------------------------------------------------------------------------------------- +This is used by function ^DecodeInstruction()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var HLEFlipG1G2 = false; + +/*------------------------------------------------------------------------------------------------------------------------- +Replaces segment overrides CS, and DS with HT, and HNT prefix for Branch taken and not taken used by jump instructions. +--------------------------------------------------------------------------------------------------------------------------- +This is used by functions ^Decode_ModRM_SIB_Address()^, and ^DecodeInstruction()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var HT = false; + +/*------------------------------------------------------------------------------------------------------------------------- +Instruction that support MPX replace the REPNE prefix with BND if operation is a MPX instruction. +--------------------------------------------------------------------------------------------------------------------------- +This is used by function ^DecodeInstruction()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +var BND = false; + +/*------------------------------------------------------------------------------------------------------------------------- +The Invalid Instruction variable is very important as some bit settings in vector extensions create invalid operation codes. +Also some opcodes are invalid in different cpu bit modes. +--------------------------------------------------------------------------------------------------------------------------- +Function ^DecodePrefixAdjustments()^ Set the Invalid Opcode if an instruction or prefix is compared that is invalid for CPU bit mode. +The function ^DecodeInstruction()^ returns an invalid instruction if Invalid Operation is used for CPU bit mode. +-------------------------------------------------------------------------------------------------------------------------*/ + +var InvalidOp = false; + +/*------------------------------------------------------------------------------------------------------------------------- +The Register array holds arrays in order from 0 though 7 for the GetOperandSize function Which goes by Prefix size settings, +and SIMD Vector length instructions using the adjusted variable SizeAttrSelect. +--------------------------------------------------------------------------------------------------------------------------- +Used by functions ^DecodeRegValue()^, ^Decode_ModRM_SIB_Address()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +const REG = [ + /*------------------------------------------------------------------------------------------------------------------------- + REG array Index 0 Is used only if the value returned from the GetOperandSize is 0 in value which is the 8 bit general use + Arithmetic registers names. Note that these same registers can be made 16 bit across instead of using just the first 8 bit + in size it depends on the instruction codes extension size. + --------------------------------------------------------------------------------------------------------------------------- + The function ^GetOperandSize()^ takes the size value the instruction uses for it's register selection by looking up binary + bit positions in the size value in log 2. Different instructions can be adjusted to different sizes using the operand size + override adjustment code, or width bit to adjust instructions to 64 in size introduced by AMD64, and EM64T in 64 bit computers. + --------------------------------------------------------------------------------------------------------------------------- + REG array Index 0 is the first 8 bit's of Arithmetic registers, however they can be used in both high, and low order in + which the upper 16 bit's is used as 8 bit's for H (High part), and the first 8 bits is L (LOW part) unless the rex prefix is + used then the first 8 bit's is used by all general use arithmetic registers. Because of this the array is broken into two + name listings that is used with the "RValue" number given to the function ^DecodeRegValue()^. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + /*------------------------------------------------------------------------------------------------------------------------- + 8 bit registers without any rex prefix active is the normal low byte to high byte order of the + first 4 general use registers "A, C, D, and B" using 8 bits. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //Registers 8 bit names without any rex prefix index 0 to 7. + "AL", "CL", "DL", "BL", "AH", "CH", "DH", "BH" + ], + /*------------------------------------------------------------------------------------------------------------------------- + 8 bit registers with any rex prefix active uses all 15 registers in low byte order. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //Registers 8 bit names with any rex prefix index 0 to 7. + "AL", "CL", "DL", "BL", "SPL", "BPL", "SIL", "DIL", + /*------------------------------------------------------------------------------------------------------------------------- + Registers 8 bit names Extended using the REX.R extend setting in the Rex prefix, or VEX.R bit, or EVEX.R. + What ever RegExtend is set based on prefix settings is added to the select Reg Index + -------------------------------------------------------------------------------------------------------------------------*/ + "R8B", "R9B", "R10B", "R11B", "R12B", "R13B", "R14B", "R15B" + ] + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG array Index 1 Is used only if the value returned from the GetOperandSize function is 1 in value in which bellow is the + general use Arithmetic register names 16 in size. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //Registers 16 bit names index 0 to 15. + "AX", "CX", "DX", "BX", "SP", "BP", "SI", "DI", "R8W", "R9W", "R10W", "R11W", "R12W", "R13W", "R14W", "R15W" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG array Index 2 Is used only if the value from the GetOperandSize function is 2 in value in which bellow is the + general use Arithmetic register names 32 in size. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //Registers 32 bit names index 0 to 15. + "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "R8D", "R9D", "R10D", "R11D", "R12D", "R13D", "R14D", "R15D" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG array Index 3 Is used only if the value returned from the GetOperandSize function is 3 in value in which bellow is the + general use Arithmetic register names 64 in size. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //general use Arithmetic registers 64 names index 0 to 15. + "RAX", "RCX", "RDX", "RBX", "RSP", "RBP", "RSI", "RDI", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG array Index 4 SIMD registers 128 across in size names. The SIMD registers are used by the SIMD Vector math unit. + Used only if the value from the GetOperandSize function is 4 in value. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //Register XMM names index 0 to 15. + "XMM0", "XMM1", "XMM2", "XMM3", "XMM4", "XMM5", "XMM6", "XMM7", "XMM8", "XMM9", "XMM10", "XMM11", "XMM12", "XMM13", "XMM14", "XMM15", + /*------------------------------------------------------------------------------------------------------------------------- + Register XMM names index 16 to 31. + Note different bit settings in the EVEX prefixes allow higher Extension values in the Register Extend variables. + -------------------------------------------------------------------------------------------------------------------------*/ + "XMM16", "XMM17", "XMM18", "XMM19", "XMM20", "XMM21", "XMM22", "XMM23", "XMM24", "XMM25", "XMM26", "XMM27", "XMM28", "XMM29", "XMM30", "XMM31" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG array Index 5 SIMD registers 256 across in size names. + Used only if the value from the GetOperandSize function is 5 in value. Set by vector length setting. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //Register YMM names index 0 to 15. + "YMM0", "YMM1", "YMM2", "YMM3", "YMM4", "YMM5", "YMM6", "YMM7", "YMM8", "YMM9", "YMM10", "YMM11", "YMM12", "YMM13", "YMM14", "YMM15", + /*------------------------------------------------------------------------------------------------------------------------- + Register YMM names index 16 to 31. + Note different bit settings in the EVEX prefixes allow higher Extension values in the Register Extend variables. + -------------------------------------------------------------------------------------------------------------------------*/ + "YMM16", "YMM17", "YMM18", "YMM19", "YMM20", "YMM21", "YMM22", "YMM23", "YMM24", "YMM25", "YMM26", "YMM27", "YMM28", "YMM29", "YMM30", "YMM31" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG array Index 6 SIMD registers 512 across in size names. + Used only if the value from the GetOperandSize function is 6 in value. Set by Vector length setting. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //Register ZMM names index 0 to 15. + "ZMM0", "ZMM1", "ZMM2", "ZMM3", "ZMM4", "ZMM5", "ZMM6", "ZMM7", "ZMM8", "ZMM9", "ZMM10", "ZMM11", "ZMM12", "ZMM13", "ZMM14", "ZMM15", + /*------------------------------------------------------------------------------------------------------------------------- + Register ZMM names index 16 to 31. + Note different bit settings in the EVEX prefixes allow higher Extension values in the Register Extend variables. + -------------------------------------------------------------------------------------------------------------------------*/ + "ZMM16", "ZMM17", "ZMM18", "ZMM19", "ZMM20", "ZMM21", "ZMM22", "ZMM23", "ZMM24", "ZMM25", "ZMM26", "ZMM27", "ZMM28", "ZMM29", "ZMM30", "ZMM31" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG array Index 7 SIMD registers 1024 bit. The SIMD registers have not been made this long yet. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //Register unknowable names index 0 to 15. + "?MM0", "?MM1", "?MM2", "?MM3", "?MM4", "?MM5", "?MM6", "?MM7", "?MM8", "?MM9", "?MM10", "?MM11", "?MM12", "?MM13", "?MM14", "?MM15", + /*------------------------------------------------------------------------------------------------------------------------- + Register unknowable names index 16 to 31. + Note different bit settings in the EVEX prefixes allow higher Extension values in the Register Extend variables. + -------------------------------------------------------------------------------------------------------------------------*/ + "?MM16", "?MM17", "?MM18", "?MM19", "?MM20", "?MM21", "?MM22", "?MM23", "?MM24", "?MM25", "?MM26", "?MM27", "?MM28", "?MM29", "?MM30", "?MM31" + ], + /*------------------------------------------------------------------------------------------------------------------------- + The Registers bellow do not change size they are completely separate, thus are used for special purposes. These registers + are selected by using size as a value for the index instead instead of giving size to the function ^GetOperandSize()^. + --------------------------------------------------------------------------------------------------------------------------- + REG array Index 8 Segment Registers. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //Segment Registers names index 0 to 7 + "ES", "CS", "SS", "DS", "FS", "GS", "ST(-2)", "ST(-1)" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG array Index 9 Stack, and MM registers used by the X87 Float point unit. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //ST registers Names index 0 to 7 + //note these are used with the X87 FPU, but are aliased to MM in MMX SSE. + "ST(0)", "ST(1)", "ST(2)", "ST(3)", "ST(4)", "ST(5)", "ST(6)", "ST(7)" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG index 10 Intel MM qword technology MMX vector instructions. + --------------------------------------------------------------------------------------------------------------------------- + These can not be used with Vector length adjustment used in vector extensions. The MM register are the ST registers aliased + to MM register. Instructions that use these registers use the SIMD vector unit registers (MM), these are called the old + MMX vector instructions. When Intel added the SSE instructions to the SIMD math vector unit the new 128 bit XMM registers, + are added into the SIMD unit then they ware made longer in size 256, then 512 across in length, with 1024 (?MM Reserved) + In which the vector length setting was added to control there size though vector setting adjustment codes. Instruction + that can be adjusted by vector length are separate from the MM registers, but still use the same SIMD unit. Because of this + some Vector instruction codes can not be used with vector extension setting codes. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //Register MM names index 0 to 7 + "MM0", "MM1", "MM2", "MM3", "MM4", "MM5", "MM6", "MM7" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG Array Index 11 bound registers introduced with MPX instructions. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //BND0 to BND3,and CR0 to CR3 for two byte opcodes 0x0F1A,and 0x0F1B register index 0 to 7 + "BND0", "BND1", "BND2", "BND3", "CR0", "CR1", "CR2", "CR3" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG array Index 12 control registers depending on the values they are set changes the modes of the CPU. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //control Registers index 0 to 15 + "CR0", "CR1", "CR2", "CR3", "CR4", "CR5", "CR6", "CR7", "CR8", "CR9", "CR10", "CR11", "CR12", "CR13", "CR14", "CR15" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG array Index 13 Debug mode registers. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //debug registers index 0 to 15 + "DR0", "DR1", "DR2", "DR3", "DR4", "DR5", "DR6", "DR7", "DR8", "DR9", "DR10", "DR11", "DR12", "DR13", "DR14", "DR15" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG array Index 14 test registers. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //TR registers index 0 to 7 + "TR0", "TR1", "TR2", "TR3", "TR4", "TR5", "TR6", "TR7" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG Array Index 15 SIMD vector mask registers. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + //K registers index 0 to 7, because of vector extensions it is repeated till last extension. + "K0", "K1", "K2", "K3", "K4", "K5", "K6", "K7","K0", "K1", "K2", "K3", "K4", "K5", "K6", "K7", + "K0", "K1", "K2", "K3", "K4", "K5", "K6", "K7","K0", "K1", "K2", "K3", "K4", "K5", "K6", "K7" + ], + /*------------------------------------------------------------------------------------------------------------------------- + REG Array Index 16 SIMD L1OM vector registers. + -------------------------------------------------------------------------------------------------------------------------*/ + [ + "V0", "V1", "V2", "V3", "V4", "V5", "V6", "V7", "V8", "V9", "V10", "V11", "V12", "V13", "V14", "V15", + "V16", "V17", "V18", "V19", "V20", "V21", "V22", "V23", "V24", "V25", "V26", "V27", "V28", "V29", "V30", "V31" + ] +]; + +/*------------------------------------------------------------------------------------------------------------------------- +RAM Pointer sizes are controlled by the GetOperandSize function which uses the Size Setting attributes for +the select pointer in the PTR array alignment. The REG array above uses the same alignment to the returned +size attribute except address pointers have far address pointers which are 16 bits plus there (8, or 16)/32/64 size attribute. +--------------------------------------------------------------------------------------------------------------------------- +Far pointers add 16 bits to the default pointer sizes. +16 bits become 16+16=32 DWORD, 32 bits becomes 32+16=48 FWORD, and 64+16=80 TBYTE. +The function GetOperandSize goes 0=8 bit, 1=16 bit, 2=32 bit, 3=64 bit, 4=128, 5=256, 6=512, 7=1024. +--------------------------------------------------------------------------------------------------------------------------- +The pointers are stored in doubles this is so every second position is each size setting. +So the Returned size attribute has to be in multiples of 2 each size multiplied by 2 looks like this. +(0*2=0)=8 bit, (1*2=2)=16 bit, (2*2=4)=32 bit, (3*2=6)=64 bit, (4*2=8)=128, (5*2=10)=256, (6*2=12)=512. +This is the same as moving by 2 this is why each pointer is in groups of two before the next line. +When the 16 bit shift is used for far pointers only plus one is added for the 16 bit shifted name of the pointer. +--------------------------------------------------------------------------------------------------------------------------- +Used by the function ^Decode_ModRM_SIB_Address()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +const PTR = [ + /*------------------------------------------------------------------------------------------------------------------------- + Pointer array index 0 when GetOperandSize returns size 0 then times 2 for 8 bit pointer. + In plus 16 bit shift array index 0 is added by 1 making 0+1=1 no pointer name is used. + The blank pointer is used for instructions like LEA which loads the effective address. + -------------------------------------------------------------------------------------------------------------------------*/ + "BYTE PTR ","", + /*------------------------------------------------------------------------------------------------------------------------- + Pointer array index 2 when GetOperandSize returns size 1 then times 2 for 16 bit pointer alignment. + In plus 16 bit shift index 2 is added by 1 making 2+1=3 The 32 bit pointer name is used (mathematically 16+16=32). + -------------------------------------------------------------------------------------------------------------------------*/ + "WORD PTR ","DWORD PTR ", + /*------------------------------------------------------------------------------------------------------------------------- + Pointer array index 4 when GetOperandSize returns size 2 then multiply by 2 for index 4 for the 32 bit pointer. + In plus 16 bit shift index 4 is added by 1 making 4+1=5 the 48 bit Far pointer name is used (mathematically 32+16=48). + -------------------------------------------------------------------------------------------------------------------------*/ + "DWORD PTR ","FWORD PTR ", + /*------------------------------------------------------------------------------------------------------------------------- + Pointer array index 6 when GetOperandSize returns size 3 then multiply by 2 gives index 6 for the 64 bit pointer. + The Non shifted 64 bit pointer has two types the 64 bit vector "MM", and regular "QWORD" the same as the REG array. + In plus 16 bit shift index 6 is added by 1 making 6+1=7 the 80 bit TBYTE pointer name is used (mathematically 64+16=80). + -------------------------------------------------------------------------------------------------------------------------*/ + "QWORD PTR ","TBYTE PTR ", + /*------------------------------------------------------------------------------------------------------------------------- + Pointer array index 8 when GetOperandSize returns size 4 then multiply by 2 gives index 8 for the 128 bit Vector pointer. + In far pointer shift the MMX vector pointer is used. + MM is designed to be used when the by size system is false using index 9 for Pointer, and index 10 for Reg. + -------------------------------------------------------------------------------------------------------------------------*/ + "XMMWORD PTR ","MMWORD PTR ", + /*------------------------------------------------------------------------------------------------------------------------- + Pointer array index 10 when GetOperandSize returns size 5 then multiply by 2 gives index 10 for the 256 bit SIMD pointer. + In far pointer shift the OWORD pointer is used with the bounds instructions it is also designed to be used when the by size is set false same as MM. + -------------------------------------------------------------------------------------------------------------------------*/ + "YMMWORD PTR ","OWORD PTR ", + /*------------------------------------------------------------------------------------------------------------------------- + Pointer array index 12 when GetOperandSize returns size 6 then multiply by 2 gives index 12 for the 512 bit pointer. + In plus 16 bit shift index 12 is added by 1 making 12+1=13 there is no 528 bit pointer name (mathematically 5126+16=528). + -------------------------------------------------------------------------------------------------------------------------*/ + "ZMMWORD PTR ","ERROR PTR ", + /*------------------------------------------------------------------------------------------------------------------------- + Pointer array index 14 when GetOperandSize returns size 7 then multiply by 2 gives index 12 for the 1024 bit pointer. + In plus 16 bit shift index 14 is added by 1 making 12+1=13 there is no 1 bit pointer name (mathematically 5126+16=528). + -------------------------------------------------------------------------------------------------------------------------*/ + "?MMWORD PTR ","ERROR PTR "]; + +/*------------------------------------------------------------------------------------------------------------------------- +SIB byte scale Note the Scale bits value is the selected index of the array bellow only used under +a Memory address that uses the SIB Address mode which uses another byte for the address selection. +--------------------------------------------------------------------------------------------------------------------------- +used by the ^Decode_ModRM_SIB_Address function()^. +-------------------------------------------------------------------------------------------------------------------------*/ + +const scale = [ + "", //when scale bits are 0 in value no scale multiple is used + "*2", //when scale bits are 1 in value a scale multiple of times two is used + "*4", //when scale bits are 2 in value a scale multiple of times four is used + "*8" //when scale bits are 3 in value a scale multiple of times eight is used + ]; + +/*------------------------------------------------------------------------------------------------------------------------- +This function changes the Mnemonics array, for older instruction codes used by specific X86 cores that are under the same instruction codes. +--------------------------------------------------------------------------------------------------------------------------- +Input "type" can be any number 0 to 6. If the input is 0 it sets the mnemonics back to normal. +If input "type" is set 1 it will adjust the few conflicting mask instructions to the K1OM instruction names used by the knights corner processor. +If input "type" is set 2 it will adjust the mnemonic array to decode Larrabee instructions. +If input "type" is set 3 it will adjust the mnemonic array to decode Cyrix instructions which are now deprecated from the architecture. +If input "type" is set 4 it will adjust the mnemonic array to decode Geode instructions which are now deprecated from the architecture. +If input "type" is set 5 it will adjust the mnemonic array to decode Centaur instructions which are now deprecated from the architecture. +If input "type" is set 6 it will adjust the mnemonic array to decode instruction for the X86/486 CPU which conflict with the vector unit instructions with UMOV. +-------------------------------------------------------------------------------------------------------------------------*/ + +export function CompatibilityMode( type ) +{ + //Reset the changeable sections of the Mnemonics array, and operand encoding array. + + Mnemonics[0x062] = ["BOUND","BOUND",""]; + Mnemonics[0x110] = [["MOVUPS","MOVUPD","MOVSS","MOVSD"],["MOVUPS","MOVUPD","MOVSS","MOVSD"]]; + Mnemonics[0x111] = [["MOVUPS","MOVUPD","MOVSS","MOVSD"],["MOVUPS","MOVUPD","MOVSS","MOVSD"]]; + Mnemonics[0x112] = [["MOVLPS","MOVLPD","MOVSLDUP","MOVDDUP"],["MOVHLPS","???","MOVSLDUP","MOVDDUP"]]; + Mnemonics[0x113] = [["MOVLPS","MOVLPD","???","???"],"???"]; + Mnemonics[0x138] = ""; Mnemonics[0x139] = "???"; Mnemonics[0x13A] = ""; Mnemonics[0x13B] = "???"; Mnemonics[0x13C] = "???"; Mnemonics[0x13D] = "???"; Mnemonics[0x13F] = "???"; + Mnemonics[0x141] = [["CMOVNO",["KANDW","","KANDQ"],"",""],["CMOVNO",["KANDB","","KANDD"],"",""],"",""]; + Mnemonics[0x142] = [["CMOVB",["KANDNW","","KANDNQ"],"",""],["CMOVB",["KANDNB","","KANDND"],"",""],"",""]; + Mnemonics[0x144] = [["CMOVE",["KNOTW","","KNOTQ"],"",""],["CMOVE",["KNOTB","","KNOTD"],"",""],"",""]; + Mnemonics[0x145] = [["CMOVNE",["KORW","","KORQ"],"",""],["CMOVNE",["KORB","","KORD"],"",""],"",""]; + Mnemonics[0x146] = [["CMOVBE",["KXNORW","","KXNORQ"],"",""],["CMOVBE",["KXNORB","","KXNORD"],"",""],"",""]; + Mnemonics[0x147] = [["CMOVA",["KXORW","","KXORQ"],"",""],["CMOVA",["KXORB","","KXORD"],"",""],"",""]; + Mnemonics[0x150] = ["???",[["MOVMSKPS","MOVMSKPS","",""],["MOVMSKPD","MOVMSKPD","",""],"???","???"]]; + Mnemonics[0x151] = ["SQRTPS","SQRTPD","SQRTSS","SQRTSD"]; + Mnemonics[0x152] = [["RSQRTPS","RSQRTPS","",""],"???",["RSQRTSS","RSQRTSS","",""],"???"]; + Mnemonics[0x154] = ["ANDPS","ANDPD","???","???"]; + Mnemonics[0x155] = ["ANDNPS","ANDNPD","???","???"]; + Mnemonics[0x158] = [["ADDPS","ADDPS","ADDPS","ADDPS"],["ADDPD","ADDPD","ADDPD","ADDPD"],"ADDSS","ADDSD"]; + Mnemonics[0x159] = [["MULPS","MULPS","MULPS","MULPS"],["MULPD","MULPD","MULPD","MULPD"],"MULSS","MULSD"]; + Mnemonics[0x15A] = [["CVTPS2PD","CVTPS2PD","CVTPS2PD","CVTPS2PD"],["CVTPD2PS","CVTPD2PS","CVTPD2PS","CVTPD2PS"],"CVTSS2SD","CVTSD2SS"]; + Mnemonics[0x15B] = [[["CVTDQ2PS","","CVTQQ2PS"],"CVTPS2DQ",""],"???","CVTTPS2DQ","???"]; + Mnemonics[0x15C] = [["SUBPS","SUBPS","SUBPS","SUBPS"],["SUBPD","SUBPD","SUBPD","SUBPD"],"SUBSS","SUBSD"]; + Mnemonics[0x15D] = ["MINPS","MINPD","MINSS","MINSD"]; + Mnemonics[0x15E] = ["DIVPS","DIVPD","DIVSS","DIVSD"]; + Mnemonics[0x178] = [["VMREAD","",["CVTTPS2UDQ","","CVTTPD2UDQ"],""],["EXTRQ","",["CVTTPS2UQQ","","CVTTPD2UQQ"],""],["???","","CVTTSS2USI",""],["INSERTQ","","CVTTSD2USI",""]]; + Mnemonics[0x179] = [["VMWRITE","",["CVTPS2UDQ","","CVTPD2UDQ"],""],["EXTRQ","",["CVTPS2UQQ","","CVTPD2UQQ"],""],["???","","CVTSS2USI",""],["INSERTQ","","CVTSD2USI",""]]; + Mnemonics[0x17A] = ["???",["","",["CVTTPS2QQ","","CVTTPD2QQ"],""],["","",["CVTUDQ2PD","","CVTUQQ2PD"],"CVTUDQ2PD"],["","",["CVTUDQ2PS","","CVTUQQ2PS"],""]]; + Mnemonics[0x17B] = ["???",["","",["CVTPS2QQ","","CVTPD2QQ"],""],["","","CVTUSI2SS",""],["","","CVTUSI2SD",""]]; + Mnemonics[0x17C] = ["???",["HADDPD","HADDPD","",""],"???",["HADDPS","HADDPS","",""]]; + Mnemonics[0x17D] = ["???",["HSUBPD","HSUBPD","",""],"???",["HSUBPS","HSUBPS","",""]]; + Mnemonics[0x17E] = [["MOVD","","",""],["MOVD","","MOVQ"],["MOVQ","MOVQ",["???","","MOVQ"],""],"???"], + Mnemonics[0x190] = [["SETO",["KMOVW","","KMOVQ"],"",""],["SETO",["KMOVB","","KMOVD"],"",""],"",""]; + Mnemonics[0x192] = [["SETB",["KMOVW","","???"],"",""],["SETB",["KMOVB","","???"],"",""],"",["SETB",["KMOVD","","KMOVQ"],"",""]]; + Mnemonics[0x193] = [["SETAE",["KMOVW","","???"],"",""],["SETAE",["KMOVB","","???"],"",""],"",["SETAE",["KMOVD","","KMOVQ"],"",""]]; + Mnemonics[0x198] = [["SETS",["KORTESTW","","KORTESTQ"],"",""],["SETS",["KORTESTB","","KORTESTD"],"",""],"",""]; + Mnemonics[0x1A6] = "XBTS"; + Mnemonics[0x1A7] = "IBTS"; + + Operands[0x110] = [["0B700770","0B700770","0A040603","0A040609"],["0B700770","0B700770","0A0412040604","0A0412040604"]]; + Operands[0x111] = [["07700B70","07700B70","06030A04","06090A04"],["07700B70","07700B70","060412040A04","060412040A04"]]; + Operands[0x112] = [["0A0412040606","0A0412040606","0B700770","0B700768"],["0A0412040604","","0B700770","0B700770"]]; + Operands[0x113] = [["06060A04","06060A04","",""],""]; + Operands[0x141] = [["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],"",""]; + Operands[0x142] = [["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],"",""]; + Operands[0x144] = [["0B0E070E0180",["0A0F06FF","","0A0F06FF"],"",""],["0B0E070E0180",["0A0F06FF","","0A0F06FF"],"",""],"",""]; + Operands[0x145] = [["0A02070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],["0A02070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],"",""]; + Operands[0x146] = [["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],"",""]; + Operands[0x147] = [["0B0E070E0180",["0A0F120F06FF","","0A0F120F06FF"],"",""],["0B0E070E0180",["0A0F120F06FF","",""],"",""],"",""]; + Operands[0x150] = ["",[["0B0C0648","0B0C0730","",""],["0B0C0648","0B0C0730","",""],"",""]]; + Operands[0x151] = ["0B7007700112","0B7007700112","0A04120406430102","0A04120406490102"]; + Operands[0x152] = [["0A040648","0A040648","",""],"",["0A040643","0A0412040643","",""],""]; + Operands[0x154] = ["0B70137007700110","0B70137007700110","",""]; + Operands[0x155] = ["0B70137007700110","0B70137007700110","",""]; + Operands[0x158] = [["0A040648","0B3013300730","0B70137007700112","0A061206066C0172"],["0A040648","0B3013300730","0B70137007700112","0A061206066C0112"],"0A04120406430102","0A04120406460102"]; + Operands[0x159] = [["0A040648","0B3013300730","0B70137007700112","0A061206066C0172"],["0A040648","0B3013300730","0B70137007700112","0A061206066C0112"],"0A04120406430102","0A04120406460102"]; + Operands[0x15A] = [["0A040648","0B300718","0B7007380111","0A06065A0111"],["0A040648","0B180730","0B3807700112","0A05066C0112"],"0A04120406430101","0A04120406460102"]; + Operands[0x15B] = [[["0B7007700112","","0B380770011A"],"0B700770011A","",""],"","0B7007700111",""]; + Operands[0x15C] = [["0A060648","0B3013300730","0B70137007700112","0A061206066C0172"],["0A060648","0B3013300730","0B70137007700112","0A061206066C0112"],"0A04120406430102","0A04120406460102"]; + Operands[0x15D] = ["0B70137007700111","0B70137007700111","0A04120406430101","0A04120406460101"]; + Operands[0x15E] = ["0B70137007700112","0B70137007700112","0A04120406430102","0A04120406460102"]; + Operands[0x178] = [["07080B080180","",["0B7007700111","","0B3807700119"],""],["064F0C000C00","",["0B7007380119","","0B7007700111"],""],["","","0B0C06440109",""],["0A04064F0C000C00","","0B0C06460109",""]]; + Operands[0x179] = [["0B0807080180","",["0B7007700112","","0B380770011A"],""],["0A04064F","",["0B700738011A","","0B7007700112"],""],["","","0B0C0644010A",""],["0A04064F","","0B0C0646010A",""]]; + Operands[0x17A] = ["",["","",["0B7007380119","","0B7007700111"],""],["","",["0B7007380112","","0B700770011A"],"0A06065A0112"],["","",["0B700770011A","","0B3807700112"],""]]; + Operands[0x17B] = ["",["","",["0B700738011A","","0B7007700112"],""],["","","0A041204070C010A",""],["","","0A041204070C010A",""]]; + Operands[0x17C] = ["",["0A040604","0B7013700770","",""],"",["0A040604","0B7013700770","",""]]; + Operands[0x17D] = ["",["0A040604","0B7013700770","",""],"",["0A040604","0B7013700770","",""]]; + Operands[0x17E] = [["070C0A0A","","",""],["06240A040108","","06360A040108"],["0A040646","0A040646",["","","0A0406460108"],""],""]; + Operands[0x190] = [["0600",["0A0F0612","","0A0F0636"],"",""],["0600",["0A0F0600","","0A0F0624"],"",""],"",""]; + Operands[0x192] = [["0600",["0A0F06F4","",""],"",""],["0600",["0A0F06F4","",""],"",""],"",["0600",["0A0F06F6","","0A0F06F6"],"",""]]; + Operands[0x193] = [["0600",["06F40A0F","",""],"",""],["0600",["06F40A0F","",""],"",""],"",["0600",["06F60A0F","","06F60A0F"],"",""]]; + Operands[0x198] = [["0600",["0A0F06FF","","0A0F06FF"],"",""],["0600",["0A0F06FF","","0A0F06FF"],"",""],"",""]; + Operands[0x1A6] = "0B0E070E"; + Operands[0x1A7] = "070E0B0E"; + + //Adjust the VEX mask instructions for K1OM (Knights corner) which conflict with the enhanced AVX512 versions. + + if( type === 1 ) + { + Mnemonics[0x141] = [["CMOVNO","KAND","",""],"","",""]; + Mnemonics[0x142] = [["CMOVB","KANDN","",""],"","",""]; + Mnemonics[0x144] = [["CMOVE","KNOT","",""],"","",""]; + Mnemonics[0x145] = [["CMOVNE","KOR","",""],"","",""]; + Mnemonics[0x146] = [["CMOVBE","KXNOR","",""],"","",""]; + Mnemonics[0x147] = [["CMOVA","KXOR","",""],"","",""]; + Mnemonics[0x190] = [["SETO","KMOV","",""],"","",""]; + Mnemonics[0x192] = [["SETB","KMOV","",""],"","",""]; + Mnemonics[0x193] = [["SETAE","KMOV","",""],"","",""]; + Mnemonics[0x198] = [["SETS","KORTEST","",""],"","",""]; + Operands[0x141] = [["0B0E070E0180","0A0F06FF","",""],"","",""]; + Operands[0x142] = [["0B0E070E0180","0A0F06FF","",""],"","",""]; + Operands[0x144] = [["0B0E070E0180","0A0F06FF","",""],"","",""]; + Operands[0x145] = [["0A02070E0180","0A0F06FF","",""],"","",""]; + Operands[0x146] = [["0B0E070E0180","0A0F06FF","",""],"","",""]; + Operands[0x147] = [["0B0E070E0180","0A0F06FF","",""],"","",""]; + Operands[0x190] = [["0600","0A0F06FF","",""],"","",""]; + Operands[0x192] = [["0600","06FF0B06","",""],"","",""]; + Operands[0x193] = [["0600","07060A0F","",""],"","",""]; + Operands[0x198] = [["0600","0A0F06FF","",""],"","",""]; + } + + //Disable Knights corner, and AVX512, for L1OM (Intel Larrabee). + + if( type === 2 ) + { + Mnemonics[0x62] = ""; + } + + //Adjust the Mnemonics, and Operand encoding, for the Cyrix processors. + + if( type === 3 ) + { + Mnemonics[0x138] = "SMINT"; Mnemonics[0x13A] = "BB0_RESET"; Mnemonics[0x13B] = "BB1_RESET"; Mnemonics[0x13C] = "CPU_WRITE"; Mnemonics[0x13D] = "CPU_READ"; + Mnemonics[0x150] = "PAVEB"; Mnemonics[0x151] = "PADDSIW"; Mnemonics[0x152] = "PMAGW"; + Mnemonics[0x154] = "PDISTIB"; Mnemonics[0x155] = "PSUBSIW"; + Mnemonics[0x158] = "PMVZB"; Mnemonics[0x159] = "PMULHRW"; Mnemonics[0x15A] = "PMVNZB"; + Mnemonics[0x15B] = "PMVLZB"; Mnemonics[0x15C] = "PMVGEZB"; Mnemonics[0x15D] = "PMULHRIW"; + Mnemonics[0x15E] = "PMACHRIW"; + Mnemonics[0x178] = "SVDC"; Mnemonics[0x179] = "RSDC"; Mnemonics[0x17A] = "SVLDT"; + Mnemonics[0x17B] = "RSLDT"; Mnemonics[0x17C] = "SVTS"; Mnemonics[0x17D] = "RSTS"; + Mnemonics[0x17E] = "SMINT"; + Operands[0x150] = "0A0A06A9"; Operands[0x151] = "0A0A06A9"; Mnemonics[0x152] = "0A0A06A9"; + Operands[0x154] = "0A0A06AF"; Operands[0x155] = "0A0A06A9"; + Operands[0x158] = "0A0A06AF"; Operands[0x159] = "0A0A06A9"; Mnemonics[0x15A] = "0A0A06AF"; + Operands[0x15B] = "0A0A06AF"; Operands[0x15C] = "0A0A06AF"; Mnemonics[0x15D] = "0A0A06A9"; + Operands[0x15E] = "0A0A06AF"; + Operands[0x178] = "30000A08"; Operands[0x179] = "0A083000"; Operands[0x17A] = "3000"; + Operands[0x17B] = "3000"; Operands[0x17C] = "3000"; Operands[0x17D] = "3000"; + Operands[0x17E] = ""; + } + + //Adjust the Mnemonics, and Operand encoding, for the Geode processor. + + if( type === 4 ) + { + Mnemonics[0x138] = "SMINT"; Mnemonics[0x139] = "DMINT"; Mnemonics[0x13A] = "RDM"; + } + + //Adjust the Mnemonics, for the Centaur processor. + + if( type === 5 ) + { + Mnemonics[0x13F] = "ALTINST"; + Mnemonics[0x1A6] = ["???",["MONTMUL","XSA1","XSA256","???","???","???","???","???"]]; + Mnemonics[0x1A7] = [ + "???", + [ + "XSTORE", + ["???","???","XCRYPT-ECB","???"], + ["???","???","XCRYPT-CBC","???"], + ["???","???","XCRYPT-CTR","???"], + ["???","???","XCRYPT-CFB","???"], + ["???","???","XCRYPT-OFB","???"], + "???", + "???" + ] + ]; + Operands[0x1A6] = ["",["","","","","","","",""]]; + Operands[0x1A7] = [ + "", + [ + "", + ["","","",""], + ["","","",""], + ["","","",""], + ["","","",""], + ["","","",""], + "", + "" + ] + ]; + } + + //Adjust the Mnemonics, for the X86/486 processor and older. + + if( type === 6 ) + { + Mnemonics[0x110] = "UMOV"; Mnemonics[0x111] = "UMOV"; Mnemonics[0x112] = "UMOV"; Mnemonics[0x113] = "UMOV"; + Mnemonics[0x1A6] = "CMPXCHG"; Mnemonics[0x1A7] = "CMPXCHG"; + Operands[0x110] = "06000A00"; Operands[0x111] = "070E0B0E"; Operands[0x112] = "0A000600"; Operands[0x113] = "0B0E070E"; + Operands[0x1A6] = ""; Operands[0x1A7] = ""; + } + +} + +/*------------------------------------------------------------------------------------------------------------------------- +This function loads the BinCode array using an hex string as input, and Resets the Code position along the array, but does not +reset the base address. This allows programs to be decoded in sections well maintaining the accurate 64 bit base address. +--------------------------------------------------------------------------------------------------------------------------- +The function "SetBasePosition()" sets the location that the Code is from in memory. +The function "GotoPosition()" tests if the address is within rage of the current loaded binary. +The function "GetPosition()" Gives back the current base address in it's proper format for the current BitMode. +--------------------------------------------------------------------------------------------------------------------------- +If the hex input is invalid returns false. +-------------------------------------------------------------------------------------------------------------------------*/ + +export function LoadBinCode( HexStr ) +{ + //Clear BinCode, and Reset Code Position in Bin Code array. + + BinCode = []; CodePos = 0; + + //Iterate though the hex string and covert to 0 to 255 byte values into the BinCode array. + + var len = HexStr.length; + + for( var i = 0, el = 0, Sign = 0, int32 = 0; i < len; i += 8 ) + { + //It is faster to read 8 hex digits at a time if possible. + + int32 = parseInt( HexStr.slice( i, i + 8 ), 16 ); + + //If input is invalid return false. + + if( isNaN( int32 ) ){ return ( false ); } + + //If the end of the Hex string is reached and is not 8 digits the number has to be lined up. + + ( ( len - i ) < 8 ) && ( int32 <<= ( 8 - len - i ) << 2 ); + + //The variable sing corrects the unusable sing bits during the 4 byte rotation algorithm. + + Sign = int32; + + //Remove the Sign bit value if active for when the number is changed to int32 during rotation. + + int32 ^= int32 & 0x80000000; + + //Rotate the 32 bit int so that each number is put in order in the BinCode array. Add the Sign Bit positions back though each rotation. + + int32 = ( int32 >> 24 ) | ( ( int32 << 8 ) & 0x7FFFFFFF ); + BinCode[el++] = ( ( ( Sign >> 24 ) & 0x80 ) | int32 ) & 0xFF; + int32 = ( int32 >> 24 ) | ( ( int32 << 8 ) & 0x7FFFFFFF ); + BinCode[el++] = ( ( ( Sign >> 16 ) & 0x80 ) | int32 ) & 0xFF; + int32 = ( int32 >> 24 ) | ( ( int32 << 8 ) & 0x7FFFFFFF ); + BinCode[el++] = ( ( ( Sign >> 8 ) & 0x80 ) | int32 ) & 0xFF; + int32 = ( int32 >> 24 ) | ( ( int32 << 8 ) & 0x7FFFFFFF ); + BinCode[el++] = ( ( Sign & 0x80 ) | int32 ) & 0xFF; + } + + //Remove elements past the Number of bytes in HexStr because int 32 is always 4 bytes it is possible to end in an uneven number. + + len >>= 1; + + for(; len < BinCode.length; BinCode.pop() ); + + //Return true for that the binary code loaded properly. + + return ( true ); +} + +/*------------------------------------------------------------------------------------------------------------------------- +This function moves the address by one and caries to 64 section for the Base address. The BitMode settings limit how much of +the 64 bit address is used in functions "GetPosition()", and "GotoPosition()", for the type of binary being disassemble. +This function also moves the binary code array position CodePos by one basically this function is used to progress the +disassembler as it is decoding a sequence of bytes. +-------------------------------------------------------------------------------------------------------------------------*/ + +function NextByte() +{ + //Add the current byte as hex to InstructionHex which will be displayed beside the decoded instruction. + //After an instruction decodes InstructionHex is only added beside the instruction if ShowInstructionHex is active. + var t; + if ( CodePos < BinCode.length ) //If not out of bounds. + { + //Convert current byte to String, and pad. + + ( ( t = BinCode[CodePos++].toString(16) ).length === 1) && ( t = "0" + t ); + + //Add it to the current bytes used for the decode instruction. + + InstructionHex += t; + + //Continue the Base address. + + ( ( Pos32 += 1 ) > 0xFFFFFFFF ) && ( Pos32 = 0, ( ( Pos64 += 1 ) > 0xFFFFFFFF ) && ( Pos64 = 0 ) ); + } +} + +/*------------------------------------------------------------------------------------------------------------------------- +Takes a 64/32/16 bit hex string and sets it as the address position depending on the address format it is split into an +segment, and offset address. Note that the Code Segment is used in 16 bit code. Also code segment is also used in 32 bit +if set 36, or higher. Effects instruction location in memory when decoding a program. +-------------------------------------------------------------------------------------------------------------------------*/ + +export function SetBasePosition( Address ) +{ + //Split the Segment:offset. + + var t = Address.split(":"); + + //Set the 16 bit code segment position if there is one. + + if ( typeof t[1] !== "undefined" ){ CodeSeg = parseInt( t[0].slice( t[0].length - 4 ), 16 ); Address = t[1]; } + + //Adjust the Instruction pointer 16(IP)/32(EIP)/64(RIP). Also varies based on Bit Mode. + + var Len = Address.length; + + if( Len >= 9 && BitMode == 2 ){ Pos64 = parseInt( Address.slice( Len - 16, Len - 8 ), 16 ); } + if( Len >= 5 && BitMode >= 1 && !( BitMode == 1 & CodeSeg >= 36 ) ){ Pos32 = parseInt( Address.slice( Len - 8 ), 16 ); } + else if( Len >= 1 && BitMode >= 0 ){ Pos32 = ( Pos32 & 0xFFFF0000 ) | ( parseInt( Address.slice( Len - 4 ), 16 ) ); } + + //Convert Pos32 to undignified integer. + + if ( Pos32 < 0 ) { Pos32 += 0x100000000; } +} + +/*------------------------------------------------------------------------------------------------------------------------- +Gives back the current Instruction address position. +In 16 bit an instruction location is Bound to the code segment location in memory, and the first 16 bit of the instruction pointer 0 to 65535. +In 32 bit an instruction location uses the first 32 bit's of the instruction pointer. +-------------------------------------------------------------------------------------------------------------------------*/ + +function GetPosition() +{ + //If 16 bit Seg:Offset, or if 32 bit and CodeSeg is 36, or higher. + + if( BitMode === 0 | ( BitMode === 1 & CodeSeg >= 36 ) ) + { + for ( var S16 = ( Pos32 & 0xFFFF ).toString(16); S16.length < 4; S16 = "0" + S16 ); + for ( var Seg = ( CodeSeg ).toString(16); Seg.length < 4; Seg = "0" + Seg ); + return( ( Seg + ":" + S16 ).toUpperCase() ); + } + + //32 bit, and 64 bit section. + + var S64="", S32=""; + + //If 32 bit or higher. + + if( BitMode >= 1 ) + { + for ( S32 = Pos32.toString(16); S32.length < 8; S32 = "0" + S32 ); + } + + //If 64 bit. + + if( BitMode === 2 ) + { + for ( S64 = Pos64.toString(16); S64.length < 8; S64 = "0" + S64 ); + } + + //Return the 32/64 address. + + return ( ( S64 + S32 ).toUpperCase() ); +} + +/*------------------------------------------------------------------------------------------------------------------------- +Moves the dissembler 64 bit address, and CodePos to correct address. Returns false if address location is out of bounds. +-------------------------------------------------------------------------------------------------------------------------*/ + +function GotoPosition( Address ) +{ + //Current address location. + + var LocPos32 = Pos32; + var LocPos64 = Pos64; + var LocCodeSeg = CodeSeg; + + //Split the by Segment:offset address format. + + var t = Address.split(":"); + + //Set the 16 bit code segment location if there is one. + + if ( typeof t[1] !== "undefined" ) + { + LocCodeSeg = parseInt(t[0].slice( t[0].length - 4 ), 16); + Address = t[1]; + } + + var len = Address.length; + + //If the address is 64 bit's long, and bit mode is 64 bit adjust the 64 bit location. + + if( len >= 9 && BitMode === 2 ) + { + LocPos64 = parseInt( Address.slice( len - 16, len - 8 ), 16 ); + } + + //If the address is 32 bit's long, and bit mode is 32 bit, or higher adjust the 32 bit location. + + if( len >= 5 && BitMode >= 1 & !( BitMode === 1 & CodeSeg >= 36 ) ) + { + LocPos32 = parseInt( Address.slice( len - 8 ), 16 ); + } + + //Else If the address is 16 bit's long, and bit mode is 16 bit, or higher adjust the first 16 bit's in location 32. + + else if( len >= 1 && BitMode >= 0 ) + { + LocPos32 = ( LocPos32 - LocPos32 + parseInt( Address.slice( len - 4 ), 16 ) ); + } + + //Find the difference between the current base address and the selected address location. + + var Dif32 = Pos32 - LocPos32, Dif64 = Pos64 - LocPos64; + + //Only calculate the Code Segment location if The program uses 16 bit address mode otherwise the + //code segment does not affect the address location. + + if( ( BitMode === 1 & CodeSeg >= 36 ) || BitMode === 0 ) + { + Dif32 += ( CodeSeg - LocCodeSeg ) << 4; + } + + //Before adjusting the Code Position Backup the Code Position in case that the address is out of bounds. + + t = CodePos; + + //Subtract the difference to the CodePos position. + + CodePos -= Dif64 * 4294967296 + Dif32; + + //If code position is out of bound for the loaded binary in the BinCode array, or + //is a negative index return false and reset CodePos. + + if( CodePos < 0 || CodePos > BinCode.length ) + { + CodePos = t; return ( false ); + } + + //Set the base address so that it matches the Selected address location that Code position is moved to in relative space in the BinCode Array. + + CodeSeg = LocCodeSeg; + Pos32 = LocPos32 + Pos64 = LocPos64; + + //Return true for that the address Position is moved in range correctly. + + return ( true ); +} + +/*------------------------------------------------------------------------------------------------------------------------- +Finds bit positions to the Size attribute indexes in REG array, and the Pointer Array. For the Size Attribute variations. +--------------------------------------------------------------------------------------------------------------------------- +The SizeAttribute settings is 8 digits big consisting of 1, or 0 to specify the extended size that an operand can be made. +In which an value of 01100100 is decoded as "0 = 1024, 1 = 512, 1 = 256, 0 = 128, 0 = 64, 1 = 32, 0 = 16, 0 = 8". +In which the largest bit position is 512, and is the 6th number "0 = 7, 1 = 6, 1 = 5, 0 = 4, 0 = 3, 1 = 2, 0 = 1, 0 = 0". +In which 6 is the bit position for 512 as the returned Size . Each size is in order from 0 to 7, thus the size given back +from this function Lines up With the Pinter array, and Register array indexes for the register names by size, and Pointers. +--------------------------------------------------------------------------------------------------------------------------- +The variable SizeAttrSelect is separate from this function it is adjusted by prefixes that adjust Vector size, and General purpose registers. +-------------------------------------------------------------------------------------------------------------------------*/ + +function GetOperandSize( SizeAttribute ) +{ + /*---------------------------------------------------------------------------------------------------------------------------------------- + Each S value goes in order to the vector length value in EVEX, and VEX Smallest to biggest in perfect alignment. + SizeAttrSelect is set 1 by default, unless it is set 0 to 3 by the vector length bit's in the EVEX prefix, or 0 to 1 in the VEX prefix. + In which if it is not an Vector instruction S2 acts as the mid default size attribute in 32 bit mode, and 64 bit mode for all instructions. + ----------------------------------------------------------------------------------------------------------------------------------------*/ + + var S4 = 0, S3 = 0, S2 = 0, S1 = 0, S0 = -1; //Note S0 is Vector size 1024, which is unused. + + /*---------------------------------------------------------------------------------------------------------------------------------------- + Lookup the Highest active bit in the SizeAttribute value giving the position the bit is in the number. S1 will be the biggest size attribute. + In which this size attribute is only used when the extended size is active from the Rex prefix using the W (width) bit setting. + In which sets variable SizeAttrSelect to 2 in value when the Width bit prefix setting is decoded, or if it is an Vector this is the + Max vector size 512 in which when the EVEX.L'L bit's are set 10 = 2 sets SizeAttrSelect 2, note 11 = 3 is reserved for vectors 1024 in size. + ----------------------------------------------------------------------------------------------------------------------------------------*/ + + S1 = SizeAttribute; S1 = ( ( S1 & 0xF0 ) !== 0 ? ( S1 >>= 4, 4 ) : 0 ) | ( ( S1 & 0xC ) !== 0 ? ( S1 >>= 2, 2 ) : 0 ) | ( ( S1 >>= 1 ) !== 0 ); + + /*---------------------------------------------------------------------------------------------------------------------------------------- + If there is no size attributes then set S1 to -1 then the rest are set to S1 as they should have no size setting. + ----------------------------------------------------------------------------------------------------------------------------------------*/ + + if( SizeAttribute === 0 ) { S1 = -1; } + + /*---------------------------------------------------------------------------------------------------------------------------------------- + Convert the Bit Position of S1 into it's value and remove it by subtracting it into the SizeAttribute settings. + ----------------------------------------------------------------------------------------------------------------------------------------*/ + + SizeAttribute -= ( 1 << S1 ); + + /*---------------------------------------------------------------------------------------------------------------------------------------- + Lookup the Highest Second active bit in the SizeAttribute value giving the position the bit is in the number. + In which S2 will be the default size attribute when SizeAttrSelect is 1 and has not been changed by prefixes, or If this is an vector + SizeAttrSelect is set one by the EVEX.L'L bit's 01 = 1, or VEX.L is active 1 = 1 in which the Mid vector size is used. + In which 256 is the Mid vector size some vectors are smaller some go 64/128/256 in which the mid size is 128. + ----------------------------------------------------------------------------------------------------------------------------------------*/ + + S2 = SizeAttribute; S2 = ( ( S2 & 0xF0 ) !== 0 ? ( S2 >>= 4, 4 ) : 0 ) | ( ( S2 & 0xC ) !== 0 ? ( S2 >>= 2, 2 ) : 0 ) | ( ( S2 >>= 1 ) !== 0 ); + + /*---------------------------------------------------------------------------------------------------------------------------------------- + Convert the Bit Position of S2 into it's value and remove it by subtracting it if it is not 0. + ----------------------------------------------------------------------------------------------------------------------------------------*/ + + if( S2 !== 0 ) { SizeAttribute -= ( 1 << S2 ); } + + /*---------------------------------------------------------------------------------------------------------------------------------------- + If it is 0 The highest size attribute is set as the default operand size. So S2 is aliased to S1, if there is no other Size setting attributes. + ----------------------------------------------------------------------------------------------------------------------------------------*/ + + else { S2 = S1; } + + /*---------------------------------------------------------------------------------------------------------------------------------------- + Lookup the Highest third active bit in the SizeAttribute value giving the position the bit is in the number. + The third Size is only used if the Operand override prefix is used setting SizeAttrSelect to 0, or if this is an vector the + EVEX.L'L bit's are 00 = 0 sets SizeAttrSelect 0, or VEX.L = 0 in which SizeAttrSelect is 0 using the smallest vector size. + ----------------------------------------------------------------------------------------------------------------------------------------*/ + + S3 = SizeAttribute; S3 = ( ( S3 & 0xF0 ) !== 0 ? ( S3 >>= 4, 4 ) : 0 ) | ( ( S3 & 0xC ) !== 0 ? ( S3 >>= 2, 2 ) : 0 ) | ( ( S3 >>= 1 ) !== 0 ); + + /*---------------------------------------------------------------------------------------------------------------------------------------- + Convert the Bit Position of S3 into it's value and remove it by subtracting it if it is not 0. + ----------------------------------------------------------------------------------------------------------------------------------------*/ + + if( S3 !== 0 ) { SizeAttribute -= ( 1 << S3 ); } + + /*---------------------------------------------------------------------------------------------------------------------------------------- + If it is 0 The second size attribute is set as the operand size. So S3 is aliased to S2, if there is no other Size setting attributes. + ----------------------------------------------------------------------------------------------------------------------------------------*/ + + else { S3 = S2; if( S2 !== 2 ) { S2 = S1; } }; + + //In 32/16 bit mode the operand size must never exceed 32. + + if ( BitMode <= 1 && S2 >= 3 && !Vect ) + { + if( ( S1 | S2 | S3 ) === S3 ){ S1 = 2; S3 = 2; } //If single size all adjust 32. + S2 = 2; //Default operand size 32. + } + + //In 16 bit mode The operand override is always active until used. This makes all operands 16 bit size. + //When Operand override is used it is the default 32 size. Flip S3 with S2. + + if( BitMode === 0 && !Vect ) { var t = S3; S3 = S2; S2 = t; } + + //If an Vect is active, then EVEX.W, VEX.W, or XOP.W bit acts as 32/64. + + if( ( Vect || Extension > 0 ) && ( ( S1 + S2 + S3 ) === 7 | ( S1 + S2 + S3 ) === 5 ) ) { Vect = false; return( ( [ S2, S1 ] )[ WidthBit & 1 ] ); } + + //If it is an vector, and Bround is active vector goes max size. + + if( Vect && ConversionMode === 1 ) + { + S0 = S1; S3 = S1; S2 = S1; + } + + //Note the fourth size that is -1 in the returned size attribute is Vector length 11=3 which is invalid unless Intel decides to add 1024 bit vectors. + //The only time S0 is not negative one is if vector broadcast round is active. + + return( ( [ S3, S2, S1, S0 ] )[ SizeAttrSelect ] ); + +} + +/*------------------------------------------------------------------------------------------------------------------------- +This function returns an array with three numbers. +--------------------------------------------------------------------------------------------------------------------------- +The first element is the two bits for the ModR/M byte for Register mode, Memory mode, and Displacement settings, or the SIB byte +scale as a number value 0 to 3 if it is not an ModR/M byte since they both use the same bit grouping. +The second element is the three bits for the ModR/M byte Opcode/Reg bits, or the SIB Index Register value as a number value 0 to 7. +The third element is the last three bits for the ModR/M byte the R/M bits, or the SIB Base Register value as a number value 0 to 7. +-------------------------------------------------------------------------------------------------------------------------*/ + +function Decode_ModRM_SIB_Value() +{ + //Get the current position byte value + + var v = BinCode[CodePos]; + + //The first tow binary digits of the read byte is the Mode bits of the ModR/M byte or + //The first tow binary digits of the byte is the Scale bits of the SIB byte. + + var ModeScale = (v >> 6) & 0x03; //value 0 to 3 + + //The three binary digits of the read byte after the first two digits is the OpcodeReg Value of the ModR/M byte or + //The three binary digits of the read byte after the first two digits is the Index Register value for the SIB byte. + + var OpcodeRegIndex = (v >> 3) & 0x07; //value 0 to 7 + + //The three binary digits at the end of the read byte is the R/M (Register,or Memory) Value of the ModR/M byte or + //The three binary digits at the end of the read byte is the Base Register Value of the SIB byte. + + var RMBase = v & 0x07; //value 0 to 7 + + //Put the array together containing the three indexes with the value + //Note both the ModR/M byte and SIB byte use the same bit value pattern + + var ByteValueArray = [ + ModeScale,//Index 0 is the first tow bits for the Mode, or Scale Depending on what the byte value is used for. + OpcodeRegIndex,//Index 1 is the three bits for the OpcodeReg, or Index Depending on what the byte value is used for. + RMBase //Index 2 is the three bits for the RM, or BASE bits Depending on what the byte value is used for. + ]; + + //Move the Decoders Position by one. + + NextByte(); + + //return the array containing the decoded values of the byte. + + return (ByteValueArray); + +} + +/*------------------------------------------------------------------------------------------------------------------------- +When input type is value 0 decode the immediate input regularly to it's size setting for accumulator Arithmetic, and IO. +When input type is value 1 decode the immediate input regularly, but zeros out the upper 4 bits for Register encoding. +When input type is value 2 decode the immediate as a relative address used by jumps, and function calls. +When input type is value 3 decode the immediate as a Integer Used by Displacements. +--------------------------------------------------------------------------------------------------------------------------- +The function argument SizeSetting is the size attributes of the IMM that is decoded using the GetOperandSize function. +The Imm uses two size setting, the first 4 bits are used for the Immediate actual adjustable sizes 8,16,32,64. +--------------------------------------------------------------------------------------------------------------------------- +If BySize is false the SizeSetting is used numerically as a single size selection as +0=8,1=16,2=32,3=64 by size setting value. +-------------------------------------------------------------------------------------------------------------------------*/ + +function DecodeImmediate( type, BySize, SizeSetting ) +{ + + /*------------------------------------------------------------------------------------------------------------------------- + Initialize V32, and V64 which will store the Immediate value. + JavaScript Float64 numbers can not accurately work with numbers 64 bit's long. + So numbers are split into two numbers that should never exceed an 32 bit value though calculation. + Numbers that are too big for the first 32 bit's are stored as the next 32 bit's in V64. + -------------------------------------------------------------------------------------------------------------------------*/ + + var V32 = 0, V64 = 0; + + //*Initialize the Pad Size for V32, and V64 depending On the Immediate type Calculation they use. + + var Pad32 = 0, Pad64 = 0; + + //*Initialize the Sign value that is only set for Negative, or Positive Relative displacements. + + var Sign = 0; + + //*Initialize the Sign Extend variable size as 0 Some Immediate numbers Sign extend. + + var Extend = 0; + + //*The variable S is the size of the Immediate. + + var S = SizeSetting & 0x0F; + + //*Extend size. + + Extend = SizeSetting >> 4; + + //*If by Size attributes is set true. + + if ( BySize ) + { + S = GetOperandSize( S ); + + if ( Extend > 0 ) + { + Extend = GetOperandSize( Extend ); + } + } + + /*------------------------------------------------------------------------------------------------------------------------- + The possible values of S (Calculated Size) are S=0 is IMM8, S=1 is IMM16, S=2 is IMM32, S=3 is IMM64. + Calculate how many bytes that are going to have to be read based on the value of S. + S=0 is 1 byte, S=1 is 2 bytes, S=2 is 4 bytes, S=3 is 8 bytes. + The Number of bytes to read is 2 to the power of S. + -------------------------------------------------------------------------------------------------------------------------*/ + + var n = 1 << S; + + //Adjust Pad32, and Pad64. + + Pad32 = Math.min( n, 4 ); ( n >= 8 ) && ( Pad64 = 8 ); + + //Store the first byte of the immediate because IMM8 can use different encodings. + + IMMValue = BinCode[CodePos]; + + //*Loop and Move the Decoder to the next byte Code position to the number of bytes to read for V32, and V64. + + for ( var i = 0, v = 1; i < Pad32; V32 += BinCode[CodePos] * v, i++, v *= 256, NextByte() ); + for ( v = 1; i < Pad64; V64 += BinCode[CodePos] * v, i++, v *= 256, NextByte() ); + + //*Adjust Pad32 so it matches the length the Immediate should be in hex for number of bytes read. + + Pad32 <<= 1; Pad64 <<= 1; + + /*--------------------------------------------------------------------------------------------------------------------------- + If the IMM type is used with an register operand on the upper four bit's then the IMM byte does not use the upper 4 bit's. + ---------------------------------------------------------------------------------------------------------------------------*/ + + if( type === 1 ) { V32 &= ( 1 << ( ( n << 3 ) - 4 ) ) - 1; } + + /*--------------------------------------------------------------------------------------------------------------------------- + If the Immediate is an relative address calculation. + ---------------------------------------------------------------------------------------------------------------------------*/ + + if ( type === 2 ) + { + //Calculate the Padded size for at the end of the function an Relative is padded to the size of the address based on bit mode. + + Pad32 = ( Math.min( BitMode, 1 ) << 2 ) + 4; Pad64 = Math.max( Math.min( BitMode, 2 ), 1 ) << 3; + + //Carry bit to 64 bit section. + + var C64 = 0; + + //Relative size. + + var n = Math.min( 0x100000000, Math.pow( 2, 4 << ( S + 1 ) ) ); + + //Sign bit adjust. + + if( V32 >= ( n / 2 ) ) { V32 -= n; } + + //Add position. + + V32 += Pos32; + + //Remove carry bit and add it to C64. + + ( C64 = ( ( V32 ) >= 0x100000000 ) ) && ( V32 -= 0x100000000 ); + + //Do not carry to 64 if address is 32, and below. + + if ( S <= 2 ) { C64 = false; } + + //Add the 64 bit position plus carry. + + ( ( V64 += Pos64 + C64 ) > 0xFFFFFFFF ) && ( V64 -= 0x100000000 ); + } + + /*--------------------------------------------------------------------------------------------------------------------------- + If the Immediate is an displacement calculation. + ---------------------------------------------------------------------------------------------------------------------------*/ + + if ( type === 3 ) + { + /*------------------------------------------------------------------------------------------------------------------------- + Calculate the displacement center point based on Immediate size. + -------------------------------------------------------------------------------------------------------------------------*/ + + //An displacement can not be bigger than 32 bit's, so Pad64 is set 0. + + Pad64 = 0; + + //Now calculate the Center Point. + + var Center = 2 * ( 1 << ( n << 3 ) - 2 ); + + //By default the Sign is Positive. + + Sign = 1; + + /*------------------------------------------------------------------------------------------------------------------------- + Calculate the VSIB displacement size if it is a VSIB Disp8. + -------------------------------------------------------------------------------------------------------------------------*/ + + if ( VSIB && S === 0 ) + { + var VScale = WidthBit | 2; + Center <<= VScale; V32 <<= VScale; + } + + //When the value is higher than the center it is negative. + + if ( V32 >= Center ) + { + //Convert the number to the negative side of the center point. + + V32 = Center * 2 - V32; + + //The Sign is negative. + + Sign = 2; + } + } + + /*--------------------------------------------------------------------------------------------------------------------------- + Pad Imm based on the calculated Immediate size, because when an value is converted to an number as text that can be displayed + the 0 digits to the left are removed. Think of this as like the number 000179 the actual length of the number is 6 digits, + but is displayed as 179, because the unused digits are not displayed, but they still exist in the memory. + ---------------------------------------------------------------------------------------------------------------------------*/ + + for( var Imm = V32.toString(16), L = Pad32; Imm.length < L; Imm = "0" + Imm ); + if( Pad64 > 8 ) { for( Imm = V64.toString(16) + Imm, L = Pad64; Imm.length < L; Imm = "0" + Imm ); } + + /*--------------------------------------------------------------------------------------------------------------------------- + Extend Imm if it's extend size is bigger than the Current Imm size. + ---------------------------------------------------------------------------------------------------------------------------*/ + + if ( Extend !== S ) + { + //Calculate number of bytes to Extend till by size. + + Extend = Math.pow( 2, Extend ) * 2; + + //Setup the Signified pad value. + + var spd = "00"; ( ( ( parseInt( Imm.substring(0, 1), 16) & 8 ) >> 3 ) ) && ( spd = "FF" ); + + //Start padding. + + for (; Imm.length < Extend; Imm = spd + Imm); + } + + //*Return the Imm. + + return ( ( Sign > 0 ? ( Sign > 1 ? "-" : "+" ) : "" ) + Imm.toUpperCase() ); + +} + +/*------------------------------------------------------------------------------------------------------------------------- +Decode registers by Size attributes, or a select register index. +-------------------------------------------------------------------------------------------------------------------------*/ + +function DecodeRegValue( RValue, BySize, Setting ) +{ + //If the instruction is a Vector instruction, and no extension is active like EVEX, VEX Make sure Size attribute uses the default vector size. + + if( Vect && Extension === 0 ) + { + SizeAttrSelect = 0; + } + + //If By size is true Use the Setting with the GetOperandSize + + if ( BySize ) + { + Setting = GetOperandSize( Setting ); //get decoded size value. + + //Any Vector register smaller than 128 has to XMM because XMM is the smallest SIMD Vector register. + + if( Vect && Setting < 4 ) { Setting = 4; } + } + + //If XOP only vector 0 to 15 are usable. + + if( Opcode >= 0x400 ) { RValue &= 15; } + + //Else If 16/32 bit mode in VEX/EVEX/MVEX vctor register can only go 0 though 7. + + else if( BitMode <= 1 && Extension >= 1 ) { RValue &= 7; } + + //If L1OM ZMM to V reg. + + if ( Opcode >= 0x700 && Setting === 6 ) + { + Setting = 16; + } + + //Else if 8 bit high/low Registers + + else if ( Setting === 0 ) + { + return (REG[0][RexActive][ RValue ]); + } + + //Return the Register. + + return (REG[Setting][ RValue ]); +} + +/*------------------------------------------------------------------------------------------------------------------------- +Decode the ModR/M pointer, and Optional SIB if used. +Note if by size attributes is false the lower four bits is the selected Memory pointer, +and the higher four bits is the selected register. +-------------------------------------------------------------------------------------------------------------------------*/ + +function Decode_ModRM_SIB_Address( ModRM, BySize, Setting ) +{ + var out = ""; //the variable out is what stores the decoded address pointer, or Register if Register mode. + var S_C = "{"; //L1OM, and K1OM {SSS,CCCCC} setting decoding, or EVEX broadcast round. + + //------------------------------------------------------------------------------------------------------------------------- + //If the ModR/M is not in register mode decode it as an Effective address. + //------------------------------------------------------------------------------------------------------------------------- + + if( ModRM[0] !== 3 ) + { + + //If the instruction is a Vector instruction, and no extension is active like EVEX, VEX Make sure Size attribute uses the default vector size. + + if( Vect && Extension === 0 ) + { + SizeAttrSelect = 0; + } + + //------------------------------------------------------------------------------------------------------------------------- + //The Selected Size is setting unless BySize attribute is true. + //------------------------------------------------------------------------------------------------------------------------- + + if ( BySize ) + { + //------------------------------------------------------------------------------------------------------------------------- + //Check if it is not the non vectorized 128 which uses "Oword ptr". + //------------------------------------------------------------------------------------------------------------------------- + + if ( Setting !== 16 || Vect ) + { + Setting = ( GetOperandSize( Setting ) << 1 ) | FarPointer; + } + + //------------------------------------------------------------------------------------------------------------------------- + //Non vectorized 128 uses "Oword ptr" alaises to "QWord ptr" in 32 bit mode, or lower. + //------------------------------------------------------------------------------------------------------------------------- + + else if ( !Vect ) { Setting = 11 - ( ( BitMode <= 1 ) * 5 ); } + } + + //------------------------------------------------------------------------------------------------------------------------- + //If By size attributes is false the selected Memory pointer is the first four bits of the size setting for all pointer indexes 0 to 15. + //Also if By size attribute is also true the selected by size index can not exceed 15 anyways which is the max combination the first four bits. + //------------------------------------------------------------------------------------------------------------------------- + + Setting = Setting & 0x0F; + + //If Vector extended then MM is changed to QWORD. + + if( Extension !== 0 && Setting === 9 ){ Setting = 6; } + + //Bround control, or 32/64 VSIB. + + if ( ConversionMode === 1 || ConversionMode === 2 || VSIB ) { out += PTR[WidthBit > 0 ? 6 : 4]; } + + //------------------------------------------------------------------------------------------------------------------------- + //Get the pointer size by Size setting. + //------------------------------------------------------------------------------------------------------------------------- + + else{ out = PTR[Setting]; } + + //Add the Segment override left address bracket if any segment override was used otherwise the SegOverride string should be just a normal left bracket. + + out += SegOverride; + + //------------------------------------------------------------------------------------------------------------------------- + //calculate the actual address size according to the Address override and the CPU bit mode. + //------------------------------------------------------------------------------------------------------------------------- + //AddressSize 1 is 16, AddressSize 2 is 32, AddressSize 3 is 64. + //The Bit mode is the address size except AddressOverride reacts differently in different bit modes. + //In 16 bit AddressOverride switches to the 32 bit ModR/M effective address system. + //In both 32/64 the Address size goes down by one is size. + //------------------------------------------------------------------------------------------------------------------------- + + var AddressSize = BitMode + 1; + + if (AddressOverride) + { + AddressSize = AddressSize - 1; + + //the only time the address size is 0 is if the BitMode is 16 bit's and is subtracted by one resulting in 0. + + if(AddressSize === 0) + { + AddressSize = 2; //set the address size to 32 bit from the 16 bit address mode. + } + } + + /*------------------------------------------------------------------------------------------------------------------------- + The displacement size calculation. + --------------------------------------------------------------------------------------------------------------------------- + In 16/32/64 the mode setting 1 will always add a Displacement of 8 to the address. + In 16 the Mode setting 2 adds a displacement of 16 to the address. + In 32/64 the Mode Setting 2 for the effective address adds an displacement of 32 to the effective address. + -------------------------------------------------------------------------------------------------------------------------*/ + + var Disp = ModRM[0] - 1; //Let disp relate size to mode value of the ModR/M. + + //if 32 bit and above, and if Mode is 2 then disp size is disp32. + + if(AddressSize >= 2 && ModRM[0] === 2) + { + Disp += 1; //Only one more higher in size is 32. + } + + /*------------------------------------------------------------------------------------------------------------------------- + End of calculation. + -------------------------------------------------------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------------------------------------------------------- + Normally the displacement type is an relative Immediate that is added ("+"), + or subtracted ("-") from the center point to the selected base register, + and the size depends on mode settings 1, and 2, and also Address bit mode (Displacement calculation). + Because the normal ModR/M format was limited to Relative addresses, and unfixed locations, + so some modes, and registers combinations where used for different Immediate displacements. + -------------------------------------------------------------------------------------------------------------------------*/ + + var DispType = 3; //by default the displacement size is added to the selected base register, or Index register if SIB byte combination is used. + + //-------------------------------------------16 Bit ModR/M address decode logic------------------------------------------- + + if( AddressSize === 1 ) + { + + //if ModR/M mode bits 0, and Base Register value is 6 then disp16 with DispType mode 0. + + if(AddressSize === 1 && ModRM[0] === 0 && ModRM[2] === 6) + { + Disp = 1; + DispType = 0; + } + + //BX , BP switch based on bit 2 of the Register value + + if( ModRM[2] < 4 ){ out += REG[ AddressSize ][ 3 + ( ModRM[2] & 2 ) ] + "+"; } + + //The first bit switches between Destination index, and source index + + if( ModRM[2] < 6 ){ out += REG[ AddressSize ][ 6 + ( ModRM[2] & 1 ) ]; } + + //[BP], and [BX] as long as Mode is not 0, and Register is not 6 which sets DispType 0. + + else if ( DispType !== 0 ) { out += REG[ AddressSize ][ 17 - ( ModRM[2] << 1 ) ]; } + } //End of 16 bit ModR/M decode logic. + + //-------------------------------------------Else 32/64 ModR/M------------------------------------------- + + else + { + + //if Mode is 0 and Base Register value is 5 then it uses an Relative (RIP) disp32. + + if( ModRM[0] === 0 && ModRM[2] === 5 ) + { + Disp = 2; + DispType = 2; + } + + //check if Base Register is 4 which goes into the SIB address system + + if( ModRM[2] === 4 ) + { + //Decode the SIB byte. + + var SIB = Decode_ModRM_SIB_Value(); + + //Calculate the Index register with it's Extended value because the index register will only cancel out if 4 in value. + + var IndexReg = IndexExtend | SIB[1]; + + //check if the base register is 5 in value in the SIB without it's added extended value, and that the ModR/M Mode is 0 this activates Disp32 + + if ( ModRM[0] === 0 && SIB[2] === 5 && !VSIB ) + { + Disp = 2; //Set Disp32 + + //check if the Index register is canceled out as well + + if (IndexReg === 4) //if the Index is canceled out then + { + DispType = 0; //a regular IMM32 is used as the address. + + //*if the Address size is 64 then the 32 bit Immediate must pad to the full 64 bit address. + + if( AddressSize === 3 ) { Disp = 50; } + } + } + + //Else Base register is not 5, and the Mode is not 0 then decode the base register normally. + + else + { + out += REG[ AddressSize ][ BaseExtend & 8 | SIB[2] ]; + + //If the Index Register is not Canceled out (Note this is only reachable if base register was decoded and not canceled out) + + if ( IndexReg !== 4 || VSIB ) + { + out = out + "+"; //Then add the Plus in front of the Base register to add the index register + } + } + + //if Index Register is not Canceled, and that it is not an Vector register then decode the Index with the possibility of the base register. + + if ( IndexReg !== 4 && !VSIB ) + { + out += REG[ AddressSize ][ IndexExtend | IndexReg ]; + + //add what the scale bits decode to the Index register by the value of the scale bits which select the name from the scale array. + + out = out + scale[SIB[0]]; + } + + //Else if it is an vector register. + + else if ( VSIB ) + { + Setting = ( Setting < 8 ) ? 4 : Setting >> 1; + + if( Opcode < 0x700 ) { IndexReg |= ( VectorRegister & 0x10 ); } + + out += DecodeRegValue( IndexExtend | IndexReg, false, Setting ); //Decode Vector register by length setting and the V' extension. + + //add what the scale bits decode to the Index register by the value of the scale bits which select the name from the scale array. + + out = out + scale[SIB[0]]; + } + } //END OF THE SIB BYTE ADDRESS DECODE. + + //else Base register is not 4 and does not go into the SIB ADDRESS. + //Decode the Base register regularly plus it's Extended value if relative (RIP) disp32 is not used. + + else if(DispType !== 2) + { + out += REG[ AddressSize ][ BaseExtend & 8 | ModRM[2] ]; + } + } + + + //Finally the Immediate displacement is put into the Address last. + + if( Disp >= 0 ) { out += DecodeImmediate( DispType, false, Disp ); } + + //Put the right bracket on the address. + + out += "]"; + + //----------------------L1OM/MVEX/EVEX memory conversion mode, or broadcast round----------------------- + + if( + ( ConversionMode !== 0 ) && //Not used if set 0. + !( + ( ConversionMode === 3 && ( Opcode >= 0x700 || !( Opcode >= 0x700 ) && !Float ) ) || //If bad L1OM/K1OM float conversion. + ( !( Opcode >= 0x700 ) && ( VectS === 0 || ( ConversionMode === 5 && VectS === 5 ) || //If K1OM UNorm conversion L1OM only. + ( ConversionMode !== 1 && VectS === 1 ) ^ ( ConversionMode < 3 && !Swizzle ) ) ) //Or K1OM broadcast Swizzle, and special case {4to16} only. + ) + ) + { + //Calculate Conversion. + + if( ConversionMode >= 4 ){ ConversionMode += 2; } + if( ConversionMode >= 8 ){ ConversionMode += 2; } + + //If L1OM. + + if( Opcode >= 0x700 ) + { + //If L1OM without Swizzle. + + if ( !Swizzle && ConversionMode > 2 ) { ConversionMode = 31; } + + //L1OM Float adjust. + + else if( Float ) + { + if( ConversionMode === 7 ) { ConversionMode++; } + if( ConversionMode === 10 ) { ConversionMode = 3; } + } + } + + //Set conversion. Note K1OM special case inverts width bit. + + out += S_C + ConversionModes[ ( ConversionMode << 1 ) | ( WidthBit ^ ( !( Opcode >= 0x700 ) & VectS === 7 ) ) & 1 ]; S_C = ","; + } + + //Else bad Conversion setting. + + else if( ConversionMode !== 0 ) { out += S_C + "Error"; S_C = ","; } + + //--------------------------------END of memory Conversion control logic-------------------------------- + + } //End of Memory address Modes 00, 01, 10 decode. + + //-----------------------------else the ModR/M mode bits are 11 register Mode----------------------------- + + else + { + //------------------------------------------------------------------------------------------------------------------------- + //The Selected Size is setting unless BySize attribute is true. + //------------------------------------------------------------------------------------------------------------------------- + + //MVEX/EVEX round mode. + + if ( ( Extension === 3 && HInt_ZeroMerg ) || ( Extension === 2 && ConversionMode === 1 ) ) + { + RoundMode |= RoundingSetting; + } + + //If the upper 4 bits are defined and by size is false then the upper four bits is the selected register. + + if( ( ( Setting & 0xF0 ) > 0 ) && !BySize ) { Setting >>= 4; } + + //Decode the register with Base expansion. + + out = DecodeRegValue( BaseExtend | ModRM[2], BySize, Setting ); + + //L1OM/K1OM Register swizzle modes. + + if( Opcode >= 0x700 || ( Extension === 3 && !HInt_ZeroMerg && Swizzle ) ) + { + if( Opcode >= 0x700 && ConversionMode >= 3 ){ ConversionMode++; } //L1OM skips swizzle type DACB. + if( ConversionMode !== 0 ){ out += S_C + RegSwizzleModes[ ConversionMode ]; S_C = ","; } + } + if( Extension !== 2 ){ HInt_ZeroMerg = false; } //Cache memory control is not possible in Register mode. + } + + //--------------------------------------------------L1OM.CCCCC conversions------------------------------------------------- + + if( Opcode >= 0x700 ) + { + //Swizzle Field control Int/Float, or Exponent adjustment. + + if(Swizzle) + { + if( Opcode === 0x79A ) { out += S_C + ConversionModes[ ( 18 | ( VectorRegister & 3 ) ) << 1 ]; S_C = "}"; } + else if( Opcode === 0x79B ) { out += S_C + ConversionModes[ ( 22 + ( VectorRegister & 3 ) ) << 1 ]; S_C = "}"; } + else if( ( RoundingSetting & 8 ) === 8 ) { out += S_C + RoundModes [ 24 | ( VectorRegister & 7 ) ]; S_C = "}"; } + } + + //Up/Down Conversion. + + else if( VectorRegister !== 0 ) + { + if( ( ( Up && VectorRegister !== 2 ) || //Up conversion "float16rz" is bad. + ( !Up && VectorRegister !== 3 && VectorRegister <= 15 ) ) //Down conversion "srgb8", and field control is bad. + ) { out += S_C + ConversionModes[ ( ( VectorRegister + 2 ) << 1 ) | WidthBit ]; S_C = "}"; } + else { out += S_C + "Error"; S_C = "}"; } //Else Invalid setting. + } + } + if ( S_C === "," ) { S_C = "}"; } + + //Right bracket if any SSS,CCCCC conversion mode setting. + + if( S_C === "}" ) { out += S_C; } + + //------------------------------------------L1OM/K1OM Hint cache memory control-------------------------------------------- + + if( HInt_ZeroMerg ) + { + if ( Extension === 3 ) { out += "{EH}"; } + else if ( Opcode >= 0x700 ) { out += "{NT}"; } + } + + //-------------------------------------------Return the Register/Memory address-------------------------------------------- + + return (out); +} + +/*------------------------------------------------------------------------------------------------------------------------- +Decode Prefix Mnemonic codes. Prefixes are instruction codes that do not do an operation instead adjust +controls in the CPU to be applied to an select instruction code that is not an Prefix instruction. +--------------------------------------------------------------------------------------------------------------------------- +At the end of this function "Opcode" should not hold any prefix code, so then Opcode contains an operation code. +-------------------------------------------------------------------------------------------------------------------------*/ + +function DecodePrefixAdjustments() +{ + //------------------------------------------------------------------------------------------------------------------------- + Opcode = ( Opcode & 0x300 ) | BinCode[CodePos]; //Add 8 bit opcode while bits 9, and 10 are used for opcode map. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + + //if 0F hex start at 256 for Opcode. + + if(Opcode === 0x0F) + { + Opcode = 0x100; //By starting at 0x100 with binary bit 9 set one then adding the 8 bit opcode then Opcode goes 256 to 511. + return(DecodePrefixAdjustments()); //restart function decode more prefix settings that can effect the decode instruction. + } + + //if 38 hex while using two byte opcode. + + else if(Opcode === 0x138 && Mnemonics[0x138] === "") + { + Opcode = 0x200; //By starting at 0x200 with binary bit 10 set one then adding the 8 bit opcode then Opcode goes 512 to 767. + return(DecodePrefixAdjustments()); //restart function decode more prefix settings that can effect the decode instruction. + } + + //if 3A hex while using two byte opcode go three byte opcodes. + + else if(Opcode === 0x13A && Mnemonics[0x13A] === "") + { + Opcode = 0x300; //By starting at 0x300 hex and adding the 8 bit opcode then Opcode goes 768 to 1023. + return(DecodePrefixAdjustments()); //restart function decode more prefix settings that can effect the decode instruction. + } + + //Rex prefix decodes only in 64 bit mode. + + if( Opcode >= 0x40 & Opcode <= 0x4F && BitMode === 2 ) + { + RexActive = 1; //Set Rex active uses 8 bit registers in lower order as 0 to 15. + BaseExtend = ( Opcode & 0x01 ) << 3; //Base Register extend setting. + IndexExtend = ( Opcode & 0x02 ) << 2; //Index Register extend setting. + RegExtend = ( Opcode & 0x04 ) << 1; //Register Extend Setting. + WidthBit = ( Opcode & 0x08 ) >> 3; //Set The Width Bit setting if active. + SizeAttrSelect = WidthBit ? 2 : 1; //The width Bit open all 64 bits. + return(DecodePrefixAdjustments()); //restart function decode more prefix settings that can effect the decode instruction. + } + + //The VEX2 Operation code Extension to SSE settings decoding. + + if( Opcode === 0xC5 && ( BinCode[CodePos] >= 0xC0 || BitMode === 2 ) ) + { + Extension = 1; + //------------------------------------------------------------------------------------------------------------------------- + Opcode = BinCode[CodePos]; //read VEX2 byte settings. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + + //some bits are inverted, so uninvert them arithmetically. + + Opcode ^= 0xF8; + + //Decode bit settings. + + if( BitMode === 2 ) + { + RegExtend = ( Opcode & 0x80 ) >> 4; //Register Extend. + VectorRegister = ( Opcode & 0x78 ) >> 3; //The added in Vector register to SSE. + } + + SizeAttrSelect = ( Opcode & 0x04 ) >> 2; //The L bit for 256 vector size. + SIMD = Opcode & 0x03; //The SIMD mode. + + //Automatically uses the two byte opcode map starts at 256 goes to 511. + + Opcode = 0x100; + + //------------------------------------------------------------------------------------------------------------------------- + Opcode = ( Opcode & 0x300 ) | BinCode[CodePos]; //read the opcode. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + + //Stop decoding prefixes. + + return(null); + } + + //The VEX3 prefix settings decoding. + + if( Opcode === 0xC4 && ( BinCode[CodePos] >= 0xC0 || BitMode === 2 ) ) + { + Extension = 1; + //------------------------------------------------------------------------------------------------------------------------- + Opcode = BinCode[CodePos]; //read VEX3 byte settings. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + Opcode |= ( BinCode[CodePos] << 8 ); //Read next VEX3 byte settings. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + + //Some bits are inverted, so uninvert them arithmetically. + + Opcode ^= 0x78E0; + + //Decode bit settings. + + if( BitMode === 2 ) + { + RegExtend = ( Opcode & 0x0080 ) >> 4; //Extend Register Setting. + IndexExtend = ( Opcode & 0x0040 ) >> 3; //Extend Index register setting. + BaseExtend = ( Opcode & 0x0020 ) >> 2; //Extend base Register setting. + } + + WidthBit = ( Opcode & 0x8000 ) >> 15; //The width bit works as a separator. + VectorRegister = ( Opcode & 0x7800 ) >> 11; //The added in Vector register to SSE. + SizeAttrSelect = ( Opcode & 0x0400 ) >> 10; //Vector length for 256 setting. + SIMD = ( Opcode & 0x0300 ) >> 8; //The SIMD mode. + Opcode = ( Opcode & 0x001F ) << 8; //Change Operation code map. + + //------------------------------------------------------------------------------------------------------------------------- + Opcode = ( Opcode & 0x300 ) | BinCode[CodePos]; //read the 8 bit opcode put them in the lower 8 bits away from opcode map bit's. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + + return(null); + } + + //The AMD XOP prefix. + + if( Opcode === 0x8F ) + { + //If XOP + + var Code = BinCode[ CodePos ] & 0x0F; + + if( Code >= 8 && Code <= 10 ) + { + Extension = 1; + //------------------------------------------------------------------------------------------------------------------------- + Opcode = BinCode[CodePos]; //read XOP byte settings. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + Opcode |= ( BinCode[CodePos] << 8 ); //Read next XOP byte settings. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + + //Some bits are inverted, so uninvert them arithmetically. + + Opcode ^= 0x78E0; + + //Decode bit settings. + + RegExtend = ( Opcode & 0x0080 ) >> 4; //Extend Register Setting. + IndexExtend = ( Opcode & 0x0040 ) >> 3; //Extend Index register setting. + BaseExtend = ( Opcode & 0x0020 ) >> 2; //Extend base Register setting. + WidthBit = ( Opcode & 0x8000 ) >> 15; //The width bit works as a separator. + VectorRegister = ( Opcode & 0x7800 ) >> 11; //The added in Vector register to SSE. + SizeAttrSelect = ( Opcode & 0x0400 ) >> 10; //Vector length for 256 setting. + SIMD = ( Opcode & 0x0300 ) >> 8; //The SIMD mode. + if( SIMD > 0 ) { InvalidOp = true; } //If SIMD MODE is set anything other than 0 the instruction is invalid. + Opcode = 0x400 | ( ( Opcode & 0x0003 ) << 8 ); //Change Operation code map. + + //------------------------------------------------------------------------------------------------------------------------- + Opcode = ( Opcode & 0x700 ) | BinCode[CodePos]; //read the 8 bit opcode put them in the lower 8 bits away from opcode map bit's. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + + return(null); + } + } + + //The L1OM vector prefix settings decoding. + + if( Opcode === 0xD6 ) + { + //------------------------------------------------------------------------------------------------------------------------- + Opcode = BinCode[CodePos]; //read L1OM byte settings. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + Opcode |= ( BinCode[CodePos] << 8 ); //Read next L1OM byte settings. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + + WidthBit = SIMD & 1; + VectorRegister = ( Opcode & 0xF800 ) >> 11; + RoundMode = VectorRegister >> 3; + MaskRegister = ( Opcode & 0x0700 ) >> 8; + HInt_ZeroMerg = ( Opcode & 0x0080 ) >> 7; + ConversionMode = ( Opcode & 0x0070 ) >> 4; + RegExtend = ( Opcode & 0x000C ) << 1; + BaseExtend = ( Opcode & 0x0003 ) << 3; + IndexExtend = ( Opcode & 0x0002 ) << 2; + + //------------------------------------------------------------------------------------------------------------------------- + Opcode = 0x700 | BinCode[CodePos]; //read the 8 bit opcode. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + + return(null); + } + + //Only decode L1OM instead of MVEX/EVEX if L1OM compatibility mode is set. + + if( Mnemonics[0x62] === "" && Opcode === 0x62 ) + { + //------------------------------------------------------------------------------------------------------------------------- + Opcode = BinCode[CodePos]; //read L1OM byte settings. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + + Opcode ^= 0xF0; + + IndexExtend = ( Opcode & 0x80 ) >> 4; + BaseExtend = ( Opcode & 0x40 ) >> 3; + RegExtend = ( Opcode & 0x20 ) >> 2; + + if ( SIMD !== 1 ) { SizeAttrSelect = ( ( Opcode & 0x10 ) === 0x10 ) ? 2 : 1; } else { SIMD = 0; } + + Opcode = 0x800 | ( ( Opcode & 0x30 ) >> 4 ) | ( ( Opcode & 0x0F ) << 2 ); + + return(null); + } + + //The MVEX/EVEX prefix settings decoding. + + if ( Opcode === 0x62 && ( BinCode[CodePos] >= 0xC0 || BitMode === 2 ) ) + { + Extension = 2; + //------------------------------------------------------------------------------------------------------------------------- + Opcode = BinCode[CodePos]; //read MVEX/EVEX byte settings. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + Opcode |= ( BinCode[CodePos] << 8 ); //read next MVEX/EVEX byte settings. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + Opcode |= ( BinCode[CodePos] << 16 ); //read next MVEX/EVEX byte settings. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + + //Some bits are inverted, so uninvert them arithmetically. + + Opcode ^= 0x0878F0; + + //Check if Reserved bits are 0 if they are not 0 the MVEX/EVEX instruction is invalid. + + InvalidOp = ( Opcode & 0x00000C ) > 0; + + //Decode bit settings. + + if( BitMode === 2 ) + { + RegExtend = ( ( Opcode & 0x80 ) >> 4 ) | ( Opcode & 0x10 ); //The Double R'R bit decode for Register Extension 0 to 32. + BaseExtend = ( Opcode & 0x60 ) >> 2; //The X bit, and B Bit base register extend combination 0 to 32. + IndexExtend = ( Opcode & 0x40 ) >> 3; //The X extends the SIB Index by 8. + } + + VectorRegister = ( ( Opcode & 0x7800 ) >> 11 ) | ( ( Opcode & 0x080000 ) >> 15 ); //The Added in Vector Register for SSE under MVEX/EVEX. + + WidthBit = ( Opcode & 0x8000 ) >> 15; //The width bit separator for MVEX/EVEX. + SIMD = ( Opcode & 0x0300 ) >> 8; //decode the SIMD mode setting. + HInt_ZeroMerg = ( Opcode & 0x800000 ) >> 23; //Zero Merge to destination control, or MVEX EH control. + + //EVEX option bits take the place of Vector length control. + + if ( ( Opcode & 0x0400 ) > 0 ) + { + SizeAttrSelect = ( Opcode & 0x600000 ) >> 21; //The EVEX.L'L Size combination. + RoundMode = SizeAttrSelect | 4; //Rounding mode is Vector length if used. + ConversionMode = (Opcode & 0x100000 ) >> 20; //Broadcast Round Memory address system. + } + + //MVEX Vector Length, and Broadcast round. + + else + { + SizeAttrSelect = 2; //Max Size by default. + ConversionMode = ( Opcode & 0x700000 ) >> 20; //"MVEX.sss" Option bits. + RoundMode = ConversionMode; //Rounding mode selection is ConversionMode if used. + Extension = 3; + } + + MaskRegister = ( Opcode & 0x070000 ) >> 16; //Mask to destination. + Opcode = ( Opcode & 0x03 ) << 8; //Change Operation code map. + + //------------------------------------------------------------------------------------------------------------------------- + Opcode = ( Opcode & 0x300 ) | BinCode[CodePos]; //read the 8 bit opcode put them in the lower 8 bits away from opcode map extend bit's. + NextByte(); //Move to the next byte. + //------------------------------------------------------------------------------------------------------------------------- + + //Stop decoding prefixes. + + return(null); + } + + //Segment overrides + + if ( ( Opcode & 0x7E7 ) === 0x26 || ( Opcode & 0x7FE ) === 0x64 ) + { + SegOverride = Mnemonics[ Opcode ]; //Set the Left Bracket for the ModR/M memory address. + return(DecodePrefixAdjustments()); //restart function decode more prefix settings that can effect the decode instruction. + } + + //Operand override Prefix + + if(Opcode === 0x66) + { + SIMD = 1; //sets SIMD mode 1 in case of SSE instruction opcode. + SizeAttrSelect = 0; //Adjust the size attribute setting for the size adjustment to the next instruction. + return(DecodePrefixAdjustments()); //restart function decode more prefix settings that can effect the decode instruction. + } + + //Ram address size override. + + if(Opcode === 0x67) + { + AddressOverride = true; //Set the setting active for the ModR/M address size. + return(DecodePrefixAdjustments()); //restart function decode more prefix settings that can effect the decode instruction. + } + + //if repeat Prefixes F2 hex REP,or F3 hex RENP + + if (Opcode === 0xF2 || Opcode === 0xF3) + { + SIMD = (Opcode & 0x02 ) | ( 1 - Opcode & 0x01 ); //F2, and F3 change the SIMD mode during SSE instructions. + PrefixG1 = Mnemonics[ Opcode ]; //set the Prefix string. + HLEFlipG1G2 = true; //set Filp HLE in case this is the last prefix read, and LOCK was set in string G2 first for HLE. + return(DecodePrefixAdjustments()); //restart function decode more prefix settings that can effect the decode instruction. + } + + //if the lock prefix note the lock prefix is separate + + if (Opcode === 0xF0) + { + PrefixG2 = Mnemonics[ Opcode ]; //set the Prefix string + HLEFlipG1G2 = false; //set Flip HLE false in case this is the last prefix read, and REP, or REPNE was set in string G2 first for HLE. + return(DecodePrefixAdjustments()); //restart function decode more prefix settings that can effect the decode instruction. + } + + //Before ending the function "DecodePrefixAdjustments()" some opcode combinations are invalid in 64 bit mode. + + if ( BitMode === 2 ) + { + InvalidOp |= ( ( ( Opcode & 0x07 ) >= 0x06 ) & ( Opcode <= 0x40 ) ); + InvalidOp |= ( Opcode === 0x60 | Opcode === 0x61 ); + InvalidOp |= ( Opcode === 0xD4 | Opcode === 0xD5 ); + InvalidOp |= ( Opcode === 0x9A | Opcode === 0xEA ); + InvalidOp |= ( Opcode === 0x82 ); + } + +} + +/*------------------------------------------------------------------------------------------------------------------------- +The Decode opcode function gives back the operation name, and what it uses for input. +The input types are for example which registers it uses with the ModR/M, or which Immediate type is used. +The input types are stored into an operand string. This function gives back the instruction name, And what the operands use. +--------------------------------------------------------------------------------------------------------------------------- +This function is designed to be used after the Decode prefix adjustments function because the Opcode should contain an real instruction code. +This is because the Decode prefix adjustments function will only end if the Opcode value is not a prefix adjustment code to the ModR/M etc. +However DecodePrefixAdjustments can also prevent this function from being called next if the prefix settings are bad or an invalid instruction is +used for the bit mode the CPU is in as it will set InvalidOp true. +-------------------------------------------------------------------------------------------------------------------------*/ + +function DecodeOpcode() +{ + //get the Operation name by the operations opcode. + + Instruction = Mnemonics[Opcode]; + + //get the Operands for this opcode it follows the same array structure as Mnemonics array + + InsOperands = Operands[Opcode]; + + //Some Opcodes use the next byte automatically for extended opcode selection. Or current SIMD mode. + + var ModRMByte = BinCode[CodePos]; //Read the byte but do not move to the next byte. + + //If the current Mnemonic is an array two in size then Register Mode, and memory mode are separate from each other. + //Used in combination with Grouped opcodes, and Static opcodes. + + if(Instruction instanceof Array && Instruction.length == 2) { var bits = ( ModRMByte >> 6 ) & ( ModRMByte >> 7 ); Instruction = Instruction[bits]; InsOperands = InsOperands[bits]; } + + //Arithmetic unit 8x8 combinational logic array combinations. + //If the current Mnemonic is an array 8 in length It is a group opcode instruction may repeat previous instructions in different forums. + + if(Instruction instanceof Array && Instruction.length == 8) { var bits = ( ModRMByte & 0x38 ) >> 3; Instruction = Instruction[bits]; InsOperands = InsOperands[bits]; + + //if The select Group opcode is another array 8 in size it is a static opcode selection which makes the last three bits of the ModR/M byte combination. + + if(Instruction instanceof Array && Instruction.length == 8) { var bits = ( ModRMByte & 0x07 ); Instruction = Instruction[bits]; InsOperands = InsOperands[bits]; NextByte(); } } + + //Vector unit 4x4 combinational array logic. + //if the current Mnemonic is an array 4 in size it is an SIMD instruction with four possible modes N/A, 66, F3, F2. + //The mode is set to SIMD, it could have been set by the EVEX.pp, VEX.pp bit combination, or by prefixes N/A, 66, F3, F2. + + if(Instruction instanceof Array && Instruction.length == 4) + { + Vect = true; //Set Vector Encoding true. + + //Reset the prefix string G1 because prefix codes F2, and F3 are used with SSE which forum the repeat prefix. + //Some SSE instructions can use the REP, RENP prefixes. + //The Vectors that do support the repeat prefix uses Packed Single format. + + if(Instruction[2] !== "" && Instruction[3] !== "") { PrefixG1 = ""; } else { SIMD = ( SIMD === 1 ) & 1; } + Instruction = Instruction[SIMD]; InsOperands = InsOperands[SIMD]; + + //If the SIMD instruction uses another array 4 in length in the Selected SIMD vector Instruction. + //Then each vector Extension is separate. The first extension is used if no extension is active for Regular instructions, and vector instruction septation. + //0=None. 1=VEX only. 2=EVEX only. 3=??? unused. + + if(Instruction instanceof Array && Instruction.length == 4) + { + //Get the correct Instruction for the Active Extension type. + + if(Instruction[Extension] !== "") { Instruction = Instruction[Extension]; InsOperands = InsOperands[Extension]; } + else{ Instruction = "???"; InsOperands = ""; } + } + else if( Extension === 3 ){ Instruction = "???"; InsOperands = ""; } + } + else if( Opcode >= 0x700 && SIMD > 0 ){ Instruction = "???"; InsOperands = ""; } + + //if Any Mnemonic is an array 3 in size the instruction name goes by size. + + if(Instruction instanceof Array && Instruction.length == 3) + { + var bits = ( Extension === 0 & BitMode !== 0 ) ^ ( SizeAttrSelect >= 1 ); //The first bit in SizeAttrSelect for size 32/16 Flips if 16 bit mode. + ( WidthBit ) && ( bits = 2 ); //Goes 64 using the Width bit. + ( Extension === 3 && HInt_ZeroMerg && Instruction[1] !== "" ) && ( HInt_ZeroMerg = false, bits = 1 ); //MVEX uses element 1 if MVEX.E is set for instruction that change name. + + if (Instruction[bits] !== "") { Instruction = Instruction[bits]; InsOperands = InsOperands[bits]; } + + //else no size prefix name then use the default size Mnemonic name. + + else { Instruction = Instruction[0]; InsOperands = InsOperands[0]; } + } + + //If Extension is not 0 then add the vector extend "V" to the instruction. + //During the decoding of the operands the instruction can be returned as invalid if it is an Arithmetic, or MM, ST instruction. + //Vector mask instructions start with K instead of V any instruction that starts with K and is an + //vector mask Instruction which starts with K instead of V. + + if( Opcode <= 0x400 && Extension > 0 && Instruction.charAt(0) !== "K" && Instruction !== "???" ) { Instruction = "V" + Instruction; } + + //In 32 bit mode, or bellow only one instruction MOVSXD is replaced with ARPL. + + if( BitMode <= 1 && Instruction === "MOVSXD" ) { Instruction = "ARPL"; InsOperands = "06020A01"; } +} + +/*------------------------------------------------------------------------------------------------------------------------- +Read each operand in the Operand String then set the correct operand in the X86 decoder array. +OpNum is the order the operands are read in the operand string. The Operand type is which operand will be set +active along the X86Decoder. The OpNum is the order the decoded operands will be positioned after they are decoded +in order along the X86 decoder. The order the operands display is different than the order they decode in sequence. +--------------------------------------------------------------------------------------------------------------------------- +This function is used after the function ^DecodeOpcode()^ because the function ^DecodeOpcode()^ gives back the +operand string for what the instruction takes as input. +-------------------------------------------------------------------------------------------------------------------------*/ + +function DecodeOperandString() +{ + //Variables that are used for decoding one operands across the operand string. + + var OperandValue = 0, Code = 0, BySize = 0, Setting = 0; + + //It does not matter which order the explicit operands decode as they do not require reading another byte. + //They start at 7 and are set in order, but the order they are displayed is the order they are read in the operand string because of OpNum. + + var ExplicitOp = 8, ImmOp = 3; + + //Each operand is 4 hex digits, and OpNum is added by one for each operand that is read per Iteration. + + for( var i = 0, OpNum = 0; i < InsOperands.length; i+=4 ) //Iterate though operand string. + { + OperandValue = parseInt( InsOperands.substring(i, (i + 4) ), 16 ); //Convert the four hex digits to a 16 bit number value. + Code = ( OperandValue & 0xFE00 ) >> 9; //Get the operand Code. + BySize = ( OperandValue & 0x0100 ) >> 8; //Get it's by size attributes setting for if Setting is used as size attributes. + Setting = ( OperandValue & 0x00FF ); //Get the 8 bit Size setting. + + //If code is 0 the next 8 bit value specifies which type of of prefix settings are active. + + if( Code === 0 ) + { + if(BySize) //Vector adjustment settings. + { + RoundingSetting = ( Setting & 0x03 ) << 3; + if( Opcode >= 0x700 && RoundingSetting >= 0x10 ){ RoundMode |= 0x10; } + VSIB = ( Setting >> 2 ) & 1; + IgnoresWidthbit = ( Setting >> 3 ) & 1; + VectS = ( Setting >> 4 ) & 7; + Swizzle = ( VectS >> 2 ) & 1; + Up = ( VectS >> 1 ) & 1; + Float = VectS & 1; + if( ( Setting & 0x80 ) == 0x80 ) { Vect = false; } //If Non vector instruction set Vect false. + } + else //Instruction Prefix types. + { + XRelease = Setting & 0x01; + XAcquire = ( Setting & 0x02 ) >> 1; + HT = ( Setting & 0x04 ) >> 2; + BND = ( Setting & 0x08 ) >> 3; + } + } + + //if it is a opcode Reg Encoding then first element along the decoder is set as this has to be decode first, before moving to the + //byte for modR/M. + + else if( Code === 1 ) + { + X86Decoder[0].set( 0, BySize, Setting, OpNum++ ); + } + + //if it is a ModR/M, or Far pointer ModR/M, or Moffs address then second decoder element is set. + + else if( Code >= 2 && Code <= 4 ) + { + X86Decoder[1].set( ( Code - 2 ), BySize, Setting, OpNum++ ); + if( Code == 4 ){ FarPointer = 1; } //If code is 4 it is a far pointer. + } + + //The ModR/M Reg bit's are separated from the address system above. The ModR/M register can be used as a different register with a + //different address pointer. The Reg bits of the ModR/M decode next as it would be inefficient to read the register value if the + //decoder moves to the immediate. + + else if( Code === 5 ) + { + X86Decoder[2].set( 0, BySize, Setting, OpNum++ ); + } + + //Immediate input one. The immediate input is just a number input it is decoded last unless the instruction does not use a + //ModR/M encoding, or Reg Opcode. + + else if( Code >= 6 && Code <= 8 && ImmOp <= 5 ) + { + X86Decoder[ImmOp++].set( ( Code - 6 ), BySize, Setting, OpNum++ ); + } + + //Vector register. If the instruction uses this register it will not be decoded or displayed unless one of the vector extension codes are + //decoded by the function ^DecodePrefixAdjustments()^. The Vector extension codes also have a Vector register value that is stored into + //the variable VectorRegister. The variable VectorRegister is given to the function ^DecodeRegValue()^. + + else if( Code === 9 && ( Extension > 0 || Opcode >= 0x700 ) ) + { + X86Decoder[6].set( 0, BySize, Setting, OpNum++ ); + } + + //The upper four bits of the Immediate is used as an register. The variable IMM stores the last immediate byte that is read by ^DecodeImmediate()^. + //The upper four bits of the IMM is given to the function ^DecodeRegValue()^. + + else if( Code === 10 ) + { + X86Decoder[7].set( 0, BySize, Setting, OpNum++ ); + } + + //Else any other encoding type higher than 13 is an explicit operand selection. + //And also there can only be an max of four explicit operands. + + else if( Code >= 11 && ExplicitOp <= 11) + { + X86Decoder[ExplicitOp].set( ( Code - 11 ), BySize, Setting, OpNum++ ); + ExplicitOp++; //move to the next Explicit operand. + } + } +} + +/*------------------------------------------------------------------------------------------------------------------------- +Decode each of the operands along the X86Decoder and deactivate them. +This function is used after ^DecodeOperandString()^ which sets up the X86 Decoder for the instructions operands. +-------------------------------------------------------------------------------------------------------------------------*/ + +function DecodeOperands() +{ + //The Operands array is a string array in which the operand number is the element the decoded operand is positioned. + + var out = []; + + //This holds the decoded ModR/M byte from the "Decode_ModRM_SIB_Value()" function because the Register, and Address can decode differently. + + var ModRMByte = [ -1, //Mode is set negative one used to check if the ModR/M has been decoded. + 0, //The register value is decoded separately if used. + 0 //the base register for the address location. + ]; + + //If no Immediate operand is used then the Immediate register encoding forces an IMM8 for the register even if the immediate is not used. + + var IMM_Used = false; //This is set true for if any Immediate is read because the last Immediate byte is used as the register on the upper four bits. + + //If reg opcode is active. + + if( X86Decoder[0].Active ) + { + out[ X86Decoder[0].OpNum ] = DecodeRegValue( + ( RegExtend | ( Opcode & 0x07 ) ), //Register value. + X86Decoder[0].BySizeAttrubute, //By size attribute or not. + X86Decoder[0].Size //Size settings. + ); + } + + //If ModR/M Address is active. + + if( X86Decoder[1].Active ) + { + //Decode the ModR/M byte Address which can end up reading another byte for SIB address, and including displacements. + + if(X86Decoder[1].Type !== 0) + { + ModRMByte = Decode_ModRM_SIB_Value(); //Decode the ModR/M byte. + out[ X86Decoder[1].OpNum ] = Decode_ModRM_SIB_Address( + ModRMByte, //The ModR/M byte. + X86Decoder[1].BySizeAttrubute, //By size attribute or not. + X86Decoder[1].Size //Size settings. + ); + } + + //Else If the ModR/M type is 0 then it is a moffs address. + + else + { + var s=0, AddrsSize = 0; + if( X86Decoder[1].BySizeAttrubute ) + { + AddrsSize = ( Math.pow( 2, BitMode ) << 1 ); + s = GetOperandSize( X86Decoder[1].Size, true ) << 1; + } + else + { + AddrsSize = BitMode + 1; + s = X86Decoder[1].Size; + } + out[ X86Decoder[1].OpNum ] = PTR[ s ]; + out[ X86Decoder[1].OpNum ] += SegOverride + DecodeImmediate( 0, X86Decoder[1].BySizeAttrubute, AddrsSize ) + "]"; + } + } + + //Decode the Register value of the ModR/M byte. + + if( X86Decoder[2].Active ) + { + //If the ModR/M address is not used, and ModR/M byte was not previously decoded then decode it. + + if( ModRMByte[0] === -1 ){ ModRMByte = Decode_ModRM_SIB_Value(); } + + //Decode only the Register Section of the ModR/M byte values. + + out[ X86Decoder[2].OpNum ] = DecodeRegValue( + ( RegExtend | ( ModRMByte[1] & 0x07 ) ), //Register value. + X86Decoder[2].BySizeAttrubute, //By size attribute or not. + X86Decoder[2].Size //Size settings. + ); + } + + //First Immediate if used. + + if( X86Decoder[3].Active ) + { + var t = DecodeImmediate( + X86Decoder[3].Type, //Immediate input type. + X86Decoder[3].BySizeAttrubute, //By size attribute or not. + X86Decoder[3].Size //Size settings. + ); + + //Check if Instruction uses condition codes. + + if( Instruction.slice(-1) === "," ) + { + Instruction = Instruction.split(","); + + if( ( Extension >= 1 && Extension <= 2 && Opcode <= 0x400 && IMMValue < 0x20 ) || IMMValue < 0x08 ) + { + IMMValue |= ( ( ( Opcode > 0x400 ) & 1 ) << 5 ); //XOP adjust. + Instruction = Instruction[0] + ConditionCodes[ IMMValue ] + Instruction[1]; + } + else { Instruction = Instruction[0] + Instruction[1]; out[ X86Decoder[3].OpNum ] = t; } + } + + //else add the Immediate byte encoding to the decoded instruction operands. + + else { out[ X86Decoder[3].OpNum ] = t; } + + IMM_Used = true; //Immediate byte is read. + } + + //Second Immediate if used. + + if( X86Decoder[4].Active ) + { + out[ X86Decoder[4].OpNum ] = DecodeImmediate( + X86Decoder[4].Type, //Immediate input type. + X86Decoder[4].BySizeAttrubute, //By size attribute or not. + X86Decoder[4].Size //Size settings. + ); + } + + //Third Immediate if used. + + if( X86Decoder[5].Active ) + { + out[ X86Decoder[5].OpNum ] = DecodeImmediate( + X86Decoder[5].Type, //Immediate input type. + X86Decoder[5].BySizeAttrubute, //By size attribute or not. + X86Decoder[5].Size //Size settings. + ); + } + + //Vector register if used from an SIMD vector extended instruction. + + if( X86Decoder[6].Active ) + { + out[ X86Decoder[6].OpNum ] = DecodeRegValue( + VectorRegister, //Register value. + X86Decoder[6].BySizeAttrubute, //By size attribute or not. + X86Decoder[6].Size //Size settings. + ); + } + + //Immediate register encoding. + + if( X86Decoder[7].Active ) + { + if( !IMM_Used ) { DecodeImmediate(0, false, 0); } //forces IMM8 if no Immediate has been used. + out[ X86Decoder[7].OpNum ] = DecodeRegValue( + ( ( ( IMMValue & 0xF0 ) >> 4 ) | ( ( IMMValue & 0x08 ) << 1 ) ), //Register value. + X86Decoder[7].BySizeAttrubute, //By size attribute or not. + X86Decoder[7].Size //Size settings. + ); + } + + //------------------------------------------------------------------------------------------------------------------------- + //Iterate though the 4 possible Explicit operands The first operands that is not active ends the Iteration. + //------------------------------------------------------------------------------------------------------------------------- + + for( var i = 8; i < 11; i++ ) + { + //------------------------------------------------------------------------------------------------------------------------- + //if Active Type is used as which Explicit operand. + //------------------------------------------------------------------------------------------------------------------------- + + if( X86Decoder[i].Active ) + { + //General use registers value 0 though 4 there size can change by size setting but can not be extended or changed. + + if( X86Decoder[i].Type <= 3 ) + { + out[ X86Decoder[i].OpNum ] = DecodeRegValue( + X86Decoder[i].Type, //register by value for Explicit Registers A, C, D, B. + X86Decoder[i].BySizeAttrubute, //By size attribute or not. + X86Decoder[i].Size //Size attribute. + ); + } + + //RBX address Explicit Operands prefixes can extend the registers and change pointer size RegMode 0. + + else if( X86Decoder[i].Type === 4 ) + { + s = 3; //If 32, or 64 bit ModR/M. + if( ( BitMode === 0 && !AddressOverride ) || ( BitMode === 1 && AddressOverride ) ){ s = 7; } //If 16 bit ModR/M. + out[ X86Decoder[i].OpNum ] = Decode_ModRM_SIB_Address( + [ 0, 0, s ], //the RBX register only for the pointer. + X86Decoder[i].BySizeAttrubute, //By size attribute or not. + X86Decoder[i].Size //size attributes. + ); + } + + //source and destination address Explicit Operands prefixes can extend the registers and change pointer size. + + else if( X86Decoder[i].Type === 5 | X86Decoder[i].Type === 6 ) + { + s = 1; //If 32, or 64 bit ModR/M. + if( ( BitMode === 0 && !AddressOverride ) || ( BitMode === 1 & AddressOverride ) ) { s = -1; } //If 16 bit ModR/M. + out[ X86Decoder[i].OpNum ] = Decode_ModRM_SIB_Address( + [ 0, 0, ( X86Decoder[i].Type + s ) ], //source and destination pointer register by type value. + X86Decoder[i].BySizeAttrubute, //By size attribute or not. + X86Decoder[i].Size //size attributes. + ); + } + + //The ST only Operand, and FS, GS. + + else if( X86Decoder[i].Type >= 7 ) + { + out[ X86Decoder[i].OpNum ] = ["ST", "FS", "GS", "1", "3", "XMM0", "M10"][ ( X86Decoder[i].Type - 7 ) ]; + } + } + + //------------------------------------------------------------------------------------------------------------------------- + //else inactive end iteration. + //------------------------------------------------------------------------------------------------------------------------- + + else { break; } + + } + + /*------------------------------------------------------------------------------------------------------------------------- + If the EVEX vector extension is active the Mask, and Zero merge control are inserted into operand 0 (Destination operand). + -------------------------------------------------------------------------------------------------------------------------*/ + + //Mask Register is used if it is not 0 in value. + + if( MaskRegister !== 0 ){ out[0] += "{K" + MaskRegister + "}"; } + + //EVEX Zero Merge control. + + if( Extension === 2 && HInt_ZeroMerg ) { out[0] += "{Z}"; } + + //convert the operand array to a string and return it. + + InsOperands = out.toString(); +} + +/*------------------------------------------------------------------------------------------------------------------------- +The main Instruction decode function plugs everything in together for the steps required to decode a full X86 instruction. +-------------------------------------------------------------------------------------------------------------------------*/ + +function DecodeInstruction() +{ + //Reset Prefix adjustments, and vector setting adjustments. + + Reset(); + + var out = ""; //The instruction code that will be returned back from this function. + + //Record the starting position. + + InstructionPos = GetPosition(); + + //First read any opcodes (prefix) that act as adjustments to the main three operand decode functions ^DecodeRegValue()^, + //^Decode_ModRM_SIB_Address()^, and ^DecodeImmediate()^. + + DecodePrefixAdjustments(); + + //Only continue if an invalid opcode is not read by DecodePrefixAdjustments() for cpu bit mode setting. + + if( !InvalidOp ) + { + //Decode the instruction. + + DecodeOpcode(); + + //------------------------------------------------------------------------------------------------------------------------- + //Intel Larrabee CCCCC condition codes. + //------------------------------------------------------------------------------------------------------------------------- + + if( Opcode >= 0x700 && Instruction.slice(-1) === "," ) + { + Instruction = Instruction.split(","); + + //CMP conditions. + + if( Opcode >= 0x720 && Opcode <= 0x72F ) + { + IMMValue = VectorRegister >> 2; + + if( Float || ( IMMValue !== 3 && IMMValue !== 7 ) ) + { + Instruction = Instruction[0] + ConditionCodes[IMMValue] + Instruction[1]; + } + else { Instruction = Instruction[0] + Instruction[1]; } + + IMMValue = 0; VectorRegister &= 0x03; + } + + //Else High/Low. + + else + { + Instruction = Instruction[0] + ( ( ( VectorRegister & 1 ) === 1 ) ? "H" : "L" ) + Instruction[1]; + } + } + + //Setup the X86 Decoder for which operands the instruction uses. + + DecodeOperandString(); + + //Now only some instructions can vector extend, and that is only if the instruction is an SIMD Vector format instruction. + + if( !Vect && Extension > 0 && Opcode <= 0x400 ) { InvalidOp = true; } + + //The Width Bit setting must match the vector numbers size otherwise this create an invalid operation code in MVEX/EVEX unless the Width bit is ignored. + + if( Vect && !IgnoresWidthbit && Extension >= 2 ) + { + InvalidOp = ( ( SIMD & 1 ) !== ( WidthBit & 1 ) ); //Note use, and ignore width bit pastern EVEX. + } + if( Opcode >= 0x700 ) { WidthBit ^= IgnoresWidthbit; } //L1OM Width bit invert. + } + + //If the instruction is invalid then set the instruction to "???" + + if( InvalidOp ) + { + out = "???" //set the returned instruction to invalid + } + + //Else finish decoding the valid instruction. + + else + { + //Decode each operand along the Decoder array in order, and deactivate them. + + DecodeOperands(); + + /*------------------------------------------------------------------------------------------------------------------------- + 3DNow Instruction name is encoded by the next byte after the ModR/M, and Reg operands. + -------------------------------------------------------------------------------------------------------------------------*/ + + if( Opcode === 0x10F ) + { + //Lookup operation code. + + Instruction = M3DNow[ BinCode[CodePos] ]; NextByte(); + + //If Invalid instruction. + + if( Instruction === "" || Instruction == null ) + { + Instruction = "???"; InsOperands = ""; + } + } + + /*------------------------------------------------------------------------------------------------------------------------- + Synthetic virtual machine operation codes. + -------------------------------------------------------------------------------------------------------------------------*/ + + else if( Instruction === "SSS" ) + { + //The Next two bytes after the static opcode is the select synthetic virtual machine operation code. + + var Code1 = BinCode[CodePos]; NextByte(); + var Code2 = BinCode[CodePos]; NextByte(); + + //No operations exist past 4 in value for both bytes that combine to the operation code. + + if( Code1 >= 5 || Code2 >= 5 ) { Instruction = "???"; } + + //Else calculate the operation code in the 5x5 map. + + else + { + Instruction = MSynthetic[ ( Code1 * 5 ) + Code2 ]; + + //If Invalid instruction. + + if( Instruction === "" || Instruction == null ) + { + Instruction = "???"; + } + } + } + + //32/16 bit instructions 9A, and EA use Segment, and offset with Immediate format. + + if( Opcode === 0x9A || Opcode === 0xEA ) + { + var t = InsOperands.split(","); + InsOperands = t[1] + ":" +t[0]; + } + + //**Depending on the operation different prefixes replace others for HLE, or MPX, and branch prediction. + //if REP prefix, and LOCK prefix are used together, and the current decoded operation allows HLE XRELEASE. + + if(PrefixG1 === Mnemonics[0xF3] && PrefixG2 === Mnemonics[0xF0] && XRelease) + { + PrefixG1 = "XRELEASE"; //Then change REP to XRELEASE. + } + + //if REPNE prefix, and LOCK prefix are used together, and the current decoded operation allows HLE XACQUIRE. + + if(PrefixG1 === Mnemonics[0xF2] && PrefixG2 === Mnemonics[0xF0] && XAcquire) + { + PrefixG1 = "XACQUIRE"; //Then change REP to XACQUIRE + } + + //Depending on the order that the Repeat prefix, and Lock prefix is used flip Prefix G1, and G2 if HLEFlipG1G2 it is true. + + if((PrefixG1 === "XRELEASE" || PrefixG1 === "XACQUIRE") && HLEFlipG1G2) + { + t = PrefixG1; PrefixG1 = PrefixG2; PrefixG2 = t; + } + + //if HT is active then it is a jump instruction check and adjust for the HT,and HNT prefix. + + if(HT) + { + if (SegOverride === Mnemonics[0x2E]) + { + PrefixG1 = "HNT"; + } + else if (SegOverride === Mnemonics[0x3E]) + { + PrefixG1 = "HT"; + } + } + + //else if Prefix is REPNE switch it to BND if operation is a MPX instruction. + + if(PrefixG1 === Mnemonics[0xF2] && BND) + { + PrefixG1 = "BND"; + } + + //Before the Instruction is put together check the length of the instruction if it is longer than 15 bytes the instruction is undefined. + + if ( InstructionHex.length > 30 ) + { + //Calculate how many bytes over. + + var Dif32 = ( ( InstructionHex.length - 30 ) >> 1 ); + + //Limit the instruction hex output to 15 bytes. + + InstructionHex = InstructionHex.substring( 0, 30 ); + + //Calculate the Difference between the Disassembler current position. + + Dif32 = Pos32 - Dif32; + + //Convert Dif to unsignified numbers. + + if( Dif32 < 0 ) { Dif32 += 0x100000000; } + + //Convert to strings. + + for (var S32 = Dif32.toString(16) ; S32.length < 8; S32 = "0" + S32); + for (var S64 = Pos64.toString(16) ; S64.length < 8; S64 = "0" + S64); + + //Go to the Calculated address right after the Instruction UD. + + GotoPosition( S64 + S32 ); + + //Set prefixes, and operands to empty strings, and set Instruction to UD. + + PrefixG1 = "";PrefixG2 = ""; Instruction = "???"; InsOperands = ""; + } + + //Put the Instruction sequence together. + + out = PrefixG1 + " " + PrefixG2 + " " + Instruction + " " + InsOperands; + + //Remove any trailing spaces because of unused prefixes. + + out = out.replace(/^[ ]+|[ ]+$/g,''); + + //Add error suppression if used. + + if( Opcode >= 0x700 || RoundMode !== 0 ) + { + out += RoundModes[ RoundMode ]; + } + + //Return the instruction. + } + + return( out ); +} + +/*------------------------------------------------------------------------------------------------------------------------- +This function Resets the Decoder in case of error, or an full instruction has been decoded. +-------------------------------------------------------------------------------------------------------------------------*/ + +function Reset() +{ + //Reset Opcode, and Size attribute selector. + + Opcode = 0; SizeAttrSelect = 1; + + //Reset Operands and instruction. + + Instruction = ""; InsOperands = ""; + + //Reset ModR/M. + + RexActive = 0; RegExtend = 0; BaseExtend = 0; IndexExtend = 0; + SegOverride = "["; AddressOverride = false; FarPointer = 0; + + //Reset Vector extensions controls. + + Extension = 0; SIMD = 0; Vect = false; ConversionMode = 0; WidthBit = false; + VectorRegister = 0; MaskRegister = 0; HInt_ZeroMerg = false; RoundMode = 0x00; + + //Reset vector format settings. + + IgnoresWidthbit = false; VSIB = false; RoundingSetting = 0; + Swizzle = false; Up = false; Float = false; VectS = 0x00; + + //Reset IMMValue used for Imm register encoding, and Condition codes. + + IMMValue = 0; + + //Reset instruction Prefixes. + + PrefixG1 = "", PrefixG2 = ""; + XRelease = false; XAcquire = false; HLEFlipG1G2 = false; + HT = false; + BND = false; + + //Reset Invalid operation code. + + InvalidOp = false; + + //Reset instruction hex because it is used to check if the instruction is longer than 15 bytes which is impossible for the X86 Decoder Circuit. + + InstructionHex = ""; + + //Deactivate all operands along the X86Decoder. + + for( var i = 0; i < X86Decoder.length; X86Decoder[i++].Deactivate() ); +} + +/*------------------------------------------------------------------------------------------------------------------------- +do an linear disassemble. +-------------------------------------------------------------------------------------------------------------------------*/ + +export function LDisassemble() +{ + var Instruction = ""; //Stores the Decoded instruction. + var Out = ""; //The Disassemble output + + //Disassemble binary code using an linear pass. + + var len = BinCode.length; + + //Backup the base address. + + var BPos64 = Pos64, BPos32 = Pos32; + + while( CodePos < len ) + { + Instruction = DecodeInstruction(); + + //Add the 64 bit address of the output if ShowInstructionPos decoding is active. + + if( ShowInstructionPos ) + { + Out += InstructionPos + " "; + } + + //Show Each byte that was read to decode the instruction if ShowInstructionHex decoding is active. + + if(ShowInstructionHex) + { + InstructionHex = InstructionHex.toUpperCase(); + for(; InstructionHex.length < 32; InstructionHex = InstructionHex + " " ); + Out += InstructionHex + ""; + } + + //Put the decoded instruction into the output and make a new line. + + Out += Instruction + "\r\n"; + + //Reset instruction Pos and Hex. + + InstructionPos = ""; InstructionHex = ""; + } + + CodePos = 0; //Reset the Code position + Pos32 = BPos32; Pos64 = BPos64; //Reset Base address. + + //return the decoded binary code + + return(Out); + +} + +//////////////////////////////////////////////////////////////////////////////////////////////// + +/* + * The following code has been added to expose public methods for use in CyberChef + */ + +export function setBitMode (val) { + BitMode = val; +}; +export function setShowInstructionHex (val) { + ShowInstructionHex = val; +}; +export function setShowInstructionPos (val) { + ShowInstructionPos = val; +}; + diff --git a/plugins/srktoolbox/src/core/vendor/gost/gostCipher.mjs b/plugins/srktoolbox/src/core/vendor/gost/gostCipher.mjs new file mode 100644 index 00000000..8505fd34 --- /dev/null +++ b/plugins/srktoolbox/src/core/vendor/gost/gostCipher.mjs @@ -0,0 +1,2259 @@ +/** + * GOST 28147-89/GOST R 34.12-2015/GOST R 32.13-2015 Encryption Algorithm + * 1.76 + * 2014-2016, Rudolf Nickolaev. All rights reserved. + * + * Exported for CyberChef by mshwed [m@ttshwed.com] + */ + +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +import GostRandom from './gostRandom.mjs'; + +import crypto from 'crypto' + +/* +* Initial parameters and common algortithms of GOST 28147-89 +* +* http://tools.ietf.org/html/rfc5830 +* +*/ // + +var root = {}; +var rootCrypto = crypto; +var CryptoOperationData = ArrayBuffer; +var SyntaxError = Error, + DataError = Error, + NotSupportedError = Error; +/* +* Check supported +* This implementation support only Little Endian arhitecture +*/ + +var littleEndian = (function () { + var buffer = new CryptoOperationData(2); + new DataView(buffer).setInt16(0, 256, true); + return new Int16Array(buffer)[0] === 256; +})(); + +// Default initial vector +var defaultIV = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]); + +// Predefined sBox collection +var sBoxes = { + 'E-TEST': [ + 0x4, 0x2, 0xF, 0x5, 0x9, 0x1, 0x0, 0x8, 0xE, 0x3, 0xB, 0xC, 0xD, 0x7, 0xA, 0x6, + 0xC, 0x9, 0xF, 0xE, 0x8, 0x1, 0x3, 0xA, 0x2, 0x7, 0x4, 0xD, 0x6, 0x0, 0xB, 0x5, + 0xD, 0x8, 0xE, 0xC, 0x7, 0x3, 0x9, 0xA, 0x1, 0x5, 0x2, 0x4, 0x6, 0xF, 0x0, 0xB, + 0xE, 0x9, 0xB, 0x2, 0x5, 0xF, 0x7, 0x1, 0x0, 0xD, 0xC, 0x6, 0xA, 0x4, 0x3, 0x8, + 0x3, 0xE, 0x5, 0x9, 0x6, 0x8, 0x0, 0xD, 0xA, 0xB, 0x7, 0xC, 0x2, 0x1, 0xF, 0x4, + 0x8, 0xF, 0x6, 0xB, 0x1, 0x9, 0xC, 0x5, 0xD, 0x3, 0x7, 0xA, 0x0, 0xE, 0x2, 0x4, + 0x9, 0xB, 0xC, 0x0, 0x3, 0x6, 0x7, 0x5, 0x4, 0x8, 0xE, 0xF, 0x1, 0xA, 0x2, 0xD, + 0xC, 0x6, 0x5, 0x2, 0xB, 0x0, 0x9, 0xD, 0x3, 0xE, 0x7, 0xA, 0xF, 0x4, 0x1, 0x8 + ], + 'E-A': [ + 0x9, 0x6, 0x3, 0x2, 0x8, 0xB, 0x1, 0x7, 0xA, 0x4, 0xE, 0xF, 0xC, 0x0, 0xD, 0x5, + 0x3, 0x7, 0xE, 0x9, 0x8, 0xA, 0xF, 0x0, 0x5, 0x2, 0x6, 0xC, 0xB, 0x4, 0xD, 0x1, + 0xE, 0x4, 0x6, 0x2, 0xB, 0x3, 0xD, 0x8, 0xC, 0xF, 0x5, 0xA, 0x0, 0x7, 0x1, 0x9, + 0xE, 0x7, 0xA, 0xC, 0xD, 0x1, 0x3, 0x9, 0x0, 0x2, 0xB, 0x4, 0xF, 0x8, 0x5, 0x6, + 0xB, 0x5, 0x1, 0x9, 0x8, 0xD, 0xF, 0x0, 0xE, 0x4, 0x2, 0x3, 0xC, 0x7, 0xA, 0x6, + 0x3, 0xA, 0xD, 0xC, 0x1, 0x2, 0x0, 0xB, 0x7, 0x5, 0x9, 0x4, 0x8, 0xF, 0xE, 0x6, + 0x1, 0xD, 0x2, 0x9, 0x7, 0xA, 0x6, 0x0, 0x8, 0xC, 0x4, 0x5, 0xF, 0x3, 0xB, 0xE, + 0xB, 0xA, 0xF, 0x5, 0x0, 0xC, 0xE, 0x8, 0x6, 0x2, 0x3, 0x9, 0x1, 0x7, 0xD, 0x4 + ], + 'E-B': [ + 0x8, 0x4, 0xB, 0x1, 0x3, 0x5, 0x0, 0x9, 0x2, 0xE, 0xA, 0xC, 0xD, 0x6, 0x7, 0xF, + 0x0, 0x1, 0x2, 0xA, 0x4, 0xD, 0x5, 0xC, 0x9, 0x7, 0x3, 0xF, 0xB, 0x8, 0x6, 0xE, + 0xE, 0xC, 0x0, 0xA, 0x9, 0x2, 0xD, 0xB, 0x7, 0x5, 0x8, 0xF, 0x3, 0x6, 0x1, 0x4, + 0x7, 0x5, 0x0, 0xD, 0xB, 0x6, 0x1, 0x2, 0x3, 0xA, 0xC, 0xF, 0x4, 0xE, 0x9, 0x8, + 0x2, 0x7, 0xC, 0xF, 0x9, 0x5, 0xA, 0xB, 0x1, 0x4, 0x0, 0xD, 0x6, 0x8, 0xE, 0x3, + 0x8, 0x3, 0x2, 0x6, 0x4, 0xD, 0xE, 0xB, 0xC, 0x1, 0x7, 0xF, 0xA, 0x0, 0x9, 0x5, + 0x5, 0x2, 0xA, 0xB, 0x9, 0x1, 0xC, 0x3, 0x7, 0x4, 0xD, 0x0, 0x6, 0xF, 0x8, 0xE, + 0x0, 0x4, 0xB, 0xE, 0x8, 0x3, 0x7, 0x1, 0xA, 0x2, 0x9, 0x6, 0xF, 0xD, 0x5, 0xC + ], + 'E-C': [ + 0x1, 0xB, 0xC, 0x2, 0x9, 0xD, 0x0, 0xF, 0x4, 0x5, 0x8, 0xE, 0xA, 0x7, 0x6, 0x3, + 0x0, 0x1, 0x7, 0xD, 0xB, 0x4, 0x5, 0x2, 0x8, 0xE, 0xF, 0xC, 0x9, 0xA, 0x6, 0x3, + 0x8, 0x2, 0x5, 0x0, 0x4, 0x9, 0xF, 0xA, 0x3, 0x7, 0xC, 0xD, 0x6, 0xE, 0x1, 0xB, + 0x3, 0x6, 0x0, 0x1, 0x5, 0xD, 0xA, 0x8, 0xB, 0x2, 0x9, 0x7, 0xE, 0xF, 0xC, 0x4, + 0x8, 0xD, 0xB, 0x0, 0x4, 0x5, 0x1, 0x2, 0x9, 0x3, 0xC, 0xE, 0x6, 0xF, 0xA, 0x7, + 0xC, 0x9, 0xB, 0x1, 0x8, 0xE, 0x2, 0x4, 0x7, 0x3, 0x6, 0x5, 0xA, 0x0, 0xF, 0xD, + 0xA, 0x9, 0x6, 0x8, 0xD, 0xE, 0x2, 0x0, 0xF, 0x3, 0x5, 0xB, 0x4, 0x1, 0xC, 0x7, + 0x7, 0x4, 0x0, 0x5, 0xA, 0x2, 0xF, 0xE, 0xC, 0x6, 0x1, 0xB, 0xD, 0x9, 0x3, 0x8 + ], + 'E-D': [ + 0xF, 0xC, 0x2, 0xA, 0x6, 0x4, 0x5, 0x0, 0x7, 0x9, 0xE, 0xD, 0x1, 0xB, 0x8, 0x3, + 0xB, 0x6, 0x3, 0x4, 0xC, 0xF, 0xE, 0x2, 0x7, 0xD, 0x8, 0x0, 0x5, 0xA, 0x9, 0x1, + 0x1, 0xC, 0xB, 0x0, 0xF, 0xE, 0x6, 0x5, 0xA, 0xD, 0x4, 0x8, 0x9, 0x3, 0x7, 0x2, + 0x1, 0x5, 0xE, 0xC, 0xA, 0x7, 0x0, 0xD, 0x6, 0x2, 0xB, 0x4, 0x9, 0x3, 0xF, 0x8, + 0x0, 0xC, 0x8, 0x9, 0xD, 0x2, 0xA, 0xB, 0x7, 0x3, 0x6, 0x5, 0x4, 0xE, 0xF, 0x1, + 0x8, 0x0, 0xF, 0x3, 0x2, 0x5, 0xE, 0xB, 0x1, 0xA, 0x4, 0x7, 0xC, 0x9, 0xD, 0x6, + 0x3, 0x0, 0x6, 0xF, 0x1, 0xE, 0x9, 0x2, 0xD, 0x8, 0xC, 0x4, 0xB, 0xA, 0x5, 0x7, + 0x1, 0xA, 0x6, 0x8, 0xF, 0xB, 0x0, 0x4, 0xC, 0x3, 0x5, 0x9, 0x7, 0xD, 0x2, 0xE + ], + 'E-SC': [ + 0x3, 0x6, 0x1, 0x0, 0x5, 0x7, 0xd, 0x9, 0x4, 0xb, 0x8, 0xc, 0xe, 0xf, 0x2, 0xa, + 0x7, 0x1, 0x5, 0x2, 0x8, 0xb, 0x9, 0xc, 0xd, 0x0, 0x3, 0xa, 0xf, 0xe, 0x4, 0x6, + 0xf, 0x1, 0x4, 0x6, 0xc, 0x8, 0x9, 0x2, 0xe, 0x3, 0x7, 0xa, 0xb, 0xd, 0x5, 0x0, + 0x3, 0x4, 0xf, 0xc, 0x5, 0x9, 0xe, 0x0, 0x6, 0x8, 0x7, 0xa, 0x1, 0xb, 0xd, 0x2, + 0x6, 0x9, 0x0, 0x7, 0xb, 0x8, 0x4, 0xc, 0x2, 0xe, 0xa, 0xf, 0x1, 0xd, 0x5, 0x3, + 0x6, 0x1, 0x2, 0xf, 0x0, 0xb, 0x9, 0xc, 0x7, 0xd, 0xa, 0x5, 0x8, 0x4, 0xe, 0x3, + 0x0, 0x2, 0xe, 0xc, 0x9, 0x1, 0x4, 0x7, 0x3, 0xf, 0x6, 0x8, 0xa, 0xd, 0xb, 0x5, + 0x5, 0x2, 0xb, 0x8, 0x4, 0xc, 0x7, 0x1, 0xa, 0x6, 0xe, 0x0, 0x9, 0x3, 0xd, 0xf + ], + 'E-Z': [// This is default S-box in according to draft of new standard + 0xc, 0x4, 0x6, 0x2, 0xa, 0x5, 0xb, 0x9, 0xe, 0x8, 0xd, 0x7, 0x0, 0x3, 0xf, 0x1, + 0x6, 0x8, 0x2, 0x3, 0x9, 0xa, 0x5, 0xc, 0x1, 0xe, 0x4, 0x7, 0xb, 0xd, 0x0, 0xf, + 0xb, 0x3, 0x5, 0x8, 0x2, 0xf, 0xa, 0xd, 0xe, 0x1, 0x7, 0x4, 0xc, 0x9, 0x6, 0x0, + 0xc, 0x8, 0x2, 0x1, 0xd, 0x4, 0xf, 0x6, 0x7, 0x0, 0xa, 0x5, 0x3, 0xe, 0x9, 0xb, + 0x7, 0xf, 0x5, 0xa, 0x8, 0x1, 0x6, 0xd, 0x0, 0x9, 0x3, 0xe, 0xb, 0x4, 0x2, 0xc, + 0x5, 0xd, 0xf, 0x6, 0x9, 0x2, 0xc, 0xa, 0xb, 0x7, 0x8, 0x1, 0x4, 0x3, 0xe, 0x0, + 0x8, 0xe, 0x2, 0x5, 0x6, 0x9, 0x1, 0xc, 0xf, 0x4, 0xb, 0x0, 0xd, 0xa, 0x3, 0x7, + 0x1, 0x7, 0xe, 0xd, 0x0, 0x5, 0x8, 0x3, 0x4, 0xf, 0xa, 0x6, 0x9, 0xc, 0xb, 0x2 + ], + //S-box for digest + 'D-TEST': [ + 0x4, 0xA, 0x9, 0x2, 0xD, 0x8, 0x0, 0xE, 0x6, 0xB, 0x1, 0xC, 0x7, 0xF, 0x5, 0x3, + 0xE, 0xB, 0x4, 0xC, 0x6, 0xD, 0xF, 0xA, 0x2, 0x3, 0x8, 0x1, 0x0, 0x7, 0x5, 0x9, + 0x5, 0x8, 0x1, 0xD, 0xA, 0x3, 0x4, 0x2, 0xE, 0xF, 0xC, 0x7, 0x6, 0x0, 0x9, 0xB, + 0x7, 0xD, 0xA, 0x1, 0x0, 0x8, 0x9, 0xF, 0xE, 0x4, 0x6, 0xC, 0xB, 0x2, 0x5, 0x3, + 0x6, 0xC, 0x7, 0x1, 0x5, 0xF, 0xD, 0x8, 0x4, 0xA, 0x9, 0xE, 0x0, 0x3, 0xB, 0x2, + 0x4, 0xB, 0xA, 0x0, 0x7, 0x2, 0x1, 0xD, 0x3, 0x6, 0x8, 0x5, 0x9, 0xC, 0xF, 0xE, + 0xD, 0xB, 0x4, 0x1, 0x3, 0xF, 0x5, 0x9, 0x0, 0xA, 0xE, 0x7, 0x6, 0x8, 0x2, 0xC, + 0x1, 0xF, 0xD, 0x0, 0x5, 0x7, 0xA, 0x4, 0x9, 0x2, 0x3, 0xE, 0x6, 0xB, 0x8, 0xC + ], + 'D-A': [ + 0xA, 0x4, 0x5, 0x6, 0x8, 0x1, 0x3, 0x7, 0xD, 0xC, 0xE, 0x0, 0x9, 0x2, 0xB, 0xF, + 0x5, 0xF, 0x4, 0x0, 0x2, 0xD, 0xB, 0x9, 0x1, 0x7, 0x6, 0x3, 0xC, 0xE, 0xA, 0x8, + 0x7, 0xF, 0xC, 0xE, 0x9, 0x4, 0x1, 0x0, 0x3, 0xB, 0x5, 0x2, 0x6, 0xA, 0x8, 0xD, + 0x4, 0xA, 0x7, 0xC, 0x0, 0xF, 0x2, 0x8, 0xE, 0x1, 0x6, 0x5, 0xD, 0xB, 0x9, 0x3, + 0x7, 0x6, 0x4, 0xB, 0x9, 0xC, 0x2, 0xA, 0x1, 0x8, 0x0, 0xE, 0xF, 0xD, 0x3, 0x5, + 0x7, 0x6, 0x2, 0x4, 0xD, 0x9, 0xF, 0x0, 0xA, 0x1, 0x5, 0xB, 0x8, 0xE, 0xC, 0x3, + 0xD, 0xE, 0x4, 0x1, 0x7, 0x0, 0x5, 0xA, 0x3, 0xC, 0x8, 0xF, 0x6, 0x2, 0x9, 0xB, + 0x1, 0x3, 0xA, 0x9, 0x5, 0xB, 0x4, 0xF, 0x8, 0x6, 0x7, 0xE, 0xD, 0x0, 0x2, 0xC + ], + 'D-SC': [ + 0xb, 0xd, 0x7, 0x0, 0x5, 0x4, 0x1, 0xf, 0x9, 0xe, 0x6, 0xa, 0x3, 0xc, 0x8, 0x2, + 0x1, 0x2, 0x7, 0x9, 0xd, 0xb, 0xf, 0x8, 0xe, 0xc, 0x4, 0x0, 0x5, 0x6, 0xa, 0x3, + 0x5, 0x1, 0xd, 0x3, 0xf, 0x6, 0xc, 0x7, 0x9, 0x8, 0xb, 0x2, 0x4, 0xe, 0x0, 0xa, + 0xd, 0x1, 0xb, 0x4, 0x9, 0xc, 0xe, 0x0, 0x7, 0x5, 0x8, 0xf, 0x6, 0x2, 0xa, 0x3, + 0x2, 0xd, 0xa, 0xf, 0x9, 0xb, 0x3, 0x7, 0x8, 0xc, 0x5, 0xe, 0x6, 0x0, 0x1, 0x4, + 0x0, 0x4, 0x6, 0xc, 0x5, 0x3, 0x8, 0xd, 0xa, 0xb, 0xf, 0x2, 0x1, 0x9, 0x7, 0xe, + 0x1, 0x3, 0xc, 0x8, 0xa, 0x6, 0xb, 0x0, 0x2, 0xe, 0x7, 0x9, 0xf, 0x4, 0x5, 0xd, + 0xa, 0xb, 0x6, 0x0, 0x1, 0x3, 0x4, 0x7, 0xe, 0xd, 0x5, 0xf, 0x8, 0x2, 0x9, 0xc + ] +}; + +var C = new Uint8Array([ + 0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23, + 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4, + 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12, + 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B +]); + +function signed(x) { + return x >= 0x80000000 ? x - 0x100000000 : x; +} + +function unsigned(x) { + return x < 0 ? x + 0x100000000 : x; +} + +// Set random values into Uint8Arry +// Random generator +function randomSeed(e) { + GostRandom = GostRandom || root.GostRandom; + var randomSource = GostRandom ? new (GostRandom || root.GostRandom) : rootCrypto; + if (randomSource.getRandomValues) + randomSource.getRandomValues(e); + else + throw new NotSupportedError('Random generator not found'); +} + +// Get buffer +function buffer(d) { + if (d instanceof CryptoOperationData) + return d; + else if (d && d?.buffer instanceof CryptoOperationData) + return d.byteOffset === 0 && d.byteLength === d.buffer.byteLength ? + d.buffer : new Uint8Array(new Uint8Array(d, d.byteOffset, d.byteLength)).buffer; + else + throw new DataError('CryptoOperationData required'); +} + +// Get byte array +function byteArray(d) { + return new Uint8Array(buffer(d)); +} + +// Clone byte array +function cloneArray(d) { + return new Uint8Array(byteArray(d)); +} + + +// Get int32 array +function intArray(d) { + return new Int32Array(buffer(d)); +} + +// Swap bytes for version 2015 +function swap32(b) { + return ((b & 0xff) << 24) + | ((b & 0xff00) << 8) + | ((b >> 8) & 0xff00) + | ((b >> 24) & 0xff); +} + +// + +/* + * Initial parameters and common algortithms of GOST R 34.12-15 + * Algorithm "Kuznechik" 128bit + * + */ // + +// Default initial vector +var defaultIV128 = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); + +// Mult table for R function +var multTable = (function () { + + // Multiply two numbers in the GF(2^8) finite field defined + // by the polynomial x^8 + x^7 + x^6 + x + 1 = 0 */ + function gmul(a, b) { + var p = 0, counter, carry; + for (counter = 0; counter < 8; counter++) { + if (b & 1) + p ^= a; + carry = a & 0x80; // detect if x^8 term is about to be generated + a = (a << 1) & 0xff; + if (carry) + a ^= 0xc3; // replace x^8 with x^7 + x^6 + x + 1 + b >>= 1; + } + return p & 0xff; + } + + // It is required only this values for R function + // 0 1 2 3 4 5 6 7 + var x = [1, 16, 32, 133, 148, 192, 194, 251]; + var m = []; + for (var i = 0; i < 8; i++) { + m[i] = []; + for (var j = 0; j < 256; j++) + m[i][j] = gmul(x[i], j); + } + return m; +})(); + +// 148, 32, 133, 16, 194, 192, 1, 251, 1, 192, 194, 16, 133, 32, 148, 1 +var kB = [4, 2, 3, 1, 6, 5, 0, 7, 0, 5, 6, 1, 3, 2, 4, 0]; + +// R - function +function funcR(d) { + var sum = 0; + for (var i = 0; i < 16; i++) + sum ^= multTable[kB[i]][d[i]]; + + for (var i = 16; i > 0; --i) + d[i] = d[i - 1]; + d[0] = sum; +} + +function funcReverseR(d) { + var tmp = d[0]; + for (var i = 0; i < 15; i++) + d[i] = d[i + 1]; + d[15] = tmp; + + var sum = 0; + for (i = 0; i < 16; i++) + sum ^= multTable[kB[i]][d[i]]; + d[15] = sum; +} + +// Nonlinear transformation +var kPi = [ + 252, 238, 221, 17, 207, 110, 49, 22, 251, 196, 250, 218, 35, 197, 4, 77, + 233, 119, 240, 219, 147, 46, 153, 186, 23, 54, 241, 187, 20, 205, 95, 193, + 249, 24, 101, 90, 226, 92, 239, 33, 129, 28, 60, 66, 139, 1, 142, 79, + 5, 132, 2, 174, 227, 106, 143, 160, 6, 11, 237, 152, 127, 212, 211, 31, + 235, 52, 44, 81, 234, 200, 72, 171, 242, 42, 104, 162, 253, 58, 206, 204, + 181, 112, 14, 86, 8, 12, 118, 18, 191, 114, 19, 71, 156, 183, 93, 135, + 21, 161, 150, 41, 16, 123, 154, 199, 243, 145, 120, 111, 157, 158, 178, 177, + 50, 117, 25, 61, 255, 53, 138, 126, 109, 84, 198, 128, 195, 189, 13, 87, + 223, 245, 36, 169, 62, 168, 67, 201, 215, 121, 214, 246, 124, 34, 185, 3, + 224, 15, 236, 222, 122, 148, 176, 188, 220, 232, 40, 80, 78, 51, 10, 74, + 167, 151, 96, 115, 30, 0, 98, 68, 26, 184, 56, 130, 100, 159, 38, 65, + 173, 69, 70, 146, 39, 94, 85, 47, 140, 163, 165, 125, 105, 213, 149, 59, + 7, 88, 179, 64, 134, 172, 29, 247, 48, 55, 107, 228, 136, 217, 231, 137, + 225, 27, 131, 73, 76, 63, 248, 254, 141, 83, 170, 144, 202, 216, 133, 97, + 32, 113, 103, 164, 45, 43, 9, 91, 203, 155, 37, 208, 190, 229, 108, 82, + 89, 166, 116, 210, 230, 244, 180, 192, 209, 102, 175, 194, 57, 75, 99, 182 +]; + +var kReversePi = (function () { + var m = []; + for (var i = 0, n = kPi.length; i < n; i++) + m[kPi[i]] = i; + return m; +})(); + +function funcS(d) { + for (var i = 0; i < 16; ++i) + d[i] = kPi[d[i]]; +} + +function funcReverseS(d) { + for (var i = 0; i < 16; ++i) + d[i] = kReversePi[d[i]]; +} + +function funcX(a, b) { + for (var i = 0; i < 16; ++i) + a[i] ^= b[i]; +} + +function funcL(d) { + for (var i = 0; i < 16; ++i) + funcR(d); +} + +function funcReverseL(d) { + for (var i = 0; i < 16; ++i) + funcReverseR(d); +} + +function funcLSX(a, b) { + funcX(a, b); + funcS(a); + funcL(a); +} + +function funcReverseLSX(a, b) { + funcX(a, b); + funcReverseL(a); + funcReverseS(a); +} + +function funcF(inputKey, inputKeySecond, iterationConst) { + var tmp = new Uint8Array(inputKey); + funcLSX(inputKey, iterationConst); + funcX(inputKey, inputKeySecond); + inputKeySecond.set(tmp); +} + +function funcC(number, d) { + for (var i = 0; i < 15; i++) + d[i] = 0; + d[15] = number; + funcL(d); +} + +// + +/** + * Key schedule for GOST R 34.12-15 128bits + * + * @memberOf GostCipher + * @private + * @instance + * @method keySchedule + * @param {type} k + * @returns {Uint8Array} + */ +function keySchedule128(k) // +{ + var keys = new Uint8Array(160), c = new Uint8Array(16); + keys.set(byteArray(k)); + for (var j = 0; j < 4; j++) { + var j0 = 32 * j, j1 = 32 * (j + 1); + keys.set(new Uint8Array(keys.buffer, j0, 32), j1); + for (var i = 1; i < 9; i++) { + funcC(j * 8 + i, c); + funcF(new Uint8Array(keys.buffer, j1, 16), + new Uint8Array(keys.buffer, j1 + 16, 16), c); + } + } + return keys; +} // + +/** + * GOST R 34.12-15 128 bits encrypt/decrypt process + * + * @memberOf GostCipher + * @private + * @instance + * @method round + * @param {Uint8Array} k Scheduled key + * @param {Uint8Array} d Data + * @param {number} ofs Offsec + * @param {number} e true - decrypt + */ +function process128(k, d, ofs, e) // +{ + ofs = ofs || d.byteOffset; + var r = new Uint8Array(d.buffer, ofs, 16); + if (e) { + for (var i = 0; i < 9; i++) + funcReverseLSX(r, new Uint8Array(k.buffer, (9 - i) * 16, 16)); + + funcX(r, new Uint8Array(k.buffer, 0, 16)); + } else { + for (var i = 0; i < 9; i++) + funcLSX(r, new Uint8Array(k.buffer, 16 * i, 16)); + + funcX(r, new Uint8Array(k.buffer, 16 * 9, 16)); + } +} // + +/** + * One GOST encryption round + * + * @memberOf GostCipher + * @private + * @instance + * @method round + * @param {Int8Array} S sBox + * @param {Int32Array} m 2x32 bits cipher block + * @param {Int32Array} k 32 bits key[i] + */ +function round(S, m, k) // +{ + var cm = (m[0] + k) & 0xffffffff; + + var om = S[ 0 + ((cm >> (0 * 4)) & 0xF)] << (0 * 4); + om |= S[ 16 + ((cm >> (1 * 4)) & 0xF)] << (1 * 4); + om |= S[ 32 + ((cm >> (2 * 4)) & 0xF)] << (2 * 4); + om |= S[ 48 + ((cm >> (3 * 4)) & 0xF)] << (3 * 4); + om |= S[ 64 + ((cm >> (4 * 4)) & 0xF)] << (4 * 4); + om |= S[ 80 + ((cm >> (5 * 4)) & 0xF)] << (5 * 4); + om |= S[ 96 + ((cm >> (6 * 4)) & 0xF)] << (6 * 4); + om |= S[112 + ((cm >> (7 * 4)) & 0xF)] << (7 * 4); + cm = om << 11 | om >>> (32 - 11); + + cm ^= m[1]; + m[1] = m[0]; + m[0] = cm; + +} // + +/** + * Process encrypt/decrypt block with key K using GOST 28147-89 + * + * @memberOf GostCipher + * @private + * @instance + * @method process + * @param k {Int32Array} 8x32 bits key + * @param d {Int32Array} 8x8 bits cipher block + * @param ofs {number} offset + */ +function process89(k, d, ofs) // +{ + ofs = ofs || d.byteOffset; + var s = this.sBox, + m = new Int32Array(d.buffer, ofs, 2); + + for (var i = 0; i < 32; i++) + round(s, m, k[i]); + + var r = m[0]; + m[0] = m[1]; + m[1] = r; +} // + +/** + * Process encrypt/decrypt block with key K using GOST R 34.12-15 64bit block + * + * @memberOf GostCipher + * @private + * @instance + * @method process + * @param k {Int32Array} 8x32 bits key + * @param d {Int32Array} 8x8 bits cipher block + * @param ofs {number} offset + */ +function process15(k, d, ofs) // +{ + ofs = ofs || d.byteOffset; + var s = this.sBox, + m = new Int32Array(d.buffer, ofs, 2), + r = swap32(m[0]); + m[0] = swap32(m[1]); + m[1] = r; + + for (var i = 0; i < 32; i++) + round(s, m, k[i]); + + m[0] = swap32(m[0]); + m[1] = swap32(m[1]); +} // + +/** + * Key keySchedule algorithm for GOST 28147-89 64bit cipher + * + * @memberOf GostCipher + * @private + * @instance + * @method process + * @param k {Uint8Array} 8 bit key array + * @param e {boolean} true - decrypt + * @returns {Int32Array} keyScheduled 32-bit key + */ +function keySchedule89(k, e) // +{ + var sch = new Int32Array(32), + key = new Int32Array(buffer(k)); + + for (var i = 0; i < 8; i++) + sch[i] = key[i]; + + if (e) { + for (var i = 0; i < 8; i++) + sch[i + 8] = sch[7 - i]; + + for (var i = 0; i < 8; i++) + sch[i + 16] = sch[7 - i]; + } else { + for (var i = 0; i < 8; i++) + sch[i + 8] = sch[i]; + + for (var i = 0; i < 8; i++) + sch[i + 16] = sch[i]; + } + + for (var i = 0; i < 8; i++) + sch[i + 24] = sch[7 - i]; + + return sch; +} // + +/** + * Key keySchedule algorithm for GOST R 34.12-15 64bit cipher + * + * @memberOf GostCipher + * @private + * @instance + * @method process + * @param k {Uint8Array} 8 bit key array + * @param e {boolean} true - decrypt + * @returns {Int32Array} keyScheduled 32-bit key + */ +function keySchedule15(k, e) // +{ + var sch = new Int32Array(32), + key = new Int32Array(buffer(k)); + + for (var i = 0; i < 8; i++) + sch[i] = swap32(key[i]); + + if (e) { + for (var i = 0; i < 8; i++) + sch[i + 8] = sch[7 - i]; + + for (var i = 0; i < 8; i++) + sch[i + 16] = sch[7 - i]; + } else { + for (var i = 0; i < 8; i++) + sch[i + 8] = sch[i]; + + for (var i = 0; i < 8; i++) + sch[i + 16] = sch[i]; + } + + for (var i = 0; i < 8; i++) + sch[i + 24] = sch[7 - i]; + + return sch; +} // + +/** + * Key schedule for RC2 + * + * https://tools.ietf.org/html/rfc2268 + * + * @memberOf GostCipher + * @private + * @instance + * @method keySchedule + * @param {Uint8Array} k + * @returns {Uint16Array} + */ +var keyScheduleRC2 = (function () // +{ + // an array of "random" bytes based on the digits of PI = 3.14159... + var PITABLE = new Uint8Array([ + 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, + 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, + 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, + 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, + 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, + 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, + 0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, + 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, + 0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, + 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, + 0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, + 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, + 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, + 0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, + 0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, + 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad + ]); + + return function (k) + { + var key = new Uint8Array(buffer(k)), + T = Math.min(key.length, 128), + T1 = this.effectiveLength, + T8 = Math.floor((T1 + 7) / 8), + TM = 0xff % Math.pow(2, 8 + T1 - 8 * T8); + + var L = new Uint8Array(128), K = new Uint16Array(L.buffer); + for (var i = 0; i < T; i++) + L[i] = key[i]; + for (var i = T; i < 128; i++) + L[i] = PITABLE[(L[i - 1] + L[i - T]) % 256]; + L[128 - T8] = PITABLE[L[128 - T8] & TM]; + for (var i = 127 - T8; i >= 0; --i) + L[i] = PITABLE[L[i + 1] ^ L[i + T8]]; + return K; + }; +} // +)(); + +/** + * RC2 encrypt/decrypt process + * + * https://tools.ietf.org/html/rfc2268 + * + * @memberOf GostCipher + * @private + * @instance + * @method round + * @param {CryptoOperationData} k Scheduled key + * @param {CryptoOperationData} d Data + * @param {number} ofs Offsec + * @param {number} e true - decrypt + */ +var processRC2 = (function () // +{ + var K, j, R = new Uint16Array(4), + s = new Uint16Array([1, 2, 3, 5]), reverse; + + function rol(R, s) { + return (R << s | R >>> (16 - s)) & 0xffff; + } + + function ror(R, s) { + return (R >>> s | R << (16 - s)) & 0xffff; + } + + function mix(i) { + if (reverse) { + R[i] = ror(R[i], s[i]); + R[i] = R[i] - K[j] - (R[(i + 3) % 4] & R[(i + 2) % 4]) - ((~R[(i + 3) % 4]) & R[(i + 1) % 4]); + j = j - 1; + } else { + R[i] = R[i] + K[j] + (R[(i + 3) % 4] & R[(i + 2) % 4]) + ((~R[(i + 3) % 4]) & R[(i + 1) % 4]); + j = j + 1; + R[i] = rol(R[i], s[i]); + } + } + + function mash(i) { + if (reverse) { + R[i] = R[i] - K[R[(i + 3) % 4] & 63]; + } else { + R[i] = R[i] + K[R[(i + 3) % 4] & 63]; + } + } + + function perform(method, count) { + count = count || 1; + for (var j = 0; j < count; j++) { + if (reverse) { + for (var i = 3; i >= 0; --i) + method(i); + } else { + for (var i = 0; i < 4; i++) + method(i); + } + } + } + + return function (k, d, ofs, e) { + reverse = e; + // 1. Initialize words R[0], ..., R[3] to contain the 64-bit + // ciphertext value. + R = new Uint16Array(d.buffer, ofs || d.byteOffset, 4); + // 2. Expand the key, so that words K[0], ..., K[63] become + // defined. + K = k; + // 3. Initialize j to zero (enc) j to 63 (dec). + j = e ? 63 : 0; + // 4. Perform five mixing rounds. + perform(mix, 5); + // 5. Perform one mashing round. + perform(mash); + // 6. Perform six mixing rounds. + perform(mix, 6); + // 7. Perform one mashing round. + perform(mash); + // 8. Perform five mixing rounds. + perform(mix, 5); + }; +} // +)(); + +/** + * Algorithm name GOST 28147-ECB

+ * + * encryptECB (K, D) is D, encrypted with key k using GOST 28147/GOST R 34.13 in + * "prostaya zamena" (Electronic Codebook, ECB) mode. + * @memberOf GostCipher + * @method encrypt + * @instance + * @param k {CryptoOperationData} 8x32 bit key + * @param d {CryptoOperationData} 8 bits message + * @return {CryptoOperationData} result + */ +function encryptECB(k, d) // +{ + var p = this.pad(byteArray(d)), + n = this.blockSize, + b = p.byteLength / n, + key = this.keySchedule(k); + + for (var i = 0; i < b; i++) + this.process(key, p, n * i); + + return p.buffer; +} // + +/** + * Algorithm name GOST 28147-ECB

+ * + * decryptECB (K, D) is D, decrypted with key K using GOST 28147/GOST R 34.13 in + * "prostaya zamena" (Electronic Codebook, ECB) mode. + * + * @memberOf GostCipher + * @method decrypt + * @instance + * @param k {CryptoOperationData} 8x32 bits key + * @param d {CryptoOperationData} 8 bits message + * @return {CryptoOperationData} result + */ +function decryptECB(k, d) // +{ + var p = cloneArray(d), + n = this.blockSize, + b = p.byteLength / n, + key = this.keySchedule(k, 1); + + for (var i = 0; i < b; i++) + this.process(key, p, n * i, 1); + + return this.unpad(p).buffer; +} // + +/** + * Algorithm name GOST 28147-CFB

+ * + * encryptCFB (IV, K, D) is D, encrypted with key K using GOST 28147/GOST R 34.13 + * in "gammirovanie s obratnoj svyaziyu" (Cipher Feedback, CFB) mode, and IV is + * used as the initialization vector. + * + * @memberOf GostCipher + * @method encrypt + * @instance + * @param {CryptoOperationData} k 8x32 bits key + * @param {CryptoOperationData} d 8 bits array with data + * @param {CryptoOperationData} iv initial vector + * @return {CryptoOperationData} result + */ +function encryptCFB(k, d, iv) // +{ + var s = new Uint8Array(iv || this.iv), + c = cloneArray(d), + m = s.length, + t = new Uint8Array(m), + b = this.shiftBits >> 3, + cb = c.length, r = cb % b, q = (cb - r) / b, + key = this.keySchedule(k); + + for (var i = 0; i < q; i++) { + + for (var j = 0; j < m; j++) + t[j] = s[j]; + + this.process(key, s); + + for (var j = 0; j < b; j++) + c[i * b + j] ^= s[j]; + + for (var j = 0; j < m - b; j++) + s[j] = t[b + j]; + + for (var j = 0; j < b; j++) + s[m - b + j] = c[i * b + j]; + + k = this.keyMeshing(k, s, i, key); + } + + if (r > 0) { + this.process(key, s); + + for (var i = 0; i < r; i++) + c[q * b + i] ^= s[i]; + } + return c.buffer; +} // + +/** + * Algorithm name GOST 28147-CFB

+ * + * decryptCFB (IV, K, D) is D, decrypted with key K using GOST 28147/GOST R 34.13 + * in "gammirovanie s obratnoj svyaziyu po shifrotekstu" (Cipher Feedback, CFB) mode, and IV is + * used as the initialization vector. + * + * @memberOf GostCipher + * @method decrypt + * @instance + * @param {CryptoOperationData} k 8x32 bits key + * @param {CryptoOperationData} d 8 bits array with data + * @param {CryptoOperationData} iv initial vector + * @return {CryptoOperationData} result + */ +function decryptCFB(k, d, iv) // +{ + var s = new Uint8Array(iv || this.iv), + c = cloneArray(d), + m = s.length, + t = new Uint8Array(m), + b = this.shiftBits >> 3, + cb = c.length, r = cb % b, q = (cb - r) / b, + key = this.keySchedule(k); + + for (var i = 0; i < q; i++) { + + for (var j = 0; j < m; j++) + t[j] = s[j]; + + this.process(key, s); + + for (var j = 0; j < b; j++) { + t[j] = c[i * b + j]; + c[i * b + j] ^= s[j]; + } + + for (var j = 0; j < m - b; j++) + s[j] = t[b + j]; + + for (var j = 0; j < b; j++) + s[m - b + j] = t[j]; + + k = this.keyMeshing(k, s, i, key); + } + + if (r > 0) { + this.process(key, s); + + for (var i = 0; i < r; i++) + c[q * b + i] ^= s[i]; + } + return c.buffer; +} // + +/** + * Algorithm name GOST 28147-OFB

+ * + * encryptOFB/decryptOFB (IV, K, D) is D, encrypted with key K using GOST 28147/GOST R 34.13 + * in "gammirovanie s obratnoj svyaziyu po vyhodu" (Output Feedback, OFB) mode, and IV is + * used as the initialization vector. + * + * @memberOf GostCipher + * @method encrypt + * @instance + * @param {CryptoOperationData} k 8x32 bits key + * @param {CryptoOperationData} d 8 bits array with data + * @param {CryptoOperationData} iv 8x8 optional bits initial vector + * @return {CryptoOperationData} result + */ +/** + * Algorithm name GOST 28147-OFB

+ * + * encryptOFB/decryptOFB (IV, K, D) is D, encrypted with key K using GOST 28147/GOST R 34.13 + * in "gammirovanie s obratnoj svyaziyu po vyhodu" (Output Feedback, OFB) mode, and IV is + * used as the initialization vector. + * + * @memberOf GostCipher + * @method decrypt + * @instance + * @param {CryptoOperationData} k 8x32 bits key + * @param {CryptoOperationData} d 8 bits array with data + * @param {CryptoOperationData} iv initial vector + * @return {CryptoOperationData} result + */ +function processOFB(k, d, iv) // +{ + var s = new Uint8Array(iv || this.iv), + c = cloneArray(d), + m = s.length, + t = new Uint8Array(m), + b = this.shiftBits >> 3, + p = new Uint8Array(b), + cb = c.length, r = cb % b, q = (cb - r) / b, + key = this.keySchedule(k); + + for (var i = 0; i < q; i++) { + + for (var j = 0; j < m; j++) + t[j] = s[j]; + + this.process(key, s); + + for (var j = 0; j < b; j++) + p[j] = s[j]; + + for (var j = 0; j < b; j++) + c[i * b + j] ^= s[j]; + + for (var j = 0; j < m - b; j++) + s[j] = t[b + j]; + + for (var j = 0; j < b; j++) + s[m - b + j] = p[j]; + + k = this.keyMeshing(k, s, i, key); + } + + if (r > 0) { + this.process(key, s); + + for (var i = 0; i < r; i++) + c[q * b + i] ^= s[i]; + } + return c.buffer; +} // + +/** + * Algorithm name GOST 28147-CTR

+ * + * encryptCTR/decryptCTR (IV, K, D) is D, encrypted with key K using GOST 28147/GOST R 34.13 + * in "gammirovanie" (Counter Mode-CTR) mode, and IV is used as the + * initialization vector. + * @memberOf GostCipher + * @method encrypt + * @instance + * @param {CryptoOperationData} k 8x32 bits key + * @param {CryptoOperationData} d 8 bits array with data + * @param {CryptoOperationData} iv 8x8 optional bits initial vector + * @return {CryptoOperationData} result + */ +/** + * Algorithm name GOST 28147-CTR

+ * + * encryptCTR/decryptCTR (IV, K, D) is D, encrypted with key K using GOST 28147/GOST R 34.13 + * in "gammirovanie" (Counter Mode-CTR) mode, and IV is used as the + * initialization vector. + * @memberOf GostCipher + * @method decrypt + * @instance + * @param {CryptoOperationData} k 8x32 bits key + * @param {CryptoOperationData} d 8 bits array with data + * @param {CryptoOperationData} iv initial vector + * @return {CryptoOperationData} result + */ +function processCTR89(k, d, iv) // +{ + var s = new Uint8Array(iv || this.iv), + c = cloneArray(d), + b = this.blockSize, + t = new Int8Array(b), + cb = c.length, r = cb % b, q = (cb - r) / b, + key = this.keySchedule(k), + syn = new Int32Array(s.buffer); + + this.process(key, s); + + for (var i = 0; i < q; i++) { + syn[0] = (syn[0] + 0x1010101) & 0xffffffff; + // syn[1] = signed(unsigned((syn[1] + 0x1010104) & 0xffffffff) % 0xffffffff); + var tmp = unsigned(syn[1]) + 0x1010104; // Special thanks to Ilya Matveychikov + syn[1] = signed(tmp < 0x100000000 ? tmp : tmp - 0xffffffff); + + for (var j = 0; j < b; j++) + t[j] = s[j]; + + this.process(key, syn); + + for (var j = 0; j < b; j++) + c[i * b + j] ^= s[j]; + + for (var j = 0; j < b; j++) + s[j] = t[j]; + + k = this.keyMeshing(k, s, i, key); + } + if (r > 0) { + syn[0] = (syn[0] + 0x1010101) & 0xffffffff; + // syn[1] = signed(unsigned((syn[1] + 0x1010104) & 0xffffffff) % 0xffffffff); + var tmp = unsigned(syn[1]) + 0x1010104; // Special thanks to Ilya Matveychikov + syn[1] = signed(tmp < 0x100000000 ? tmp : tmp - 0xffffffff); + + this.process(key, syn); + + for (var i = 0; i < r; i++) + c[q * b + i] ^= s[i]; + } + return c.buffer; +} // + +function processCTR15(k, d, iv) // +{ + var c = cloneArray(d), + n = this.blockSize, + b = this.shiftBits >> 3, + cb = c.length, r = cb % b, q = (cb - r) / b, + s = new Uint8Array(n), + t = new Int32Array(n), + key = this.keySchedule(k); + + s.set(iv || this.iv); + for (var i = 0; i < q; i++) { + + for (var j = 0; j < n; j++) + t[j] = s[j]; + + this.process(key, s); + + for (var j = 0; j < b; j++) + c[b * i + j] ^= s[j]; + + for (var j = 0; j < n; j++) + s[j] = t[j]; + + for (var j = n - 1; i >= 0; --i) { + if (s[j] > 0xfe) { + s[j] -= 0xfe; + } else { + s[j]++; + break; + } + } + } + + if (r > 0) { + this.process(key, s); + for (var j = 0; j < r; j++) + c[b * q + j] ^= s[j]; + } + + return c.buffer; +} // + +/** + * Algorithm name GOST 28147-CBC

+ * + * encryptCBC (IV, K, D) is D, encrypted with key K using GOST 28147/GOST R 34.13 + * in "Prostaya zamena s zatsepleniem" (Cipher-Block-Chaining, CBC) mode and IV is used as the initialization + * vector. + * + * @memberOf GostCipher + * @method encrypt + * @instance + * @param {CryptoOperationData} k 8x32 bits key + * @param {CryptoOperationData} d 8 bits array with data + * @param {CryptoOperationData} iv initial vector + * @return {CryptoOperationData} result + */ +function encryptCBC(k, d, iv) // +{ + var s = new Uint8Array(iv || this.iv), + n = this.blockSize, + m = s.length, + c = this.pad(byteArray(d)), + key = this.keySchedule(k); + + for (var i = 0, b = c.length / n; i < b; i++) { + + for (var j = 0; j < n; j++) + s[j] ^= c[i * n + j]; + + this.process(key, s); + + for (var j = 0; j < n; j++) + c[i * n + j] = s[j]; + + if (m !== n) { + for (var j = 0; j < m - n; j++) + s[j] = s[n + j]; + + for (var j = 0; j < n; j++) + s[j + m - n] = c[i * n + j]; + } + + k = this.keyMeshing(k, s, i, key); + } + + return c.buffer; +} // + +/** + * Algorithm name GOST 28147-CBC

+ * + * decryptCBC (IV, K, D) is D, decrypted with key K using GOST 28147/GOST R 34.13 + * in "Prostaya zamena s zatsepleniem" (Cipher-Block-Chaining, CBC) mode and IV is used as the initialization + * vector. + * + * @memberOf GostCipher + * @method decrypt + * @instance + * @param {CryptoOperationData} k 8x32 bits key + * @param {CryptoOperationData} d 8 bits array with data + * @param {CryptoOperationData} iv initial vector + * @return {CryptoOperationData} result + */ +function decryptCBC(k, d, iv) // +{ + var s = new Uint8Array(iv || this.iv), + n = this.blockSize, + m = s.length, + c = cloneArray(d), + next = new Uint8Array(n), + key = this.keySchedule(k, 1); + + for (var i = 0, b = c.length / n; i < b; i++) { + + for (var j = 0; j < n; j++) + next[j] = c[i * n + j]; + + this.process(key, c, i * n, 1); + + for (var j = 0; j < n; j++) + c[i * n + j] ^= s[j]; + + if (m !== n) { + for (var j = 0; j < m - n; j++) + s[j] = s[n + j]; + } + + for (var j = 0; j < n; j++) + s[j + m - n] = next[j]; + + k = this.keyMeshing(k, s, i, key, 1); + } + + return this.unpad(c).buffer; +} // + +/** + * The generateKey method returns a new generated key. + * + * @memberOf GostCipher + * @method generateKey + * @instance + * @return {CryptoOperationData} result + */ + +function generateKey() // +{ + // Simple generate 256 bit random seed + var k = new Uint8Array(this.keySize); + randomSeed(k); + return k.buffer; +} // + + +/** + * makeIMIT (K, D) is the 32-bit result of the GOST 28147/GOST R 34.13 in + * "imitovstavka" (MAC) mode, used with D as plaintext, K as key and IV + * as initialization vector. Note that the standard specifies its use + * in this mode only with an initialization vector of zero. + * + * @memberOf GostCipher + * @method processMAC + * @private + * @instance + * @param {Int32Array} key 8x32 bits key + * @param {Int32Array} s 8x8 sum array + * @param {Uint8Array} d 8 bits array with data + * @return {Uint8Array} result + */ +function processMAC89(key, s, d) // +{ + var c = zeroPad.call(this, byteArray(d)), + n = this.blockSize, + q = c.length / n, + sBox = this.sBox, + sum = new Int32Array(s.buffer); + + for (var i = 0; i < q; i++) { + + for (var j = 0; j < n; j++) + s[j] ^= c[i * n + j]; + + for (var j = 0; j < 16; j++) // 1-16 steps + round(sBox, sum, key[j]); + } +} // + +function processKeyMAC15(s) // +{ + var t = 0, n = s.length; + for (var i = n - 1; i >= 0; --i) { + var t1 = s[i] >>> 7; + s[i] = (s[i] << 1) & 0xff | t; + t = t1; + } + if (t !== 0) { + if (n === 16) + s[15] ^= 0x87; + else + s[7] ^= 0x1b; + } +} // + +function processMAC15(key, s, d) // +{ + var n = this.blockSize, + sBox = this.sBox, c = byteArray(d), + r = new Uint8Array(n); + // R + this.process(key, r); + // K1 + processKeyMAC15(r); + if (d.byteLength % n !== 0) { + c = bitPad.call(this, byteArray(d)); + // K2 + processKeyMAC15(r); + } + + for (var i = 0, q = c.length / n; i < q; i++) { + + for (var j = 0; j < n; j++) + s[j] ^= c[i * n + j]; + + if (i === q - 1) {// Last block + for (var j = 0; j < n; j++) + s[j] ^= r[j]; + } + + this.process(key, s); + } +} // + +/** + * signMAC (K, D, IV) is the 32-bit result of the GOST 28147/GOST R 34.13 in + * "imitovstavka" (MAC) mode, used with D as plaintext, K as key and IV + * as initialization vector. Note that the standard specifies its use + * in this mode only with an initialization vector of zero. + * + * @memberOf GostCipher + * @method sign + * @instance + * @param {CryptoOperationData} k 8x32 bits key + * @param {CryptoOperationData} d 8 bits array with data + * @param {CryptoOperationData} iv initial vector + * @return {CryptoOperationData} result + */ +function signMAC(k, d, iv) // +{ + var key = this.keySchedule(k), + s = new Uint8Array(iv || this.iv), + m = Math.ceil(this.macLength >> 3) || this.blockSize >> 1; + + this.processMAC(key, s, d); + + var mac = new Uint8Array(m); // mac size + mac.set(new Uint8Array(s.buffer, 0, m)); + return mac.buffer; +} // + +/** + * verifyMAC (K, M, D, IV) the 32-bit result verification of the GOST 28147/GOST R 34.13 in + * "imitovstavka" (MAC) mode, used with D as plaintext, K as key and IV + * as initialization vector. Note that the standard specifies its use + * in this mode only with an initialization vector of zero. + * + * @memberOf GostCipher + * @method verify + * @instance + * @param {CryptoOperationData} k 8x32 bits key + * @param {CryptoOperationData} m 8 bits array with signature + * @param {CryptoOperationData} d 8 bits array with data + * @param {CryptoOperationData} iv 8x8 optional bits initial vector + * @return {boolen} MAC verified = true + */ +function verifyMAC(k, m, d, iv) // +{ + var mac = new Uint8Array(signMAC.call(this, k, d, iv)), + test = byteArray(m); + if (mac.length !== test.length) + return false; + for (var i = 0, n = mac.length; i < n; i++) + if (mac[i] !== test[i]) + return false; + return true; +} // + +/** + * Algorithm name GOST 28147-KW

+ * + * This algorithm encrypts GOST 28147-89 CEK with a GOST 28147/GOST R 34.13 KEK. + * Ref. rfc4357 6.1 GOST 28147-89 Key Wrap + * Note: This algorithm MUST NOT be used with a KEK produced by VKO GOST + * R 34.10-94, because such a KEK is constant for every sender-recipient + * pair. Encrypting many different content encryption keys on the same + * constant KEK may reveal that KEK. + * + * @memberOf GostCipher + * @method wrapKey + * @instance + * @param {CryptoOperationData} kek Key encryption key + * @param {CryptoOperationData} cek Content encryption key + * @returns {CryptoOperationData} Encrypted cek + */ +function wrapKeyGOST(kek, cek) // +{ + var n = this.blockSize, k = this.keySize, len = k + (n >> 1); + // 1) For a unique symmetric KEK, generate 8 octets at random and call + // the result UKM. For a KEK, produced by VKO GOST R 34.10-2001, use + // the UKM that was used for key derivation. + if (!this.ukm) + throw new DataError('UKM must be defined'); + var ukm = new Uint8Array(this.ukm); + // 2) Compute a 4-byte checksum value, GOST 28147IMIT (UKM, KEK, CEK). + // Call the result CEK_MAC. + var mac = signMAC.call(this, kek, cek, ukm); + // 3) Encrypt the CEK in ECB mode using the KEK. Call the ciphertext CEK_ENC. + var enc = encryptECB.call(this, kek, cek); + // 4) The wrapped content-encryption key is (UKM | CEK_ENC | CEK_MAC). + var r = new Uint8Array(len); + r.set(new Uint8Array(enc), 0); + r.set(new Uint8Array(mac), k); + return r.buffer; +} // + +/** + * Algorithm name GOST 28147-KW

+ * + * This algorithm decrypts GOST 28147-89 CEK with a GOST 28147 KEK. + * Ref. rfc4357 6.2 GOST 28147-89 Key Unwrap + * + * @memberOf GostCipher + * @method unwrapKey + * @instance + * @param {type} kek Key encryption key + * @param {type} data Content encryption key + * @return {CryptoOperationData} result + */ +function unwrapKeyGOST(kek, data) // +{ + var n = this.blockSize, k = this.keySize, len = k + (n >> 1); + // 1) If the wrapped content-encryption key is not 44 octets, then error. + var d = buffer(data); + if (d.byteLength !== len) + throw new DataError('Wrapping key size must be ' + len + ' bytes'); + // 2) Decompose the wrapped content-encryption key into UKM, CEK_ENC, and CEK_MAC. + // UKM is the most significant (first) 8 octets. CEK_ENC is next 32 octets, + // and CEK_MAC is the least significant (last) 4 octets. + if (!this.ukm) + throw new DataError('UKM must be defined'); + var ukm = new Uint8Array(this.ukm), + enc = new Uint8Array(d, 0, k), + mac = new Uint8Array(d, k, n >> 1); + // 3) Decrypt CEK_ENC in ECB mode using the KEK. Call the output CEK. + var cek = decryptECB.call(this, kek, enc); + // 4) Compute a 4-byte checksum value, GOST 28147IMIT (UKM, KEK, CEK), + // compare the result with CEK_MAC. If they are not equal, then error. + var check = verifyMAC.call(this, kek, mac, cek, ukm); + if (!check) + throw new DataError('Error verify MAC of wrapping key'); + return cek; +} // + +/** + * Algorithm name GOST 28147-CPKW

+ * + * Given a random 64-bit UKM and a GOST 28147 key K, this algorithm + * creates a new GOST 28147-89 key K(UKM). + * Ref. rfc4357 6.3 CryptoPro KEK Diversification Algorithm + * + * @memberOf GostCipher + * @method diversify + * @instance + * @private + * @param {CryptoOperationData} kek Key encryption key + * @param {CryptoOperationData} ukm Random generated value + * @returns {CryptoOperationData} Diversified kek + */ +function diversifyKEK(kek, ukm) // +{ + var n = this.blockSize; + + // 1) Let K[0] = K; + var k = intArray(kek); + // 2) UKM is split into components a[i,j]: + // UKM = a[0]|..|a[7] (a[i] - byte, a[i,0]..a[i,7] - it’s bits) + var a = []; + for (var i = 0; i < n; i++) { + a[i] = []; + for (var j = 0; j < 8; j++) { + a[i][j] = (ukm[i] >>> j) & 0x1; + } + } + // 3) Let i be 0. + // 4) K[1]..K[8] are calculated by repeating the following algorithm + // eight times: + for (var i = 0; i < n; i++) { + // A) K[i] is split into components k[i,j]: + // K[i] = k[i,0]|k[i,1]|..|k[i,7] (k[i,j] - 32-bit integer) + // B) Vector S[i] is calculated: + // S[i] = ((a[i,0]*k[i,0] + ... + a[i,7]*k[i,7]) mod 2^32) | + // (((~a[i,0])*k[i,0] + ... + (~a[i,7])*k[i,7]) mod 2^32); + var s = new Int32Array(2); + for (var j = 0; j < 8; j++) { + if (a[i][j]) + s[0] = (s[0] + k[j]) & 0xffffffff; + else + s[1] = (s[1] + k[j]) & 0xffffffff; + } + // C) K[i+1] = encryptCFB (S[i], K[i], K[i]) + var iv = new Uint8Array(s.buffer); + k = new Int32Array(encryptCFB.call(this, k, k, iv)); + // D) i = i + 1 + } + // 5) Let K(UKM) be K[8]. + return k; +} // + +/** + * Algorithm name GOST 28147-CPKW

+ * + * This algorithm encrypts GOST 28147-89 CEK with a GOST 28147 KEK. + * It can be used with any KEK (e.g., produced by VKO GOST R 34.10-94 or + * VKO GOST R 34.10-2001) because a unique UKM is used to diversify the KEK. + * Ref. rfc4357 6.3 CryptoPro Key Wrap + * + * @memberOf GostCipher + * @method wrapKey + * @instance + * @param {CryptoOperationData} kek Key encryption key + * @param {CryptoOperationData} cek Content encryption key + * @returns {CryptoOperationData} Encrypted cek + */ +function wrapKeyCP(kek, cek) // +{ + var n = this.blockSize, k = this.keySize, len = k + (n >> 1); + // 1) For a unique symmetric KEK or a KEK produced by VKO GOST R + // 34.10-94, generate 8 octets at random. Call the result UKM. For + // a KEK, produced by VKO GOST R 34.10-2001, use the UKM that was + // used for key derivation. + if (!this.ukm) + throw new DataError('UKM must be defined'); + var ukm = new Uint8Array(this.ukm); + // 2) Diversify KEK, using the CryptoPro KEK Diversification Algorithm, + // described in Section 6.5. Call the result KEK(UKM). + var dek = diversifyKEK.call(this, kek, ukm); + // 3) Compute a 4-byte checksum value, GOST 28147IMIT (UKM, KEK(UKM), + // CEK). Call the result CEK_MAC. + var mac = signMAC.call(this, dek, cek, ukm); + // 4) Encrypt CEK in ECB mode using KEK(UKM). Call the ciphertext + // CEK_ENC. + var enc = encryptECB.call(this, dek, cek); + // 5) The wrapped content-encryption key is (UKM | CEK_ENC | CEK_MAC). + var r = new Uint8Array(len); + r.set(new Uint8Array(enc), 0); + r.set(new Uint8Array(mac), k); + return r.buffer; +} // + +/** + * Algorithm name GOST 28147-CPKW

+ * + * This algorithm encrypts GOST 28147-89 CEK with a GOST 28147 KEK. + * Ref. rfc4357 6.4 CryptoPro Key Unwrap + * + * @memberOf GostCipher + * @method unwrapKey + * @instance + * @param {CryptoOperationData} kek Key encryption key + * @param {CryptoOperationData} data Encrypted content encryption keu + * @return {CryptoOperationData} result Decrypted content encryption keu + */ +function unwrapKeyCP(kek, data) // +{ + var n = this.blockSize, k = this.keySize, len = k + (n >> 1); + // 1) If the wrapped content-encryption key is not 44 octets, then error. + var d = buffer(data); + if (d.byteLength !== len) + throw new DataError('Wrapping key size must be ' + len + ' bytes'); + // 2) Decompose the wrapped content-encryption key into UKM, CEK_ENC, + // and CEK_MAC. UKM is the most significant (first) 8 octets. + // CEK_ENC is next 32 octets, and CEK_MAC is the least significant + // (last) 4 octets. + if (!this.ukm) + throw new DataError('UKM must be defined'); + var ukm = new Uint8Array(this.ukm), + enc = new Uint8Array(d, 0, k), + mac = new Uint8Array(d, k, n >> 1); + // 3) Diversify KEK using the CryptoPro KEK Diversification Algorithm, + // described in section 6.5. Call the result KEK(UKM). + var dek = diversifyKEK.call(this, kek, ukm); + // 4) Decrypt CEK_ENC in ECB mode using KEK(UKM). Call the output CEK. + var cek = decryptECB.call(this, dek, enc); + // 5) Compute a 4-byte checksum value, GOST 28147IMIT (UKM, KEK(UKM), + // CEK), compare the result with CEK_MAC. If they are not equal, + // then it is an error. + var check = verifyMAC.call(this, dek, mac, cek, ukm); + if (!check) + throw new DataError('Error verify MAC of wrapping key'); + return cek; +} // + +/** + * SignalCom master key packing algorithm + * + * kek stored in 3 files - kek.opq, mk.db3, masks.db3 + * kek.opq - always 36 bytes length = 32 bytes encrypted kek + 4 bytes mac of decrypted kek + * mk.db3 - 6 bytes header (1 byte magic code 0x22 + 1 byte count of masks + 4 bytes mac of + * xor summarizing masks value) + attached masks + * masks.db3 - detached masks. + * Total length of attached + detached masks = 32 bits * count of masks + * Default value of count 8 = (7 attached + 1 detached). But really no reason for such + * separation - all masks xor summarizing - order is not matter. + * Content of file rand.opq can used as ukm. Don't forget change file content after using. + * + * For usb-token files has names: + * a001 - mk.db3, b001 - masks.db3, c001 - kek.opq, d001 - rand.opq + * For windows registry + * 00000001 - mk.db3, 00000002 - masks.db3, 00000003 - key.opq, 00000004 - rand.opq, + * 00000006 - keys\00000001.key, 0000000A - certificate + * + * @memberOf GostCipher + * @method packKey + * @instance + * @private + * @param {CryptoOperationData} unpacked - clear main key 32 bytes + * @param {CryptoOperationData} ukm - random vector for packing - 32 bytes * (count of masks - 1) + * @returns {CryptoOperationData} packed master key - concatination of mk.db3 + masks.db3 + */ +function packKeySC(unpacked, ukm) // +{ + var m = this.blockSize >> 1, k = this.keySize; + var mcount = 8; + var key = new Uint8Array(buffer(unpacked)); + if (key.byteLength !== k) + throw new DataError('Wrong cleartext size ' + key.byteLength + ' bytes'); + // Check or generate UKM + ukm = ukm || this.ukm; + if (ukm) { + ukm = new Uint8Array(buffer(ukm)); + if (ukm.byteLength > 0 && ukm.byteLength % k === 0) + mcount = ukm.byteLength / k + 1; + else + throw new DataError('Wrong rand size ' + ukm.byteLength + ' bytes'); + } else + randomSeed(ukm = new Uint8Array((mcount - 1) * k)); + // Output array + var d = new Uint8Array(mcount * k + m + 2), b = d.buffer; + // Calculate MAC + var zero32 = new Uint8Array(k); + var mac = signMAC.call(this, key, zero32); + d[0] = 0x22; // Magic code + d[1] = mcount; // Count of masks + d.set(new Uint8Array(mac), 2); + d.set(ukm, k + m + 2); + for (var i = 1; i < mcount; i++) { + var mask = new Uint8Array(b, 2 + m + k * i); + for (var j = 0; j < k; j++) + key[j] ^= mask[j]; + } + d.set(key, m + 2); + return d.buffer; +} // + +/** + * Algorithm name GOST 28147-SCKW

+ * + * SignalCom master key unpacking algorithm + * + * @memberOf GostCipher + * @method unpackKey + * @instance + * @private + * @param {CryptoOperationData} packed - concatination of mk.db3 + masks.db3 + * @returns {CryptoOperationData} unpacked master key + */ +function unpackKeySC(packed) // +{ + var m = this.blockSize >> 1, k = this.keySize; + var b = buffer(packed); + // Unpack master key + var magic = new Uint8Array(b, 0, 1)[0]; + if (magic !== 0x22) + throw new DataError('Invalid magic number'); + var mcount = new Uint8Array(b, 1, 1)[0]; + var mac = new Uint8Array(b, 2, m); // MAC for summarized mask + // Compute packKey xor summing for all masks + var key = new Uint8Array(k); + for (var i = 0; i < mcount; i++) { + var mask = new Uint8Array(b, 2 + m + k * i, k); + for (var j = 0; j < k; j++) + key[j] ^= mask[j]; + } + // Test MAC for packKey with default sBox on zero 32 bytes array + var zero32 = new Uint8Array(k); + var test = verifyMAC.call(this, key, mac, zero32); + if (!test) { + // Try to use different sBoxes + var names = ['E-A', 'E-B', 'E-C', 'E-D', 'E-SC']; + for (var i = 0, n = names.length; i < n; i++) { + this.sBox = sBoxes[names[i]]; + test = verifyMAC.call(this, key, mac, zero32); + if (test) + break; + } + } + if (!test) + throw new DataError('Invalid main key MAC'); + return key.buffer; +} // + +/** + * Algorithm name GOST 28147-SCKW

+ * + * SignalCom Key Wrapping algorithm + * + * @memberOf GostCipher + * @method wrapKey + * @instance + * @param {CryptoOperationData} kek - clear kek or concatination of mk.db3 + masks.db3 + * @param {CryptoOperationData} cek - key for wrapping + * @returns {CryptoOperationData} wrapped key - file kek.opq + */ +function wrapKeySC(kek, cek) // +{ + var m = this.blockSize >> 1, n = this.keySize; + var k = buffer(kek); + var c = buffer(cek); + if (k.byteLength !== n) + k = unpackKeySC.call(this, k); + var enc = encryptECB.call(this, k, c); + var mac = signMAC.call(this, k, c); + var d = new Uint8Array(m + n); + d.set(new Uint8Array(enc), 0); + d.set(new Uint8Array(mac), n); + return d.buffer; +} // + +/** + * Algorithm name GOST 28147-SCKW

+ * + * SignalCom Key UnWrapping algorithm + * + * @memberOf GostCipher + * @method unwrapKey + * @instance + * @param {CryptoOperationData} kek - concatination of files mk.db3 + masks.db3 or clear kek + * @param {CryptoOperationData} cek - wrapping key - file kek.opq + * @return {CryptoOperationData} result + */ +function unwrapKeySC(kek, cek) // +{ + var m = this.blockSize >> 1, n = this.keySize; + var k = buffer(kek); + var c = buffer(cek); + if (k.byteLength !== n) + k = unpackKeySC.call(this, k); + var enc = new Uint8Array(c, 0, n); // Encrypted kek + var mac = new Uint8Array(c, n, m); // MAC for clear kek + var d = decryptECB.call(this, k, enc); + if (!verifyMAC.call(this, k, mac, d)) + throw new DataError('Invalid key MAC'); + return d; +} // + +/** + * Algorithm name GOST 28147-SCKW

+ * + * SignalCom master key generation for wrapping + * + * @memberOf GostCipher + * @method generateKey + * @instance + * @return {CryptoOperationData} result + */ +function generateWrappingKeySC() // +{ + return packKeySC.call(this, generateKey.call(this)); +} // + +function maskKey(mask, key, inverse, keySize) // +{ + var k = keySize / 4, + m32 = new Int32Array(buffer(mask)), + k32 = new Int32Array(buffer(key)), + r32 = new Int32Array(k); + if (inverse) + for (var i = 0; i < k; i++) + r32[i] = (k32[i] + m32[i]) & 0xffffffff; + else + for (var i = 0; i < k; i++) + r32[i] = (k32[i] - m32[i]) & 0xffffffff; + return r32.buffer; +} // + +/** + * Algorithm name GOST 28147-MASK

+ * + * This algorithm wrap key mask + * + * @memberOf GostCipher + * @method wrapKey + * @instance + * @param {CryptoOperationData} mask The mask + * @param {CryptoOperationData} key The key + * @returns {CryptoOperationData} The masked key + */ +function wrapKeyMask(mask, key) // +{ + return maskKey(mask, key, this.procreator === 'VN', this.keySize); +} // + +/** + * Algorithm name GOST 28147-CPKW

+ * + * This algorithm unwrap key mask + * + * @memberOf GostCipher + * @method unwrapKey + * @instance + * @param {CryptoOperationData} mask The mask + * @param {CryptoOperationData} key The masked key + * @return {CryptoOperationData} result The key + */ +function unwrapKeyMask(mask, key) // +{ + return maskKey(mask, key, this.procreator !== 'VN', this.keySize); +} // + +/** + * Algorithm name GOST 28147-CPKM

+ * + * Key meshing in according to rfc4357 2.3.2. CryptoPro Key Meshing + * + * @memberOf GostCipher + * @method keyMeshing + * @instance + * @private + * @param {(Uint8Array|CryptoOperationData)} k 8x8 bit key + * @param {Uint8Array} s 8x8 bit sync (iv) + * @param {Integer} i block index + * @param {Int32Array} key 8x32 bit key schedule + * @param {boolean} e true - decrypt + * @returns CryptoOperationData next 8x8 bit key + */ +function keyMeshingCP(k, s, i, key, e) // +{ + if ((i + 1) * this.blockSize % 1024 === 0) { // every 1024 octets + // K[i+1] = decryptECB (K[i], C); + k = decryptECB.call(this, k, C); + // IV0[i+1] = encryptECB (K[i+1],IVn[i]) + s.set(new Uint8Array(encryptECB.call(this, k, s))); + // restore key schedule + key.set(this.keySchedule(k, e)); + } + return k; +} // + +/** + * Null Key Meshing in according to rfc4357 2.3.1 + * + * @memberOf GostCipher + * @method keyMeshing + * @instance + * @private + * @param {(Uint8Array|CryptoOperationData)} k 8x8 bit key + */ +function noKeyMeshing(k) // +{ + return k; +} // + +/** + * Algorithm name GOST 28147-NoPadding

+ * + * No padding. + * + * @memberOf GostCipher + * @method padding + * @instance + * @private + * @param {Uint8Array} d array with source data + * @returns {Uint8Array} result + */ +function noPad(d) // +{ + return new Uint8Array(d); +} // + +/** + * Algorithm name GOST 28147-PKCS5Padding

+ * + * PKCS#5 padding: 8-x remaining bytes are filled with the value of + * 8-x. If there’s no incomplete block, one extra block filled with + * value 8 is added + * + * @memberOf GostCipher + * @method padding + * @instance + * @private + * @param {Uint8Array} d array with source data + * @returns {Uint8Array} result + */ +function pkcs5Pad(d) // +{ + var n = d.byteLength, + nb = this.blockSize, + q = nb - n % nb, + m = Math.ceil((n + 1) / nb) * nb, + r = new Uint8Array(m); + r.set(d); + for (var i = n; i < m; i++) + r[i] = q; + return r; +} // + +function pkcs5Unpad(d) // +{ + var m = d.byteLength, + nb = this.blockSize, + q = d[m - 1], + n = m - q; + if (q > nb) + throw DataError('Invalid padding'); + var r = new Uint8Array(n); + if (n > 0) + r.set(new Uint8Array(d.buffer, 0, n)); + return r; +} // + + +/** + * Algorithm name GOST 28147-ZeroPadding

+ * + * Zero padding: 8-x remaining bytes are filled with zero + * + * @memberOf GostCipher + * @method padding + * @instance + * @private + * @param {Uint8Array} d array with source data + * @returns {Uint8Array} result + */ +function zeroPad(d) // +{ + var n = d.byteLength, + nb = this.blockSize, + m = Math.ceil(n / nb) * nb, + r = new Uint8Array(m); + r.set(d); + for (var i = n; i < m; i++) + r[i] = 0; + return r; +} // + + +/** + * Algorithm name GOST 28147-BitPadding

+ * + * Bit padding: P* = P || 1 || 000...0 If there’s no incomplete block, + * one extra block filled with 1 || 000...0 + * + * @memberOf GostCipher + * @method padding + * @instance + * @private + * @param {Uint8Array} d array with source data + * @returns {Uint8Array} result + */ +function bitPad(d) // +{ + var n = d.byteLength, + nb = this.blockSize, + m = Math.ceil((n + 1) / nb) * nb, + r = new Uint8Array(m); + r.set(d); + r[n] = 1; + for (var i = n + 1; i < m; i++) + r[i] = 0; + return r; +} // + +function bitUnpad(d) // +{ + var m = d.byteLength, + n = m; + while (n > 1 && d[n - 1] === 0) + n--; + if (d[n - 1] !== 1) + throw DataError('Invalid padding'); + n--; + var r = new Uint8Array(n); + if (n > 0) + r.set(new Uint8Array(d.buffer, 0, n)); + return r; +} // + +/** + * Algorithm name GOST 28147-RandomPadding

+ * + * Random padding: 8-x remaining bytes of the last block are set to + * random. + * + * @memberOf GostCipher + * @method padding + * @instance + * @private + * @param {Uint8Array} d array with source data + * @returns {Uint8Array} result + */ +function randomPad(d) // +{ + var n = d.byteLength, + nb = this.blockSize, + q = nb - n % nb, + m = Math.ceil(n / nb) * nb, + r = new Uint8Array(m), e = new Uint8Array(r.buffer, n, q); + r.set(d); + randomSeed(e); + return r; +} // + +/** + * GOST 28147-89 Encryption Algorithm

+ * + * References {@link http://tools.ietf.org/html/rfc5830}

+ * + * When keys and initialization vectors are converted to/from byte arrays, + * little-endian byte order is assumed.

+ * + * Normalized algorithm identifier common parameters: + * + *
    + *
  • name Algorithm name 'GOST 28147' or 'GOST R 34.12'
  • + *
  • version Algorithm version, number + *
      + *
    • 1989 Current version of standard
    • + *
    • 2015 New draft version of standard
    • + *
    + *
  • + *
  • length Block length + *
      + *
    • 64 64 bits length (default)
    • + *
    • 128 128 bits length (only for version 2015)
    • + *
    + *
  • + *
  • mode Algorithm mode, string + *
      + *
    • ES Encryption mode (default)
    • + *
    • MAC "imitovstavka" (MAC) mode
    • + *
    • KW Key wrapping mode
    • + *
    + *
  • + *
  • sBox Paramset sBox for GOST 28147-89, string. Used only if version = 1989
  • + *
+ * + * Supported algorithms, modes and parameters: + * + *
    + *
  • Encript/Decrypt mode (ES) + *
      + *
    • block Block mode, string. Default ECB
    • + *
    • keyMeshing Key meshing mode, string. Default NO
    • + *
    • padding Padding mode, string. Default NO for CFB and CTR modes, or ZERO for others
    • + *
    • iv {@link CryptoOperationData} Initial vector with length of block. Default - zero block
    • + *
    + *
  • + *
  • Sign/Verify mode (MAC) + *
      + *
    • macLength Length of mac in bits (default - 32 bits)
    • + *
    • iv {@link CryptoOperationData} Initial vector with length of block. Default - zero block
    • + *
    + *
  • + *
  • Wrap/Unwrap key mode (KW) + *
      + *
    • keyWrapping Mode of keywrapping, string. Default NO - standard GOST key wrapping
    • + *
    • ukm {@link CryptoOperationData} User key material. Default - random generated value
    • + *
    + *
  • + *
+ * + * Supported paramters values: + * + *
    + *
  • Block modes (parameter 'block') + *
      + *
    • ECB "prostaya zamena" (ECB) mode (default)
    • + *
    • CFB "gammirovanie s obratnoj svyaziyu po shifrotekstu" (CFB) mode
    • + *
    • OFB "gammirovanie s obratnoj svyaziyu po vyhodu" (OFB) mode
    • + *
    • CTR "gammirovanie" (counter) mode
    • + *
    • CBC Cipher-Block-Chaining (CBC) mode
    • + *
    + *
  • + *
  • Key meshing modes (parameter 'keyMeshing') + *
      + *
    • NO No key wrapping (default)
    • + *
    • CP CryptoPor Key key meshing
    • + *
    + *
  • + *
  • Padding modes (parameter 'padding') + *
      + *
    • NO No padding only for CFB, OFB and CTR modes
    • + *
    • PKCS5 PKCS#5 padding mode
    • + *
    • ZERO Zero bits padding mode
    • + *
    • RANDOM Random bits padding mode
    • + *
    • BIT One bit padding mode
    • + *
    + *
  • + *
  • Wrapping key modes (parameter 'keyWrapping') + *
      + *
    • NO Ref. rfc4357 6.1 GOST 28147-89 Key wrapping
    • + *
    • CP CryptoPro Key wrapping mode
    • + *
    • SC SignalCom Key wrapping mode
    • + *
    + *
  • + *
+ * + * @class GostCipher + * @param {AlgorithmIndentifier} algorithm WebCryptoAPI algorithm identifier + */ +function GostCipher(algorithm) // +{ + // Check little endian support + if (!littleEndian) + throw new NotSupportedError('Big endian platform not supported'); + algorithm = algorithm || {}; + this.keySize = 32; + this.blockLength = algorithm.length || 64; + this.blockSize = this.blockLength >> 3; + + this.name = (algorithm.name || (algorithm.version === 1 ? 'RC2' : + algorithm.version === 1989 ? 'GOST 28147' : 'GOST R 34.12')) + + (algorithm.version > 4 ? '-' + ((algorithm.version || 1989) % 100) : '') + '-' + + (this.blockLength === 64 ? '' : this.blockLength + '-') + + ((algorithm.mode === 'MAC') ? 'MAC-' + (algorithm.macLength || this.blockLength >> 1) : + (algorithm.mode === 'KW' || algorithm.keyWrapping) ? + ((algorithm.keyWrapping || 'NO') !== 'NO' ? algorithm.keyWrapping : '') + 'KW' : + (algorithm.block || 'ECB') + ((algorithm.block === 'CFB' || algorithm.block === 'OFB' || + (algorithm.block === 'CTR' && algorithm.version === 2015)) && + algorithm?.shiftBits !== this.blockLength ? '-' + algorithm.shiftBits : '') + + (algorithm.padding ? '-' + (algorithm.padding || (algorithm.block === 'CTR' || + algorithm.block === 'CFB' || algorithm.block === 'OFB' ? 'NO' : 'ZERO')) + 'PADDING' : '') + + ((algorithm.keyMeshing || 'NO') !== 'NO' ? '-CPKEYMESHING' : '')) + + (algorithm.procreator ? '/' + algorithm.procreator : '') + + (typeof algorithm.sBox === 'string' ? '/' + algorithm.sBox : ''); + + // Algorithm procreator + this.procreator = algorithm.procreator; + + switch (algorithm.version || 1989) { + case 1: + this.process = processRC2; + this.keySchedule = keyScheduleRC2; + this.blockLength = 64; + this.effectiveLength = algorithm.length || 32; + this.keySize = 8 * Math.ceil(this.effectiveLength / 8); // Max 128 + this.blockSize = this.blockLength >> 3; + break; + case 2015: + this.version = 2015; + if (this.blockLength === 64) { + this.process = process15; + this.keySchedule = keySchedule15; + } else if (this.blockLength === 128) { + this.process = process128; + this.keySchedule = keySchedule128; + } else + throw new DataError('Invalid block length'); + this.processMAC = processMAC15; + break; + case 1989: + this.version = 1989; + this.process = process89; + this.processMAC = processMAC89; + this.keySchedule = keySchedule89; + if (this.blockLength !== 64) + throw new DataError('Invalid block length'); + break; + default: + throw new NotSupportedError('Algorithm version ' + algorithm.version + ' not supported'); + } + + switch (algorithm.mode || (algorithm.keyWrapping && 'KW') || 'ES') { + + case 'ES': + switch (algorithm.block || 'ECB') { + case 'ECB': + this.encrypt = encryptECB; + this.decrypt = decryptECB; + break; + case 'CTR': + if (this.version === 1989) { + this.encrypt = processCTR89; + this.decrypt = processCTR89; + } else { + this.encrypt = processCTR15; + this.decrypt = processCTR15; + this.shiftBits = algorithm.shiftBits || this.blockLength; + } + break + case 'CBC': + this.encrypt = encryptCBC; + this.decrypt = decryptCBC; + break + case 'CFB': + this.encrypt = encryptCFB; + this.decrypt = decryptCFB; + this.shiftBits = algorithm.shiftBits || this.blockLength; + break; + case 'OFB': + this.encrypt = processOFB; + this.decrypt = processOFB; + this.shiftBits = algorithm.shiftBits || this.blockLength; + break; + default: + throw new NotSupportedError('Block mode ' + algorithm.block + ' not supported'); + } + switch (algorithm.keyMeshing) { + case 'CP': + this.keyMeshing = keyMeshingCP; + break; + default: + this.keyMeshing = noKeyMeshing; + } + if (this.encrypt === encryptECB || this.encrypt === encryptCBC) { + switch (algorithm.padding) { + case 'PKCS5P': + this.pad = pkcs5Pad; + this.unpad = pkcs5Unpad; + break; + case 'RANDOM': + this.pad = randomPad; + this.unpad = noPad; + break; + case 'BIT': + this.pad = bitPad; + this.unpad = bitUnpad; + break; + default: + this.pad = zeroPad; + this.unpad = noPad; + } + } else { + this.pad = noPad; + this.unpad = noPad; + } + this.generateKey = generateKey; + break; + case 'MAC': + this.sign = signMAC; + this.verify = verifyMAC; + this.generateKey = generateKey; + this.macLength = algorithm.macLength || (this.blockLength >> 1); + this.pad = noPad; + this.unpad = noPad; + this.keyMeshing = noKeyMeshing; + break; + case 'KW': + this.pad = noPad; + this.unpad = noPad; + this.keyMeshing = noKeyMeshing; + switch (algorithm.keyWrapping) { + case 'CP': + this.wrapKey = wrapKeyCP; + this.unwrapKey = unwrapKeyCP; + this.generateKey = generateKey; + this.shiftBits = algorithm.shiftBits || this.blockLength; + break; + case 'SC': + this.wrapKey = wrapKeySC; + this.unwrapKey = unwrapKeySC; + this.generateKey = generateWrappingKeySC; + break; + default: + this.wrapKey = wrapKeyGOST; + this.unwrapKey = unwrapKeyGOST; + this.generateKey = generateKey; + } + break; + case 'MASK': + this.wrapKey = wrapKeyMask; + this.unwrapKey = unwrapKeyMask; + this.generateKey = generateKey; + break; + default: + throw new NotSupportedError('Mode ' + algorithm.mode + ' not supported'); + } + + // Define sBox parameter + var sBox = algorithm.sBox, sBoxName; + if (!sBox) + sBox = this.version === 2015 ? sBoxes['E-Z'] : this.procreator === 'SC' ? sBoxes['E-SC'] : sBoxes['E-A']; + else if (typeof sBox === 'string') { + sBoxName = sBox.toUpperCase(); + sBox = sBoxes[sBoxName]; + if (!sBox) + throw new SyntaxError('Unknown sBox name: ' + algorithm.sBox); + } else if (!sBox.length || sBox.length !== sBoxes['E-Z'].length) + throw new SyntaxError('Length of sBox must be ' + sBoxes['E-Z'].length); + this.sBox = sBox; + // Initial vector + if (algorithm.iv) { + this.iv = new Uint8Array(algorithm.iv); + if (this.iv.byteLength !== this.blockSize && this.version === 1989) + throw new SyntaxError('Length of iv must be ' + this.blockLength + ' bits'); + else if (this.iv.byteLength !== this.blockSize >> 1 && this.encrypt === processCTR15) + throw new SyntaxError('Length of iv must be ' + this.blockLength >> 1 + ' bits'); + else if (this.iv.byteLength % this.blockSize !== 0 && this.encrypt !== processCTR15) + throw new SyntaxError('Length of iv must be a multiple of ' + this.blockLength + ' bits'); + } else + this.iv = this.blockLength === 128 ? defaultIV128 : defaultIV; + // User key material + if (algorithm.ukm) { + this.ukm = new Uint8Array(algorithm.ukm); + if (this.ukm.byteLength * 8 !== this.blockLength) + throw new SyntaxError('Length of ukm must be ' + this.blockLength + ' bits'); + } +} // + +export default GostCipher; diff --git a/plugins/srktoolbox/src/core/vendor/gost/gostCoding.mjs b/plugins/srktoolbox/src/core/vendor/gost/gostCoding.mjs new file mode 100644 index 00000000..ed42b3cc --- /dev/null +++ b/plugins/srktoolbox/src/core/vendor/gost/gostCoding.mjs @@ -0,0 +1,1160 @@ +/** + * Coding algorithms: Base64, Hex, Int16, Chars, BER and PEM + * version 1.76 + * 2014-2016, Rudolf Nickolaev. All rights reserved. + * + * Exported for CyberChef by mshwed [m@ttshwed.com] + */ + +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * THIS SOfTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES Of MERCHANTABILITY AND fITNESS fOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * fOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT Of SUBSTITUTE GOODS OR + * SERVICES; LOSS Of USE, DATA, OR PROfITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY Of LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT Of THE USE + * Of THIS SOfTWARE, EVEN If ADVISED Of THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +import gostCrypto from './gostCrypto.mjs'; + +/** + * The Coding interface provides string converting methods: Base64, Hex, + * Int16, Chars, BER and PEM + * @class GostCoding + * + */ // +var root = {}; +var DataError = Error; +var CryptoOperationData = ArrayBuffer; +var Date = Date; + +function buffer(d) { + if (d instanceof CryptoOperationData) + return d; + else if (d && d?.buffer instanceof CryptoOperationData) + return d.byteOffset === 0 && d.byteLength === d.buffer.byteLength ? + d.buffer : new Uint8Array(new Uint8Array(d, d.byteOffset, d.byteLength)).buffer; + else + throw new DataError('CryptoOperationData required'); +} // + +function GostCoding() { +} + +/** + * BASE64 conversion + * + * @class GostCoding.Base64 + */ +var Base64 = {// + /** + * Base64.decode convert BASE64 string s to CryptoOperationData + * + * @memberOf GostCoding.Base64 + * @param {String} s BASE64 encoded string value + * @returns {CryptoOperationData} Binary decoded data + */ + decode: function (s) { + s = s.replace(/[^A-Za-z0-9\+\/]/g, ''); + var n = s.length, + k = n * 3 + 1 >> 2, r = new Uint8Array(k); + + for (var m3, m4, u24 = 0, j = 0, i = 0; i < n; i++) { + m4 = i & 3; + var c = s.charCodeAt(i); + + c = c > 64 && c < 91 ? + c - 65 : c > 96 && c < 123 ? + c - 71 : c > 47 && c < 58 ? + c + 4 : c === 43 ? + 62 : c === 47 ? + 63 : 0; + + u24 |= c << 18 - 6 * m4; + if (m4 === 3 || n - i === 1) { + for (m3 = 0; m3 < 3 && j < k; m3++, j++) { + r[j] = u24 >>> (16 >>> m3 & 24) & 255; + } + u24 = 0; + + } + } + return r.buffer; + }, + /** + * Base64.encode(data) convert CryptoOperationData data to BASE64 string + * + * @memberOf GostCoding.Base64 + * @param {CryptoOperationData} data Bynary data for encoding + * @returns {String} BASE64 encoded data + */ + encode: function (data) { + var slen = 8, d = new Uint8Array(buffer(data)); + var m3 = 2, s = ''; + for (var n = d.length, u24 = 0, i = 0; i < n; i++) { + m3 = i % 3; + if (i > 0 && (i * 4 / 3) % (12 * slen) === 0) + s += '\r\n'; + u24 |= d[i] << (16 >>> m3 & 24); + if (m3 === 2 || n - i === 1) { + for (var j = 18; j >= 0; j -= 6) { + var c = u24 >>> j & 63; + c = c < 26 ? c + 65 : c < 52 ? c + 71 : c < 62 ? c - 4 : + c === 62 ? 43 : c === 63 ? 47 : 65; + s += String.fromCharCode(c); + } + u24 = 0; + } + } + return s.substr(0, s.length - 2 + m3) + (m3 === 2 ? '' : m3 === 1 ? '=' : '=='); + } // +}; + +/** + * BASE64 conversion + * + * @memberOf GostCoding + * @insnance + * @type GostCoding.Base64 + */ +GostCoding.prototype.Base64 = Base64; + +/** + * Text string conversion
+ * Methods support charsets: ascii, win1251, utf8, utf16 (ucs2, unicode), utf32 (ucs4) + * + * @class GostCoding.Chars + */ +var Chars = (function () { // + + var _win1251_ = { + 0x402: 0x80, 0x403: 0x81, 0x201A: 0x82, 0x453: 0x83, 0x201E: 0x84, 0x2026: 0x85, 0x2020: 0x86, 0x2021: 0x87, + 0x20AC: 0x88, 0x2030: 0x89, 0x409: 0x8A, 0x2039: 0x8B, 0x40A: 0x8C, 0x40C: 0x8D, 0x40B: 0x8E, 0x40f: 0x8f, + 0x452: 0x90, 0x2018: 0x91, 0x2019: 0x92, 0x201C: 0x93, 0x201D: 0x94, 0x2022: 0x95, 0x2013: 0x96, 0x2014: 0x97, + 0x2122: 0x99, 0x459: 0x9A, 0x203A: 0x9B, 0x45A: 0x9C, 0x45C: 0x9D, 0x45B: 0x9E, 0x45f: 0x9f, + 0xA0: 0xA0, 0x40E: 0xA1, 0x45E: 0xA2, 0x408: 0xA3, 0xA4: 0xA4, 0x490: 0xA5, 0xA6: 0xA6, 0xA7: 0xA7, + 0x401: 0xA8, 0xA9: 0xA9, 0x404: 0xAA, 0xAB: 0xAB, 0xAC: 0xAC, 0xAD: 0xAD, 0xAE: 0xAE, 0x407: 0xAf, + 0xB0: 0xB0, 0xB1: 0xB1, 0x406: 0xB2, 0x456: 0xB3, 0x491: 0xB4, 0xB5: 0xB5, 0xB6: 0xB6, 0xB7: 0xB7, + 0x451: 0xB8, 0x2116: 0xB9, 0x454: 0xBA, 0xBB: 0xBB, 0x458: 0xBC, 0x405: 0xBD, 0x455: 0xBE, 0x457: 0xBf + }; + var _win1251back_ = {}; + for (var from in _win1251_) { + var to = _win1251_[from]; + _win1251back_[to] = from; + } + + return { + /** + * Chars.decode(s, charset) convert string s with defined charset to CryptoOperationData + * + * @memberOf GostCoding.Chars + * @param {string} s Javascript string + * @param {string} charset Charset, default 'win1251' + * @returns {CryptoOperationData} Decoded binary data + */ + decode: function (s, charset) { + charset = (charset || 'win1251').toLowerCase().replace('-', ''); + var r = []; + for (var i = 0, j = s.length; i < j; i++) { + var c = s.charCodeAt(i); + if (charset === 'utf8') { + if (c < 0x80) { + r.push(c); + } else if (c < 0x800) { + r.push(0xc0 + (c >>> 6)); + r.push(0x80 + (c & 63)); + } else if (c < 0x10000) { + r.push(0xe0 + (c >>> 12)); + r.push(0x80 + (c >>> 6 & 63)); + r.push(0x80 + (c & 63)); + } else if (c < 0x200000) { + r.push(0xf0 + (c >>> 18)); + r.push(0x80 + (c >>> 12 & 63)); + r.push(0x80 + (c >>> 6 & 63)); + r.push(0x80 + (c & 63)); + } else if (c < 0x4000000) { + r.push(0xf8 + (c >>> 24)); + r.push(0x80 + (c >>> 18 & 63)); + r.push(0x80 + (c >>> 12 & 63)); + r.push(0x80 + (c >>> 6 & 63)); + r.push(0x80 + (c & 63)); + } else { + r.push(0xfc + (c >>> 30)); + r.push(0x80 + (c >>> 24 & 63)); + r.push(0x80 + (c >>> 18 & 63)); + r.push(0x80 + (c >>> 12 & 63)); + r.push(0x80 + (c >>> 6 & 63)); + r.push(0x80 + (c & 63)); + } + } else if (charset === 'unicode' || charset === 'ucs2' || charset === 'utf16') { + if (c < 0xD800 || (c >= 0xE000 && c <= 0x10000)) { + r.push(c >>> 8); + r.push(c & 0xff); + } else if (c >= 0x10000 && c < 0x110000) { + c -= 0x10000; + var first = ((0xffc00 & c) >> 10) + 0xD800; + var second = (0x3ff & c) + 0xDC00; + r.push(first >>> 8); + r.push(first & 0xff); + r.push(second >>> 8); + r.push(second & 0xff); + } + } else if (charset === 'utf32' || charset === 'ucs4') { + r.push(c >>> 24 & 0xff); + r.push(c >>> 16 & 0xff); + r.push(c >>> 8 & 0xff); + r.push(c & 0xff); + } else if (charset === 'win1251') { + if (c >= 0x80) { + if (c >= 0x410 && c < 0x450) // А..Яа..я + c -= 0x350; + else + c = _win1251_[c] || 0; + } + r.push(c); + } else + r.push(c & 0xff); + } + return new Uint8Array(r).buffer; + }, + /** + * Chars.encode(data, charset) convert CryptoOperationData data to string with defined charset + * + * @memberOf GostCoding.Chars + * @param {CryptoOperationData} data Binary data + * @param {string} charset Charset, default win1251 + * @returns {string} Encoded javascript string + */ + encode: function (data, charset) { + charset = (charset || 'win1251').toLowerCase().replace('-', ''); + var r = [], d = new Uint8Array(buffer(data)); + for (var i = 0, n = d.length; i < n; i++) { + var c = d[i]; + if (charset === 'utf8') { + c = c >= 0xfc && c < 0xfe && i + 5 < n ? // six bytes + (c - 0xfc) * 1073741824 + (d[++i] - 0x80 << 24) + (d[++i] - 0x80 << 18) + (d[++i] - 0x80 << 12) + (d[++i] - 0x80 << 6) + d[++i] - 0x80 + : c >> 0xf8 && c < 0xfc && i + 4 < n ? // five bytes + (c - 0xf8 << 24) + (d[++i] - 0x80 << 18) + (d[++i] - 0x80 << 12) + (d[++i] - 0x80 << 6) + d[++i] - 0x80 + : c >> 0xf0 && c < 0xf8 && i + 3 < n ? // four bytes + (c - 0xf0 << 18) + (d[++i] - 0x80 << 12) + (d[++i] - 0x80 << 6) + d[++i] - 0x80 + : c >= 0xe0 && c < 0xf0 && i + 2 < n ? // three bytes + (c - 0xe0 << 12) + (d[++i] - 0x80 << 6) + d[++i] - 0x80 + : c >= 0xc0 && c < 0xe0 && i + 1 < n ? // two bytes + (c - 0xc0 << 6) + d[++i] - 0x80 + : c; // one byte + } else if (charset === 'unicode' || charset === 'ucs2' || charset === 'utf16') { + c = (c << 8) + d[++i]; + if (c >= 0xD800 && c < 0xE000) { + var first = (c - 0xD800) << 10; + c = d[++i]; + c = (c << 8) + d[++i]; + var second = c - 0xDC00; + c = first + second + 0x10000; + } + } else if (charset === 'utf32' || charset === 'ucs4') { + c = (c << 8) + d[++i]; + c = (c << 8) + d[++i]; + c = (c << 8) + d[++i]; + } else if (charset === 'win1251') { + if (c >= 0x80) { + if (c >= 0xC0 && c < 0x100) + c += 0x350; // А..Яа..я + else + c = _win1251back_[c] || 0; + } + } + r.push(String.fromCharCode(c)); + } + return r.join(''); + } + }; // +})(); + +/** + * Text string conversion + * + * @memberOf GostCoding + * @insnance + * @type GostCoding.Chars + */ +GostCoding.prototype.Chars = Chars; + +/** + * HEX conversion + * + * @class GostCoding.Hex + */ +var Hex = {// + /** + * Hex.decode(s, endean) convert HEX string s to CryptoOperationData in endean mode + * + * @memberOf GostCoding.Hex + * @param {string} s Hex encoded string + * @param {boolean} endean Little or Big Endean, default Little + * @returns {CryptoOperationData} Decoded binary data + */ + decode: function (s, endean) { + s = s.replace(/[^A-Fa-f0-9]/g, ''); + var n = Math.ceil(s.length / 2), r = new Uint8Array(n); + s = (s.length % 2 > 0 ? '0' : '') + s; + if (endean && ((typeof endean !== 'string') || + (endean.toLowerCase().indexOf('little') < 0))) + for (var i = 0; i < n; i++) + r[i] = parseInt(s.substr((n - i - 1) * 2, 2), 16); + else + for (var i = 0; i < n; i++) + r[i] = parseInt(s.substr(i * 2, 2), 16); + return r.buffer; + }, + /** + * Hex.encode(data, endean) convert CryptoOperationData data to HEX string in endean mode + * + * @memberOf GostCoding.Hex + * @param {CryptoOperationData} data Binary data + * @param {boolean} endean Little/Big Endean, default Little + * @returns {string} Hex decoded string + */ + encode: function (data, endean) { + var s = [], d = new Uint8Array(buffer(data)), n = d.length; + if (endean && ((typeof endean !== 'string') || + (endean.toLowerCase().indexOf('little') < 0))) + for (var i = 0; i < n; i++) { + var j = n - i - 1; + s[j] = (j > 0 && j % 32 === 0 ? '\r\n' : '') + + ('00' + d[i].toString(16)).slice(-2); + } + else + for (var i = 0; i < n; i++) + s[i] = (i > 0 && i % 32 === 0 ? '\r\n' : '') + + ('00' + d[i].toString(16)).slice(-2); + return s.join(''); + } // +}; + +/** + * HEX conversion + * @memberOf GostCoding + * @insnance + * @type GostCoding.Hex + */ +GostCoding.prototype.Hex = Hex; + +/** + * String hex-encoded integer conversion + * + * @class GostCoding.Int16 + */ +var Int16 = {// + /** + * Int16.decode(s) convert hex big insteger s to CryptoOperationData + * + * @memberOf GostCoding.Int16 + * @param {string} s Int16 string + * @returns {CryptoOperationData} Decoded binary data + */ + decode: function (s) { + s = (s || '').replace(/[^\-A-Fa-f0-9]/g, ''); + if (s.length === 0) + s = '0'; + // Signature + var neg = false; + if (s.charAt(0) === '-') { + neg = true; + s = s.substring(1); + } + // Align 2 chars + while (s.charAt(0) === '0' && s.length > 1) + s = s.substring(1); + s = (s.length % 2 > 0 ? '0' : '') + s; + // Padding for singanuture + // '800000' - 'ffffff' - for positive + // '800001' - 'ffffff' - for negative + if ((!neg && !/^[0-7]/.test(s)) || + (neg && !/^[0-7]|8[0]+$/.test(s))) + s = '00' + s; + // Convert hex + var n = s.length / 2, r = new Uint8Array(n), t = 0; + for (var i = n - 1; i >= 0; --i) { + var c = parseInt(s.substr(i * 2, 2), 16); + if (neg && (c + t > 0)) { + c = 256 - c - t; + t = 1; + } + r[i] = c; + } + return r.buffer; + }, + /** + * Int16.encode(data) convert CryptoOperationData data to big integer hex string + * + * @memberOf GostCoding.Int16 + * @param {CryptoOperationData} data Binary data + * @returns {string} Int16 encoded string + */ + encode: function (data) { + var d = new Uint8Array(buffer(data)), n = d.length; + if (d.length === 0) + return '0x00'; + var s = [], neg = d[0] > 0x7f, t = 0; + for (var i = n - 1; i >= 0; --i) { + var v = d[i]; + if (neg && (v + t > 0)) { + v = 256 - v - t; + t = 1; + } + s[i] = ('00' + v.toString(16)).slice(-2); + } + s = s.join(''); + while (s.charAt(0) === '0') + s = s.substring(1); + return (neg ? '-' : '') + '0x' + s; + } // +}; + +/** + * String hex-encoded integer conversion + * @memberOf GostCoding + * @insnance + * @type GostCoding.Int16 + */ +GostCoding.prototype.Int16 = Int16; + +/** + * BER, DER, CER conversion + * + * @class GostCoding.BER + */ +var BER = (function () { // + + // Predefenition block + function encodeBER(source, format, onlyContent) { + // Correct primitive type + var object = source.object; + if (object === undefined) + object = source; + + // Determinate tagClass + var tagClass = source.tagClass = source.tagClass || 0; // Universial default + + // Determinate tagNumber. Use only for Universal class + if (tagClass === 0) { + var tagNumber = source.tagNumber; + if (typeof tagNumber === 'undefined') { + if (typeof object === 'string') { + if (object === '') // NULL + tagNumber = 0x05; + else if (/^\-?0x[0-9a-fA-F]+$/.test(object)) // INTEGER + tagNumber = 0x02; + else if (/^(\d+\.)+\d+$/.test(object)) // OID + tagNumber = 0x06; + else if (/^[01]+$/.test(object)) // BIT STRING + tagNumber = 0x03; + else if (/^(true|false)$/.test(object)) // BOOLEAN + tagNumber = 0x01; + else if (/^[0-9a-fA-F]+$/.test(object)) // OCTET STRING + tagNumber = 0x04; + else + tagNumber = 0x13; // Printable string (later can be changed to UTF8String) + } else if (typeof object === 'number') { // INTEGER + tagNumber = 0x02; + } else if (typeof object === 'boolean') { // BOOLEAN + tagNumber = 0x01; + } else if (object instanceof Array) { // SEQUENCE + tagNumber = 0x10; + } else if (object instanceof Date) { // GeneralizedTime + tagNumber = 0x18; + } else if (object instanceof CryptoOperationData || (object && object.buffer instanceof CryptoOperationData)) { + tagNumber = 0x04; + } else + throw new DataError('Unrecognized type for ' + object); + } + } + + // Determinate constructed + var tagConstructed = source.tagConstructed; + if (typeof tagConstructed === 'undefined') + tagConstructed = source.tagConstructed = object instanceof Array; + + // Create content + var content; + if (object instanceof CryptoOperationData || (object && object.buffer instanceof CryptoOperationData)) { // Direct + content = new Uint8Array(buffer(object)); + if (tagNumber === 0x03) { // BITSTRING + // Set unused bits + var a = new Uint8Array(buffer(content)); + content = new Uint8Array(a.length + 1); + content[0] = 0; // No unused bits + content.set(a, 1); + } + } else if (tagConstructed) { // Sub items coding + if (object instanceof Array) { + var bytelen = 0, ba = [], offset = 0; + for (var i = 0, n = object.length; i < n; i++) { + ba[i] = encodeBER(object[i], format); + bytelen += ba[i].length; + } + if (tagNumber === 0x11) + ba.sort(function (a, b) { // Sort order for SET components + for (var i = 0, n = Math.min(a.length, b.length); i < n; i++) { + var r = a[i] - b[i]; + if (r !== 0) + return r; + } + return a.length - b.length; + }); + if (format === 'CER') { // final for CER 00 00 + ba[n] = new Uint8Array(2); + bytelen += 2; + } + content = new Uint8Array(bytelen); + for (var i = 0, n = ba.length; i < n; i++) { + content.set(ba[i], offset); + offset = offset + ba[i].length; + } + } else + throw new DataError('Constracted block can\'t be primitive'); + } else { + switch (tagNumber) { + // 0x00: // EOC + case 0x01: // BOOLEAN + content = new Uint8Array(1); + content[0] = object ? 0xff : 0; + break; + case 0x02: // INTEGER + case 0x0a: // ENUMIRATED + content = Int16.decode( + typeof object === 'number' ? object.toString(16) : object); + break; + case 0x03: // BIT STRING + if (typeof object === 'string') { + var unusedBits = 7 - (object.length + 7) % 8; + var n = Math.ceil(object.length / 8); + content = new Uint8Array(n + 1); + content[0] = unusedBits; + for (var i = 0; i < n; i++) { + var c = 0; + for (var j = 0; j < 8; j++) { + var k = i * 8 + j; + c = (c << 1) + (k < object.length ? (object.charAt(k) === '1' ? 1 : 0) : 0); + } + content[i + 1] = c; + } + } + break; + case 0x04: + content = Hex.decode( + typeof object === 'number' ? object.toString(16) : object); + break; + // case 0x05: // NULL + case 0x06: // OBJECT IDENTIFIER + var a = object.match(/\d+/g), r = []; + for (var i = 1; i < a.length; i++) { + var n = +a[i], r1 = []; + if (i === 1) + n = n + a[0] * 40; + do { + r1.push(n & 0x7F); + n = n >>> 7; + } while (n); + // reverse order + for (j = r1.length - 1; j >= 0; --j) + r.push(r1[j] + (j === 0 ? 0x00 : 0x80)); + } + content = new Uint8Array(r); + break; + // case 0x07: // ObjectDescriptor + // case 0x08: // EXTERNAL + // case 0x09: // REAL + // case 0x0A: // ENUMERATED + // case 0x0B: // EMBEDDED PDV + case 0x0C: // UTF8String + content = Chars.decode(object, 'utf8'); + break; + // case 0x10: // SEQUENCE + // case 0x11: // SET + case 0x12: // NumericString + case 0x16: // IA5String // ASCII + case 0x13: // PrintableString // ASCII subset + case 0x14: // TeletexString // aka T61String + case 0x15: // VideotexString + case 0x19: // GraphicString + case 0x1A: // VisibleString // ASCII subset + case 0x1B: // GeneralString + // Reflect on character encoding + for (var i = 0, n = object.length; i < n; i++) + if (object.charCodeAt(i) > 255) + tagNumber = 0x0C; + if (tagNumber === 0x0C) + content = Chars.decode(object, 'utf8'); + else + content = Chars.decode(object, 'ascii'); + break; + case 0x17: // UTCTime + case 0x18: // GeneralizedTime + var result = object.original; + if (!result) { + var date = new Date(object); + date.setMinutes(date.getMinutes() + date.getTimezoneOffset()); // to UTC + var ms = tagNumber === 0x18 ? date.getMilliseconds().toString() : ''; // Milliseconds, remove trailing zeros + while (ms.length > 0 && ms.charAt(ms.length - 1) === '0') + ms = ms.substring(0, ms.length - 1); + if (ms.length > 0) + ms = '.' + ms; + result = (tagNumber === 0x17 ? date.getYear().toString().slice(-2) : date.getFullYear().toString()) + + ('00' + (date.getMonth() + 1)).slice(-2) + + ('00' + date.getDate()).slice(-2) + + ('00' + date.getHours()).slice(-2) + + ('00' + date.getMinutes()).slice(-2) + + ('00' + date.getSeconds()).slice(-2) + ms + 'Z'; + } + content = Chars.decode(result, 'ascii'); + break; + case 0x1C: // UniversalString + content = Chars.decode(object, 'utf32'); + break; + case 0x1E: // BMPString + content = Chars.decode(object, 'utf16'); + break; + } + } + + if (!content) + content = new Uint8Array(0); + if (content instanceof CryptoOperationData) + content = new Uint8Array(content); + + if (!tagConstructed && format === 'CER') { + // Encoding CER-form for string types + var k; + switch (tagNumber) { + case 0x03: // BIT_STRING + k = 1; // ingnore unused bit for bit string + case 0x04: // OCTET_STRING + case 0x0C: // UTF8String + case 0x12: // NumericString + case 0x13: // PrintableString + case 0x14: // TeletexString + case 0x15: // VideotexString + case 0x16: // IA5String + case 0x19: // GraphicString + case 0x1A: // VisibleString + case 0x1B: // GeneralString + case 0x1C: // UniversalString + case 0x1E: // BMPString + k = k || 0; + // Split content on 1000 octet len parts + var size = 1000; + var bytelen = 0, ba = [], offset = 0; + for (var i = k, n = content.length; i < n; i += size - k) { + ba[i] = encodeBER({ + object: new Unit8Array(content.buffer, i, Math.min(size - k, n - i)), + tagNumber: tagNumber, + tagClass: 0, + tagConstructed: false + }, format); + bytelen += ba[i].length; + } + ba[n] = new Uint8Array(2); // final for CER 00 00 + bytelen += 2; + content = new Uint8Array(bytelen); + for (var i = 0, n = ba.length; i < n; i++) { + content.set(ba[i], offset); + offset = offset + ba[i].length; + } + } + } + + // Restore tagNumber for all classes + if (tagClass === 0) + source.tagNumber = tagNumber; + else + source.tagNumber = tagNumber = source.tagNumber || 0; + source.content = content; + + if (onlyContent) + return content; + + // Create header + // tagNumber + var ha = [], first = tagClass === 3 ? 0xC0 : tagClass === 2 ? 0x80 : + tagClass === 1 ? 0x40 : 0x00; + if (tagConstructed) + first |= 0x20; + if (tagNumber < 0x1F) { + first |= tagNumber & 0x1F; + ha.push(first); + } else { + first |= 0x1F; + ha.push(first); + var n = tagNumber, ha1 = []; + do { + ha1.push(n & 0x7F); + n = n >>> 7; + } while (n) + // reverse order + for (var j = ha1.length - 1; j >= 0; --j) + ha.push(ha1[j] + (j === 0 ? 0x00 : 0x80)); + } + // Length + if (tagConstructed && format === 'CER') { + ha.push(0x80); + } else { + var len = content.length; + if (len > 0x7F) { + var l2 = len, ha2 = []; + do { + ha2.push(l2 & 0xff); + l2 = l2 >>> 8; + } while (l2); + ha.push(ha2.length + 0x80); // reverse order + for (var j = ha2.length - 1; j >= 0; --j) + ha.push(ha2[j]); + } else { + // simple len + ha.push(len); + } + } + var header = source.header = new Uint8Array(ha); + + // Result - complete buffer + var block = new Uint8Array(header.length + content.length); + block.set(header, 0); + block.set(content, header.length); + return block; + } + + function decodeBER(source, offset) { + + // start pos + var pos = offset || 0, start = pos; + var tagNumber, tagClass, tagConstructed, + content, header, buffer, sub, len; + + if (source.object) { + // Ready from source + tagNumber = source.tagNumber; + tagClass = source.tagClass; + tagConstructed = source.tagConstructed; + content = source.content; + header = source.header; + buffer = source.object instanceof CryptoOperationData ? + new Uint8Array(source.object) : null; + sub = source.object instanceof Array ? source.object : null; + len = buffer && buffer.length || null; + } else { + // Decode header + var d = source; + + // Read tag + var buf = d[pos++]; + tagNumber = buf & 0x1f; + tagClass = buf >> 6; + tagConstructed = (buf & 0x20) !== 0; + if (tagNumber === 0x1f) { // long tag + tagNumber = 0; + do { + if (tagNumber > 0x1fffffffffff80) + throw new DataError('Convertor not supported tag number more then (2^53 - 1) at position ' + offset); + buf = d[pos++]; + tagNumber = (tagNumber << 7) + (buf & 0x7f); + } while (buf & 0x80); + } + + // Read len + buf = d[pos++]; + len = buf & 0x7f; + if (len !== buf) { + if (len > 6) // no reason to use Int10, as it would be a huge buffer anyways + throw new DataError('Length over 48 bits not supported at position ' + offset); + if (len === 0) + len = null; // undefined + else { + buf = 0; + for (var i = 0; i < len; ++i) + buf = (buf << 8) + d[pos++]; + len = buf; + } + } + + start = pos; + sub = null; + + if (tagConstructed) { + // must have valid content + sub = []; + if (len !== null) { + // definite length + var end = start + len; + while (pos < end) { + var s = decodeBER(d, pos); + sub.push(s); + pos += s.header.length + s.content.length; + } + if (pos !== end) + throw new DataError('Content size is not correct for container starting at offset ' + start); + } else { + // undefined length + try { + for (; ; ) { + var s = decodeBER(d, pos); + pos += s.header.length + s.content.length; + if (s.tagClass === 0x00 && s.tagNumber === 0x00) + break; + sub.push(s); + } + len = pos - start; + } catch (e) { + throw new DataError('Exception ' + e + ' while decoding undefined length content at offset ' + start); + } + } + } + + // Header and content + header = new Uint8Array(d.buffer, offset, start - offset); + content = new Uint8Array(d.buffer, start, len); + buffer = content; + } + + // Constructed types - check for string concationation + if (sub !== null && tagClass === 0) { + var k; + switch (tagNumber) { + case 0x03: // BIT_STRING + k = 1; // ingnore unused bit for bit string + case 0x04: // OCTET_STRING + case 0x0C: // UTF8String + case 0x12: // NumericString + case 0x13: // PrintableString + case 0x14: // TeletexString + case 0x15: // VideotexString + case 0x16: // IA5String + case 0x19: // GraphicString + case 0x1A: // VisibleString + case 0x1B: // GeneralString + case 0x1C: // UniversalString + case 0x1E: // BMPString + k = k || 0; + // Concatination + if (sub.length === 0) + throw new DataError('No constructed encoding content of string type at offset ' + start); + len = k; + for (var i = 0, n = sub.length; i < n; i++) { + var s = sub[i]; + if (s.tagClass !== tagClass || s.tagNumber !== tagNumber || s.tagConstructed) + throw new DataError('Invalid constructed encoding of string type at offset ' + start); + len += s.content.length - k; + } + buffer = new Uint8Array(len); + for (var i = 0, n = sub.length, j = k; i < n; i++) { + var s = sub[i]; + if (k > 0) + buffer.set(s.content.subarray(1), j); + else + buffer.set(s.content, j); + j += s.content.length - k; + } + tagConstructed = false; // follow not required + sub = null; + break; + } + } + // Primitive types + var object = ''; + if (sub === null) { + if (len === null) + throw new DataError('Invalid tag with undefined length at offset ' + start); + + if (tagClass === 0) { + switch (tagNumber) { + case 0x01: // BOOLEAN + object = buffer[0] !== 0; + break; + case 0x02: // INTEGER + case 0x0a: // ENUMIRATED + if (len > 6) { + object = Int16.encode(buffer); + } else { + var v = buffer[0]; + if (buffer[0] > 0x7f) + v = v - 256; + for (var i = 1; i < len; i++) + v = v * 256 + buffer[i]; + object = v; + } + break; + case 0x03: // BIT_STRING + if (len > 5) { // Content buffer + object = new Uint8Array(buffer.subarray(1)).buffer; + } else { // Max bit mask only for 32 bit + var unusedBit = buffer[0], + skip = unusedBit, s = []; + for (var i = len - 1; i >= 1; --i) { + var b = buffer[i]; + for (var j = skip; j < 8; ++j) + s.push((b >> j) & 1 ? '1' : '0'); + skip = 0; + } + object = s.reverse().join(''); + } + break; + case 0x04: // OCTET_STRING + object = new Uint8Array(buffer).buffer; + break; + // case 0x05: // NULL + case 0x06: // OBJECT_IDENTIFIER + var s = '', + n = 0, + bits = 0; + for (var i = 0; i < len; ++i) { + var v = buffer[i]; + n = (n << 7) + (v & 0x7F); + bits += 7; + if (!(v & 0x80)) { // finished + if (s === '') { + var m = n < 80 ? n < 40 ? 0 : 1 : 2; + s = m + "." + (n - m * 40); + } else + s += "." + n.toString(); + n = 0; + bits = 0; + } + } + if (bits > 0) + throw new DataError('Incompleted OID at offset ' + start); + object = s; + break; + //case 0x07: // ObjectDescriptor + //case 0x08: // EXTERNAL + //case 0x09: // REAL + //case 0x0A: // ENUMERATED + //case 0x0B: // EMBEDDED_PDV + case 0x10: // SEQUENCE + case 0x11: // SET + object = []; + break; + case 0x0C: // UTF8String + object = Chars.encode(buffer, 'utf8'); + break; + case 0x12: // NumericString + case 0x13: // PrintableString + case 0x14: // TeletexString + case 0x15: // VideotexString + case 0x16: // IA5String + case 0x19: // GraphicString + case 0x1A: // VisibleString + case 0x1B: // GeneralString + object = Chars.encode(buffer, 'ascii'); + break; + case 0x1C: // UniversalString + object = Chars.encode(buffer, 'utf32'); + break; + case 0x1E: // BMPString + object = Chars.encode(buffer, 'utf16'); + break; + case 0x17: // UTCTime + case 0x18: // GeneralizedTime + var shortYear = tagNumber === 0x17; + var s = Chars.encode(buffer, 'ascii'), + m = (shortYear ? + /^(\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/ : + /^(\d\d\d\d)(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])([01]\d|2[0-3])(?:([0-5]\d)(?:([0-5]\d)(?:[.,](\d{1,3}))?)?)?(Z|[-+](?:[0]\d|1[0-2])([0-5]\d)?)?$/).exec(s); + if (!m) + throw new DataError('Unrecognized time format "' + s + '" at offset ' + start); + if (shortYear) { + // Where YY is greater than or equal to 50, the year SHALL be interpreted as 19YY; and + // Where YY is less than 50, the year SHALL be interpreted as 20YY + m[1] = +m[1]; + m[1] += (m[1] < 50) ? 2000 : 1900; + } + var dt = new Date(m[1], +m[2] - 1, +m[3], +(m[4] || '0'), +(m[5] || '0'), +(m[6] || '0'), +(m[7] || '0')), + tz = dt.getTimezoneOffset(); + if (m[8] || tagNumber === 0x17) { + if (m[8].toUpperCase() !== 'Z' && m[9]) { + tz = tz + parseInt(m[9]); + } + dt.setMinutes(dt.getMinutes() - tz); + } + dt.original = s; + object = dt; + break; + } + } else // OCTET_STRING + object = new Uint8Array(buffer).buffer; + } else + object = sub; + + // result + return { + tagConstructed: tagConstructed, + tagClass: tagClass, + tagNumber: tagNumber, + header: header, + content: content, + object: object + }; + } + + return { + /** + * BER.decode(object, format) convert javascript object to ASN.1 format CryptoOperationData

+ * If object has members tagNumber, tagClass and tagConstructed + * it is clear define encoding rules. Else method use defaul rules: + *
    + *
  • Empty string or null - NULL
  • + *
  • String starts with '0x' and has 0-9 and a-f characters - INTEGER
  • + *
  • String like d.d.d.d (d - set of digits) - OBJECT IDENTIFIER
  • + *
  • String with characters 0 and 1 - BIT STRING
  • + *
  • Strings 'true' or 'false' - BOOLEAN
  • + *
  • String has only 0-9 and a-f characters - OCTET STRING
  • + *
  • String has only characters with code 0-255 - PrintableString
  • + *
  • Other strings - UTF8String
  • + *
  • Number - INTEGER
  • + *
  • Date - GeneralizedTime
  • + *
  • Boolean - SEQUENCE
  • + *
  • CryptoOperationData - OCTET STRING
  • + *
+ * SEQUENCE or SET arrays recursively encoded for each item.
+ * OCTET STRING and BIT STRING can presents as array with one item. + * It means encapsulates encoding for child element.
+ * + * If CONTEXT or APPLICATION classes item presents as array with one + * item we use EXPLICIT encoding for element, else IMPLICIT encoding.
+ * + * @memberOf GostCoding.BER + * @param {Object} object Object to encoding + * @param {string} format Encoding rule: 'DER' or 'CER', default 'DER' + * @param {boolean} onlyContent Encode content only, without header + * @returns {CryptoOperationData} BER encoded data + */ + encode: function (object, format, onlyContent) { + return encodeBER(object, format, onlyContent).buffer; + }, + /** + * BER.encode(data) convert ASN.1 format CryptoOperationData data to javascript object

+ * + * Conversion rules to javascript object: + *
    + *
  • BOOLEAN - Boolean object
  • + *
  • INTEGER, ENUMIRATED - Integer object if len <= 6 (48 bits) else Int16 encoded string
  • + *
  • BIT STRING - Integer object if len <= 5 (w/o unsedBit octet - 32 bits) else String like '10111100' or Array with one item in case of incapsulates encoding
  • + *
  • OCTET STRING - Hex encoded string or Array with one item in case of incapsulates encoding
  • + *
  • OBJECT IDENTIFIER - String with object identifier
  • + *
  • SEQUENCE, SET - Array of encoded items
  • + *
  • UTF8String, NumericString, PrintableString, TeletexString, VideotexString, + * IA5String, GraphicString, VisibleString, GeneralString, UniversalString, + * BMPString - encoded String
  • + *
  • UTCTime, GeneralizedTime - Date
  • + *
+ * @memberOf GostCoding.BER + * @param {(CryptoOperationData|GostCoding.BER)} data Binary data to decode + * @returns {Object} Javascript object with result of decoding + */ + decode: function (data) { + return decodeBER(data.object ? data : new Uint8Array(buffer(data)), 0); + } + }; //
+})(); + +/** + * BER, DER, CER conversion + * @memberOf GostCoding + * @insnance + * @type GostCoding.BER + */ +GostCoding.prototype.BER = BER; + +/** + * PEM conversion + * @class GostCoding.PEM + */ +var PEM = {// + /** + * PEM.encode(data, name) encode CryptoOperationData to PEM format with name label + * + * @memberOf GostCoding.PEM + * @param {(Object|CryptoOperationData)} data Java script object or BER-encoded binary data + * @param {string} name Name of PEM object: 'certificate', 'private key' etc. + * @returns {string} Encoded object + */ + encode: function (data, name) { + return (name ? '-----BEGIN ' + name.toUpperCase() + '-----\r\n' : '') + + Base64.encode(data instanceof CryptoOperationData ? data : BER.encode(data)) + + (name ? '\r\n-----END ' + name.toUpperCase() + '-----' : ''); + }, + /** + * PEM.decode(s, name, deep) decode PEM format s labeled name to CryptoOperationData or javascript object in according to deep parameter + * + * @memberOf GostCoding.PEM + * @param {string} s PEM encoded string + * @param {string} name Name of PEM object: 'certificate', 'private key' etc. + * @param {boolean} deep If true method do BER-decoding, else only BASE64 decoding + * @param {integer} index Index of decoded value + * @returns {(Object|CryptoOperationData)} Decoded javascript object if deep=true, else CryptoOperationData for father BER decoding + */ + decode: function (s, name, deep, index) { + // Try clear base64 + var re1 = /([A-Za-z0-9\+\/\s\=]+)/g, + valid = re1.exec(s); + if (valid[1].length !== s.length) + valid = false; + if (!valid && name) { + // Try with the name + var re2 = new RegExp( + '-----\\s?BEGIN ' + name.toUpperCase() + + '-----([A-Za-z0-9\\+\\/\\s\\=]+)-----\\s?END ' + + name.toUpperCase() + '-----', 'g'); + valid = re2.exec(s); + } + if (!valid) { + // Try with some name + var re3 = new RegExp( + '-----\\s?BEGIN [A-Z0-9\\s]+' + + '-----([A-Za-z0-9\\+\\/\\s\\=]+)-----\\s?END ' + + '[A-Z0-9\\s]+-----', 'g'); + valid = re3.exec(s); + } + var r = valid && valid[1 + (index || 0)]; + if (!r) + throw new DataError('Not valid PEM format'); + var out = Base64.decode(r); + if (deep) + out = BER.decode(out); + return out; + } // +}; + +/** + * PEM conversion + * @memberOf GostCoding + * @insnance + * @type GostCoding.PEM + */ +GostCoding.prototype.PEM = PEM; + +if (gostCrypto) + /** + * Coding algorithms: Base64, Hex, Int16, Chars, BER and PEM + * + * @memberOf gostCrypto + * @type GostCoding + */ + gostCrypto.coding = new GostCoding(); + +export default GostCoding; diff --git a/plugins/srktoolbox/src/core/vendor/gost/gostCrypto.mjs b/plugins/srktoolbox/src/core/vendor/gost/gostCrypto.mjs new file mode 100644 index 00000000..77132f6c --- /dev/null +++ b/plugins/srktoolbox/src/core/vendor/gost/gostCrypto.mjs @@ -0,0 +1,1653 @@ +/** + * Implementation Web Crypto interfaces for GOST algorithms + * 1.76 + * 2014-2016, Rudolf Nickolaev. All rights reserved. + * + * Exported for CyberChef by mshwed [m@ttshwed.com] + */ + +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +import GostRandom from './gostRandom.mjs'; +import gostEngine from './gostEngine.mjs'; + +import crypto from 'crypto' + +/* +* Algorithm normalization +* +*/ // + +var root = {}; +root.gostEngine = gostEngine; + +var rootCrypto = crypto + +var SyntaxError = Error, + DataError = Error, + NotSupportedError = Error, + OperationError = Error, + InvalidStateError = Error, + InvalidAccessError = Error; + +// Normalize algorithm +function normalize(algorithm, method) { + if (typeof algorithm === 'string' || algorithm instanceof String) + algorithm = {name: algorithm}; + var name = algorithm.name; + if (!name) + throw new SyntaxError('Algorithm name not defined'); + // Extract algorithm modes from name + var modes = name.split('/'), modes = modes[0].split('-').concat(modes.slice(1)); + // Normalize the name with default modes + var na = {}; + name = modes[0].replace(/[\.\s]/g, ''); + modes = modes.slice(1); + if (name.indexOf('28147') >= 0) { + na = { + name: 'GOST 28147', + version: 1989, + mode: (algorithm.mode || (// ES, MAC, KW + (method === 'sign' || method === 'verify') ? 'MAC' : + (method === 'wrapKey' || method === 'unwrapKey') ? 'KW' : 'ES')).toUpperCase(), + length: algorithm.length || 64 + }; + } else if (name.indexOf('3412') >= 0) { + na = { + name: 'GOST R 34.12', + version: 2015, + mode: (algorithm.mode || (// ES, MAC, KW + (method === 'sign' || method === 'verify') ? 'MAC' : + (method === 'wrapKey' || method === 'unwrapKey') ? 'KW' : 'ES')).toUpperCase(), + length: algorithm.length || 64 // 128 + }; + } else if (name.indexOf('3411') >= 0) { + na = { + name: 'GOST R 34.11', + version: 2012, // 1994 + mode: (algorithm.mode || (// HASH, KDF, HMAC, PBKDF2, PFXKDF, CPKDF + (method === 'deriveKey' || method === 'deriveBits') ? 'KDF' : + (method === 'sign' || method === 'verify') ? 'HMAC' : 'HASH')).toUpperCase(), + length: algorithm.length || 256 // 512 + }; + } else if (name.indexOf('3410') >= 0) { + na = { + name: 'GOST R 34.10', + version: 2012, // 1994, 2001 + mode: (algorithm.mode || (// SIGN, DH, MASK + (method === 'deriveKey' || method === 'deriveBits') ? 'DH' : 'SIGN')).toUpperCase(), + length: algorithm.length || 256 // 512 + }; + } else if (name.indexOf('SHA') >= 0) { + na = { + name: 'SHA', + version: (algorithm.length || 160) === 160 ? 1 : 2, // 1, 2 + mode: (algorithm.mode || (// HASH, KDF, HMAC, PBKDF2, PFXKDF + (method === 'deriveKey' || method === 'deriveBits') ? 'KDF' : + (method === 'sign' || method === 'verify') ? 'HMAC' : 'HASH')).toUpperCase(), + length: algorithm.length || 160 + }; + } else if (name.indexOf('RC2') >= 0) { + na = { + name: 'RC2', + version: 1, + mode: (algorithm.mode || (// ES, MAC, KW + (method === 'sign' || method === 'verify') ? 'MAC' : + (method === 'wrapKey' || method === 'unwrapKey') ? 'KW' : 'ES')).toUpperCase(), + length: algorithm.length || 32 // 1 - 1024 + }; + } else if (name.indexOf('PBKDF2') >= 0) { + na = normalize(algorithm.hash, 'digest'); + na.mode = 'PBKDF2'; + } else if (name.indexOf('PFXKDF') >= 0) { + na = normalize(algorithm.hash, 'digest'); + na.mode = 'PFXKDF'; + } else if (name.indexOf('CPKDF') >= 0) { + na = normalize(algorithm.hash, 'digest'); + na.mode = 'CPKDF'; + } else if (name.indexOf('HMAC') >= 0) { + na = normalize(algorithm.hash, 'digest'); + na.mode = 'HMAC'; + } else + throw new NotSupportedError('Algorithm not supported'); + + // Compile modes + modes.forEach(function (mode) { + mode = mode.toUpperCase(); + if (/^[0-9]+$/.test(mode)) { + if ((['8', '16', '32'].indexOf(mode) >= 0) || (na.length === '128' && mode === '64')) { // Shift bits + if (na.mode === 'ES') + na.shiftBits = parseInt(mode); + else if (na.mode === 'MAC') + na.macLength = parseInt(mode); + else + throw new NotSupportedError('Algorithm ' + na.name + ' mode ' + mode + ' not supported'); + } else if (['89', '94', '01', '12', '15', '1989', '1994', '2001', '2012', '2015'].indexOf(mode) >= 0) { // GOST Year + var version = parseInt(mode); + version = version < 1900 ? (version < 80 ? 2000 + version : 1900 + version) : version; + na.version = version; + } else if (['1'].indexOf(mode) >= 0 && na.name === 'SHA') { // SHA-1 + na.version = 1; + na.length = 160; + } else if (['256', '384', '512'].indexOf(mode) >= 0 && na.name === 'SHA') { // SHA-2 + na.version = 2; + na.length = parseInt(mode); + } else if (['40', '128'].indexOf(mode) >= 0 && na.name === 'RC2') { // RC2 + na.version = 1; + na.length = parseInt(mode); // key size + } else if (['64', '128', '256', '512'].indexOf(mode) >= 0) // block size + na.length = parseInt(mode); + else if (['1000', '2000'].indexOf(mode) >= 0) // Iterations + na.iterations = parseInt(mode); + // Named Paramsets + } else if (['E-TEST', 'E-A', 'E-B', 'E-C', 'E-D', 'E-SC', 'E-Z', 'D-TEST', 'D-A', 'D-SC'].indexOf(mode) >= 0) { + na.sBox = mode; + } else if (['S-TEST', 'S-A', 'S-B', 'S-C', 'S-D', 'X-A', 'X-B', 'X-C'].indexOf(mode) >= 0) { + na.namedParam = mode; + } else if (['S-256-TEST', 'S-256-A', 'S-256-B', 'S-256-C', 'P-256', 'T-512-TEST', 'T-512-A', + 'T-512-B', 'X-256-A', 'X-256-B', 'T-256-TEST', 'T-256-A', 'T-256-B', 'S-256-B', 'T-256-C', 'S-256-C'].indexOf(mode) >= 0) { + na.namedCurve = mode; + } else if (['SC', 'CP', 'VN'].indexOf(mode) >= 0) { + na.procreator = mode; + + // Encription GOST 28147 or GOST R 34.12 + } else if (na.name === 'GOST 28147' || na.name === 'GOST R 34.12' || na.name === 'RC2') { + if (['ES', 'MAC', 'KW', 'MASK'].indexOf(mode) >= 0) { + na.mode = mode; + } else if (['ECB', 'CFB', 'OFB', 'CTR', 'CBC'].indexOf(mode) >= 0) { + na.mode = 'ES'; + na.block = mode; + } else if (['CPKW', 'NOKW', 'SCKW'].indexOf(mode) >= 0) { + na.mode = 'KW'; + na.keyWrapping = mode.replace('KW', ''); + } else if (['ZEROPADDING', 'PKCS5PADDING', 'NOPADDING', 'RANDOMPADDING', 'BITPADDING'].indexOf(mode) >= 0) { + na.padding = mode.replace('PADDING', ''); + } else if (['NOKM', 'CPKM'].indexOf(mode) >= 0) { + na.keyMeshing = mode.replace('KM', ''); + } else + throw new NotSupportedError('Algorithm ' + na.name + ' mode ' + mode + ' not supported'); + + // Digesting GOST 34.11 + } else if (na.name === 'GOST R 34.11' || na.name === 'SHA') { + if (['HASH', 'KDF', 'HMAC', 'PBKDF2', 'PFXKDF', 'CPKDF'].indexOf(mode) >= 0) + na.mode = mode; + else + throw new NotSupportedError('Algorithm ' + na.name + ' mode ' + mode + ' not supported'); + + // Signing GOST 34.10 + } else if (na.name === 'GOST R 34.10') { + var hash = mode.replace(/[\.\s]/g, ''); + if (hash.indexOf('GOST') >= 0 && hash.indexOf('3411') >= 0) + na.hash = mode; + else if (['SIGN', 'DH', 'MASK'].indexOf(mode)) + na.mode = mode; + else + throw new NotSupportedError('Algorithm ' + na.name + ' mode ' + mode + ' not supported'); + } + }); + + // Procreator + na.procreator = algorithm.procreator || na.procreator || 'CP'; + + // Key size + switch (na.name) { + case 'GOST R 34.10': + na.keySize = na.length / (na.version === 1994 ? 4 : 8); + break; + case 'GOST R 34.11': + na.keySize = 32; + break; + case 'GOST 28147': + case 'GOST R 34.12': + na.keySize = 32; + break; + case 'RC2': + na.keySize = Math.ceil(na.length / 8); + break; + case 'SHA': + na.keySize = na.length / 8; + break; + } + + // Encrypt additional modes + if (na.mode === 'ES') { + if (algorithm.block) + na.block = algorithm.block; // ECB, CFB, OFB, CTR, CBC + if (na.block) + na.block = na.block.toUpperCase(); + if (algorithm.padding) + na.padding = algorithm.padding; // NO, ZERO, PKCS5, RANDOM, BIT + if (na.padding) + na.padding = na.padding.toUpperCase(); + if (algorithm.shiftBits) + na.shiftBits = algorithm.shiftBits; // 8, 16, 32, 64 + if (algorithm.keyMeshing) + na.keyMeshing = algorithm.keyMeshing; // NO, CP + if (na.keyMeshing) + na.keyMeshing = na.keyMeshing.toUpperCase(); + // Default values + if (method !== 'importKey' && method !== 'generateKey') { + na.block = na.block || 'ECB'; + na.padding = na.padding || (na.block === 'CBC' || na.block === 'ECB' ? 'ZERO' : 'NO'); + if (na.block === 'CFB' || na.block === 'OFB') + na.shiftBits = na.shiftBits || na.length; + na.keyMeshing = na.keyMeshing || 'NO'; + } + } + if (na.mode === 'KW') { + if (algorithm.keyWrapping) + na.keyWrapping = algorithm.keyWrapping; // NO, CP, SC + if (na.keyWrapping) + na.keyWrapping = na.keyWrapping.toUpperCase(); + if (method !== 'importKey' && method !== 'generateKey') + na.keyWrapping = na.keyWrapping || 'NO'; + } + + // Paramsets + ['sBox', 'namedParam', 'namedCurve', 'curve', 'param', 'modulusLength'].forEach(function (name) { + algorithm[name] && (na[name] = algorithm[name]); + }); + // Default values + if (method !== 'importKey' && method !== 'generateKey') { + if (na.name === 'GOST 28147') { + na.sBox = na.sBox || (na.procreator === 'SC' ? 'E-SC' : 'E-A'); // 'E-A', 'E-B', 'E-C', 'E-D', 'E-SC' + } else if (na.name === 'GOST R 34.12' && na.length === 64) { + na.sBox = 'E-Z'; + } else if (na.name === 'GOST R 34.11' && na.version === 1994) { + na.sBox = na.sBox || (na.procreator === 'SC' ? 'D-SC' : 'D-A'); // 'D-SC' + } else if (na.name === 'GOST R 34.10' && na.version === 1994) { + na.namedParam = na.namedParam || (na.mode === 'DH' ? 'X-A' : 'S-A'); // 'S-B', 'S-C', 'S-D', 'X-B', 'X-C' + } else if (na.name === 'GOST R 34.10' && na.version === 2001) { + na.namedCurve = na.namedCurve || (na.length === 256 ? + na.procreator === 'SC' ? 'P-256' : (na.mode === 'DH' ? 'X-256-A' : 'S-256-A') : // 'S-256-B', 'S-256-C', 'X-256-B', 'T-256-A', 'T-256-B', 'T-256-C', 'P-256' + na.mode === 'T-512-A'); // 'T-512-B', 'T-512-C' + } else if (na.name === 'GOST R 34.10' && na.version === 2012) { + na.namedCurve = na.namedCurve || (na.length === 256 ? + na.procreator === 'SC' ? 'P-256' : (na.mode === 'DH' ? 'X-256-A' : 'S-256-A') : // 'S-256-B', 'S-256-C', 'X-256-B', 'T-256-A', 'T-256-B', 'T-256-C', 'P-256' + na.mode === 'T-512-A'); // 'T-512-B', 'T-512-C' + } + } + + // Vectors + switch (na.mode) { + case 'DH': + algorithm.ukm && (na.ukm = algorithm.ukm); + algorithm['public'] && (na['public'] = algorithm['public']); + break; + case 'SIGN': + case 'KW': + algorithm.ukm && (na.ukm = algorithm.ukm); + break; + case 'ES': + case 'MAC': + algorithm.iv && (na.iv = algorithm.iv); + break; + case 'KDF': + algorithm.label && (na.label = algorithm.label); + algorithm.contex && (na.context = algorithm.contex); + break; + case 'PBKDF2': + algorithm.salt && (na.salt = algorithm.salt); + algorithm.iterations && (na.iterations = algorithm.iterations); + algorithm.diversifier && (na.diversifier = algorithm.diversifier); + break; + case 'PFXKDF': + algorithm.salt && (na.salt = algorithm.salt); + algorithm.iterations && (na.iterations = algorithm.iterations); + algorithm.diversifier && (na.diversifier = algorithm.diversifier); + break; + case 'CPKDF': + algorithm.salt && (na.salt = algorithm.salt); + algorithm.iterations && (na.iterations = algorithm.iterations); + break; + } + + // Verification method and modes + if (method && ( + ((na.mode !== 'ES' && na.mode !== 'SIGN' && na.mode !== 'MAC' && + na.mode !== 'HMAC' && na.mode !== 'KW' && na.mode !== 'DH' + && na.mode !== 'MASK') && + (method === 'generateKey')) || + ((na.mode !== 'ES') && + (method === 'encrypt' || method === 'decrypt')) || + ((na.mode !== 'SIGN' && na.mode !== 'MAC' && na.mode !== 'HMAC') && + (method === 'sign' || method === 'verify')) || + ((na.mode !== 'HASH') && + (method === 'digest')) || + ((na.mode !== 'KW' && na.mode !== 'MASK') && + (method === 'wrapKey' || method === 'unwrapKey')) || + ((na.mode !== 'DH' && na.mode !== 'PBKDF2' && na.mode !== 'PFXKDF' && + na.mode !== 'CPKDF' && na.mode !== 'KDF') && + (method === 'deriveKey' || method === 'deriveBits')))) + throw new NotSupportedError('Algorithm mode ' + na.mode + ' not valid for method ' + method); + + // Normalize hash algorithm + algorithm.hash && (na.hash = algorithm.hash); + if (na.hash) { + if ((typeof na.hash === 'string' || na.hash instanceof String) + && na.procreator) + na.hash = na.hash + '/' + na.procreator; + na.hash = normalize(na.hash, 'digest'); + } + + // Algorithm object identirifer + algorithm.id && (na.id = algorithm.id); + + return na; +} + +// Check for possibility use native crypto.subtle +function checkNative(algorithm) { + if (!rootCrypto || !rootCrypto.subtle || !algorithm) + return false; + // Prepare name + var name = (typeof algorithm === 'string' || algorithm instanceof String) ? + name = algorithm : algorithm.name; + if (!name) + return false; + name = name.toUpperCase(); + // Digest algorithm for key derivation + if ((name.indexOf('KDF') >= 0 || name.indexOf('HMAC') >= 0) && algorithm.hash) + return checkNative(algorithm.hash); + // True if no supported names + return name.indexOf('GOST') === -1 && + name.indexOf('SHA-1') === -1 && + name.indexOf('RC2') === -1 && + name.indexOf('?DES') === -1; +} +// + +/* + * Key conversion methods + * + */ // + +// Check key parameter +function checkKey(key, method) { + if (!key.algorithm) + throw new SyntaxError('Key algorithm not defined'); + + if (!key.algorithm.name) + throw new SyntaxError('Key algorithm name not defined'); + + var name = key.algorithm.name, + gostCipher = name === 'GOST 28147' || name === 'GOST R 34.12' || name === 'RC2', + gostDigest = name === 'GOST R 34.11' || name === 'SHA', + gostSign = name === 'GOST R 34.10'; + + if (!gostCipher && !gostSign && !gostDigest) + throw new NotSupportedError('Key algorithm ' + name + ' is unsupproted'); + + if (!key.type) + throw new SyntaxError('Key type not defined'); + + if (((gostCipher || gostDigest) && key.type !== 'secret') || + (gostSign && !(key.type === 'public' || key.type === 'private'))) + throw new DataError('Key type ' + key.type + ' is not valid for algorithm ' + name); + + if (!key.usages || !key.usages.indexOf) + throw new SyntaxError('Key usages not defined'); + + for (var i = 0, n = key.usages.length; i < n; i++) { + var md = key.usages[i]; + if (((md === 'encrypt' || md === 'decrypt') && key.type !== 'secret') || + (md === 'sign' && key.type === 'public') || + (md === 'verify' && key.type === 'private')) + throw new InvalidStateError('Key type ' + key.type + ' is not valid for ' + md); + } + + if (method) + if (key.usages.indexOf(method) === -1) + throw new InvalidAccessError('Key usages is not contain method ' + method); + + if (!key.buffer) + throw new SyntaxError('Key buffer is not defined'); + + var size = key.buffer.byteLength * 8, keySize = 8 * key.algorithm.keySize; + if ((key.type === 'secret' && size !== (keySize || 256) && + (key.usages.indexOf('encrypt') >= 0 || key.usages.indexOf('decrypt') >= 0)) || + (key.type === 'private' && !(size === 256 || size === 512)) || + (key.type === 'public' && !(size === 512 || size === 1024))) + throw new SyntaxError('Key buffer has wrong size ' + size + ' bit'); +} + +// Extract key and enrich cipher algorithm +function extractKey(method, algorithm, key) { + checkKey(key, method); + if (algorithm) { + var params; + switch (algorithm.mode) { + case 'ES': + params = ['sBox', 'keyMeshing', 'padding', 'block']; + break; + case 'SIGN': + params = ['namedCurve', 'namedParam', 'sBox', 'curve', 'param', 'modulusLength']; + break; + case 'MAC': + params = ['sBox']; + break; + case 'KW': + params = ['keyWrapping', 'ukm']; + break; + case 'DH': + params = ['namedCurve', 'namedParam', 'sBox', 'ukm', 'curve', 'param', 'modulusLength']; + break; + case 'KDF': + params = ['context', 'label']; + break; + case 'PBKDF2': + params = ['sBox', 'iterations', 'salt']; + break; + case 'PFXKDF': + params = ['sBox', 'iterations', 'salt', 'diversifier']; + break; + case 'CPKDF': + params = ['sBox', 'salt']; + break; + } + if (params) + params.forEach(function (name) { + key.algorithm[name] && (algorithm[name] = key.algorithm[name]); + }); + } + return key.buffer; +} + +// Make key definition +function convertKey(algorithm, extractable, keyUsages, keyData, keyType) { + var key = { + type: keyType || (algorithm.name === 'GOST R 34.10' ? 'private' : 'secret'), + extractable: extractable || 'false', + algorithm: algorithm, + usages: keyUsages || [], + buffer: keyData + }; + checkKey(key); + return key; +} + +function convertKeyPair(publicAlgorithm, privateAlgorithm, extractable, keyUsages, publicBuffer, privateBuffer) { + + if (!keyUsages || !keyUsages.indexOf) + throw new SyntaxError('Key usages not defined'); + + var publicUsages = keyUsages.filter(function (value) { + return value !== 'sign'; + }); + var privateUsages = keyUsages.filter(function (value) { + return value !== 'verify'; + }); + + return { + publicKey: convertKey(publicAlgorithm, extractable, publicUsages, publicBuffer, 'public'), + privateKey: convertKey(privateAlgorithm, extractable, privateUsages, privateBuffer, 'private') + }; +} + +// Swap bytes in buffer +function swapBytes(src) { + if (src instanceof CryptoOperationData) + src = new Uint8Array(src); + var dst = new Uint8Array(src.length); + for (var i = 0, n = src.length; i < n; i++) + dst[n - i - 1] = src[i]; + return dst.buffer; +} +// + +/** + * Promise stub object (not fulfill specification, only for internal use) + * Class not defined if Promise class already defined in root context

+ * + * The Promise object is used for deferred and asynchronous computations. A Promise is in one of the three states: + *
    + *
  • pending: initial state, not fulfilled or rejected.
  • + *
  • fulfilled: successful operation
  • + *
  • rejected: failed operation.
  • + *
+ * Another term describing the state is settled: the Promise is either fulfilled or rejected, but not pending.

+ * @class Promise + * @global + * @param {function} executor Function object with two arguments resolve and reject. + * The first argument fulfills the promise, the second argument rejects it. + * We can call these functions, once our operation is completed. + */ // +if (!Promise) { + + root.Promise = (function () { + + function mswrap(value) { + if (value && value.oncomplete === null && value.onerror === null) { + return new Promise(function (resolve, reject) { + value.oncomplete = function () { + resolve(value.result); + }; + value.onerror = function () { + reject(new OperationError(value.toString())); + }; + }); + } else + return value; + } + + function Promise(executor) { + + var state = 'pending', result, + resolveQueue = [], rejectQueue = []; + + function call(callback) { + try { + callback(); + } catch (e) { + } + } + + try { + executor(function (value) { + if (state === 'pending') { + state = 'fulfilled'; + result = value; + resolveQueue.forEach(call); + } + }, function (reason) { + if (state === 'pending') { + state = 'rejected'; + result = reason; + rejectQueue.forEach(call); + } + }); + } catch (error) { + if (state === 'pending') { + state = 'rejected'; + result = error; + rejectQueue.forEach(call); + } + } + /** + * The then() method returns a Promise. It takes two arguments, both are + * callback functions for the success and failure cases of the Promise. + * + * @method then + * @memberOf Promise + * @instance + * @param {function} onFulfilled A Function called when the Promise is fulfilled. This function has one argument, the fulfillment value. + * @param {function} onRejected A Function called when the Promise is rejected. This function has one argument, the rejection reason. + * @returns {Promise} + */ + this.then = function (onFulfilled, onRejected) { + + return new Promise(function (resolve, reject) { + + function asyncOnFulfilled() { + var value; + try { + value = onFulfilled ? onFulfilled(result) : result; + } catch (error) { + reject(error); + return; + } + value = mswrap(value); + if (value && value?.then?.call) { + value.then(resolve, reject); + } else { + resolve(value); + } + } + + function asyncOnRejected() { + var reason; + try { + reason = onRejected ? onRejected(result) : result; + } catch (error) { + reject(error); + return; + } + reason = mswrap(reason); + if (reason && reason?.then?.call) { + reason.then(resolve, reject); + } else { + reject(reason); + } + } + + if (state === 'fulfilled') { + asyncOnFulfilled(); + } else if (state === 'rejected') { + asyncOnRejected(); + } else { + resolveQueue.push(asyncOnFulfilled); + rejectQueue.push(asyncOnRejected); + } + + }); + + }; + /** + * The catch() method returns a Promise and deals with rejected cases only. + * It behaves the same as calling Promise.prototype.then(undefined, onRejected). + * + * @method catch + * @memberOf Promise + * @instance + * @param {function} onRejected A Function called when the Promise is rejected. This function has one argument, the rejection reason. + * @returns {Promise} + */ + this['catch'] = function (onRejected) { + return this.then(undefined, onRejected); + }; + } + + /** + * The Promise.all(iterable) method returns a promise that resolves when all + * of the promises in the iterable argument have resolved.

+ * + * The result is passed as an array of values from all the promises. + * If something passed in the iterable array is not a promise, it's converted to + * one by Promise.resolve. If any of the passed in promises rejects, the + * all Promise immediately rejects with the value of the promise that rejected, + * discarding all the other promises whether or not they have resolved. + * + * @method all + * @memberOf Promise + * @static + * @param {KeyUsages} promises Array with promises. + * @returns {Promise} + */ + Promise.all = function (promises) { + return new Promise(function (resolve, reject) { + var result = [], count = 0; + function asyncResolve(k) { + count++; + return function (data) { + result[k] = data; + count--; + if (count === 0) + resolve(result); + }; + } + + function asyncReject(reason) { + if (count > 0) + reject(reason); + count = 0; + } + + for (var i = 0, n = promises.length; i < n; i++) { + var data = promises[i]; + if (data?.then?.call) + data.then(asyncResolve(i), asyncReject); + else + result[i] = data; + } + + if (count === 0) + resolve(result); + }); + }; + + return Promise; + })(); +} //
+ +/* + * Worker executor + * + */ // + +var baseUrl = '', nameSuffix = ''; +// Try to define from DOM model +if (typeof document !== 'undefined') { + (function () { + var regs = /^(.*)gostCrypto(.*)\.js$/i; + var list = document.querySelectorAll('script'); + for (var i = 0, n = list.length; i < n; i++) { + var value = list[i].getAttribute('src'); + var test = regs.exec(value); + if (test) { + baseUrl = test[1]; + nameSuffix = test[2]; + } + } + })(); +} + +// Local importScripts procedure for include dependens +function importScripts() { + for (var i = 0, n = arguments.length; i < n; i++) { + var name = arguments[i].split('.'), + src = baseUrl + name[0] + nameSuffix + '.' + name[1]; + var el = document.querySelector('script[src="' + src + '"]'); + if (!el) { + el = document.createElement('script'); + el.setAttribute('src', src); + document.head.appendChild(el); + } + } +} + +// Create Worker +var worker = false, tasks = [], sequence = 0; +// Worker will create only for first child process and +// Gost implementation libraries not yet loaded +if (!root.importScripts && !root.gostEngine) { + + try { + worker = new Worker(baseUrl + 'gostEngine' + nameSuffix + '.js'); + + // Result of opertion + worker.onmessage = function (event) { + // Find task + var id = event.data.id; + for (var i = 0, n = tasks.length; i < n; i++) + if (tasks[i].id === id) + break; + if (i < n) { + var task = tasks[i]; + tasks.splice(i, 1); + // Reject if error or resolve with result + if (event.data.error) + task.reject(new OperationError(event.data.error)); + else + task.resolve(event.data.result); + } + }; + + // Worker error - reject all waiting tasks + worker.onerror = function (event) { + for (var i = 0, n = tasks.length; i < n; i++) + tasks[i].reject(event.error); + tasks = []; + }; + + } catch (e) { + // Worker is't supported + worker = false; + } +} + +if (!root.importScripts) { + // This procedure emulate load dependents as in Worker + root.importScripts = importScripts; + +} + +if (!worker) { + // Import main module + // Reason: we are already in worker process or Worker interface is not + // yet supported + root.gostEngine || require('./gostEngine'); +} + +// Executor for any method +function execute(algorithm, method, args) { + return new Promise(function (resolve, reject) { + try { + if (worker) { + var id = ++sequence; + tasks.push({ + id: id, + resolve: resolve, + reject: reject + }); + worker.postMessage({ + id: id, algorithm: algorithm, + method: method, args: args + }); + } else { + if (root.gostEngine) + resolve(root.gostEngine.execute(algorithm, method, args)); + else + reject(new OperationError('Module gostEngine not found')); + } + } catch (error) { + reject(error); + } + }); +} + +// Self resolver +function call(callback) { + try { + callback(); + } catch (e) { + } +} + +// + +/* + * WebCrypto common class references + * + */ // +/** + * The Algorithm object is a dictionary object [WebIDL] which is used to + * specify an algorithm and any additional parameters required to fully + * specify the desired operation.
+ *
+ *  dictionary Algorithm {
+ *      DOMString name;
+ *  };
+ * 
+ * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#algorithm-dictionary} + * @class Algorithm + * @param {DOMString} name The name of the registered algorithm to use. + */ + +/** + * AlgorithmIdentifier - Algorithm or DOMString name of algorithm
+ *
+ *  typedef (Algorithm or DOMString) AlgorithmIdentifier;
+ * 
+ * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#algorithm-dictionary} + * @class AlgorithmIdentifier + */ + +/** + * The KeyAlgorithm interface represents information about the contents of a + * given Key object. + *
+ *  interface KeyAlgorithm {
+ *      readonly attribute DOMString name
+ *  };
+ * 
+ * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#key-algorithm-interface} + * @class KeyAlgorithm + * @param {DOMString} name The name of the algorithm used to generate the Key + */ + +/** + * The type of a key. The recognized key type values are "public", "private" + * and "secret". Opaque keying material, including that used for symmetric + * algorithms, is represented by "secret", while keys used as part of asymmetric + * algorithms composed of public/private keypairs will be either "public" or "private". + *
+ *  typedef DOMString KeyType;
+ * 
+ * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#key-interface} + * @class KeyType + */ + +/** + * Sequence of operation type that may be performed using a key. The recognized + * key usage values are "encrypt", "decrypt", "sign", "verify", "deriveKey", + * "deriveBits", "wrapKey" and "unwrapKey". + *
+ *  typedef DOMString[] KeyUsages;
+ * 
+ * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#key-interface} + * @class KeyUsages + */ + +/** + * The Key object represents an opaque reference to keying material that is + * managed by the user agent.
+ * This specification provides a uniform interface for many different kinds of + * keying material managed by the user agent. This may include keys that have + * been generated by the user agent, derived from other keys by the user agent, + * imported to the user agent through user actions or using this API, + * pre-provisioned within software or hardware to which the user agent has + * access or made available to the user agent in other ways. The term key refers + * broadly to any keying material including actual keys for cryptographic + * operations and secret values obtained within key derivation or exchange operations.
+ * The Key object is not required to directly interface with the underlying key + * storage mechanism, and may instead simply be a reference for the user agent + * to understand how to obtain the keying material when needed, eg. when performing + * a cryptographic operation. + *
+ *  interface Key {
+ *      readonly attribute KeyType type;
+ *      readonly attribute boolean extractable;
+ *      readonly attribute KeyAlgorithm algorithm;
+ *      readonly attribute KeyUsages usages;
+ *  };
+ * 
+ * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#key-interface} + * @class Key + * @param {KeyType} type The type of a key. The recognized key type values are "public", "private" and "secret". + * @param {boolean} extractable Whether or not the raw keying material may be exported by the application. + * @param {KeyAlgorithm} algorithm The Algorithm used to generate the key. + * @param {KeyUsages} usages Key usage array: type of operation that may be performed using a key. + */ + +/** + * The KeyPair interface represents an asymmetric key pair that is comprised of both public and private keys. + *
+ *  interface KeyPair {
+ *      readonly attribute Key publicKey;
+ *      readonly attribute Key privateKey;
+ *  };
+ * 
+ * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#keypair} + * @class KeyPair + * @param {Key} privateKey Private key + * @param {Key} publicKey Public key + */ + +/** + * Specifies a serialization format for a key. The recognized key format values are: + *
    + *
  • 'raw' - An unformatted sequence of bytes. Intended for secret keys.
  • + *
  • 'pkcs8' - The DER encoding of the PrivateKeyInfo structure from RFC 5208.
  • + *
  • 'spki' - The DER encoding of the SubjectPublicKeyInfo structure from RFC 5280.
  • + *
  • 'jwk' - The key is represented as JSON according to the JSON Web Key format.
  • + *
+ *
+ *  typedef DOMString KeyFormat;
+ *  
+ * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#key-interface} + * @class KeyFormat + */ + +/** + * Binary data + *
+ *  typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData;
+ *  
+ * @class CryptoOperationData + */ +var CryptoOperationData = ArrayBuffer; + +/** + * DER-encoded ArrayBuffer or PEM-encoded DOMString constains ASN.1 object
+ *
+ *  typedef (ArrayBuffer or DOMString) FormatedData;
+ * 
+ * @class FormatedData + */ +//
+ +/** + * The gostCrypto provide general purpose cryptographic functionality for + * GOST standards including a cryptographically strong pseudo-random number + * generator seeded with truly random values. + * + * @namespace gostCrypto + */ +var gostCrypto = {}; + +/** + * The SubtleCrypto class provides low-level cryptographic primitives and algorithms. + * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#subtlecrypto-interface} + * + * @class SubtleCrypto + */ // +function SubtleCrypto() { +} + +/** + * The encrypt method returns a new Promise object that will encrypt data + * using the specified algorithm identifier with the supplied Key. + * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-encrypt}

+ * + * Supported algorithm names: + *
    + *
  • GOST 28147-ECB "prostaya zamena" (ECB) mode (default)
  • + *
  • GOST 28147-CFB "gammirovanie s obratnoj svyaziyu po shifrotekstu" (CFB) mode
  • + *
  • GOST 28147-OFB "gammirovanie s obratnoj svyaziyu po vyhodu" (OFB) mode
  • + *
  • GOST 28147-CTR "gammirovanie" (counter) mode
  • + *
  • GOST 28147-CBC Cipher-Block-Chaining (CBC) mode
  • + *
  • GOST R 34.12-ECB "prostaya zamena" (ECB) mode (default)
  • + *
  • GOST R 34.12-CFB "gammirovanie s obratnoj svyaziyu po shifrotekstu" (CFB) mode
  • + *
  • GOST R 34.12-OFB "gammirovanie s obratnoj svyaziyu po vyhodu" (OFB) mode
  • + *
  • GOST R 34.12-CTR "gammirovanie" (counter) mode
  • + *
  • GOST R 34.12-CBC Cipher-Block-Chaining (CBC) mode
  • + *
+ * For more information see {@link GostCipher} + * + * @memberOf SubtleCrypto + * @method encrypt + * @instance + * @param {AlgorithmIdentifier} algorithm Algorithm identifier + * @param {Key} key Key object + * @param {CryptoOperationData} data Operation data + * @returns {Promise} Promise that resolves with {@link CryptoOperationData} + */ +SubtleCrypto.prototype.encrypt = function (algorithm, key, data) // +{ + return new Promise(call).then(function () { + if (checkNative(algorithm)) + return rootCrypto.subtle.encrypt(algorithm, key, data); + + algorithm = normalize(algorithm, 'encrypt'); + return execute(algorithm, 'encrypt', + [extractKey('encrypt', algorithm, key), data]); + }); +}; // + +/** + * The decrypt method returns a new Promise object that will decrypt data + * using the specified algorithm identifier with the supplied Key. + * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-decrypt}

+ * + * Supported algorithm names: + *
    + *
  • GOST 28147-ECB "prostaya zamena" (ECB) mode (default)
  • + *
  • GOST 28147-CFB "gammirovanie s obratnoj svyaziyu po shifrotekstu" (CFB) mode
  • + *
  • GOST 28147-OFB "gammirovanie s obratnoj svyaziyu po vyhodu" (OFB) mode
  • + *
  • GOST 28147-CTR "gammirovanie" (counter) mode
  • + *
  • GOST 28147-CBC Cipher-Block-Chaining (CBC) mode
  • + *
  • GOST R 34.12-ECB "prostaya zamena" (ECB) mode (default)
  • + *
  • GOST R 34.12-CFB "gammirovanie s obratnoj svyaziyu po shifrotekstu" (CFB) mode
  • + *
  • GOST R 34.12-OFB "gammirovanie s obratnoj svyaziyu po vyhodu" (OFB) mode
  • + *
  • GOST R 34.12-CTR "gammirovanie" (counter) mode
  • + *
  • GOST R 34.12-CBC Cipher-Block-Chaining (CBC) mode
  • + *
+ * For additional modes see {@link GostCipher} + * + * @memberOf SubtleCrypto + * @method decrypt + * @instance + * @param {AlgorithmIdentifier} algorithm Algorithm identifier + * @param {Key} key Key object + * @param {CryptoOperationData} data Operation data + * @returns {Promise} Promise that resolves with {@link CryptoOperationData} + */ +SubtleCrypto.prototype.decrypt = function (algorithm, key, data) // +{ + return new Promise(call).then(function () { + if (checkNative(algorithm)) + return rootCrypto.subtle.decrypt(algorithm, key, data); + + algorithm = normalize(algorithm, 'decrypt'); + return execute(algorithm, 'decrypt', + [extractKey('decrypt', algorithm, key), data]); + }); +}; // + +/** + * The sign method returns a new Promise object that will sign data using + * the specified algorithm identifier with the supplied Key. + * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-sign}

+ * + * Supported algorithm names: + *
    + *
  • GOST R 34.10-94 GOST Signature
  • + *
  • GOST R 34.10-94/GOST R 34.11-94 GOST Signature with Hash
  • + *
  • GOST R 34.10 ECGOST Signature
  • + *
  • GOST R 34.10/GOST R 34.11-94 ECGOST Signature with Old-Style Hash
  • + *
  • GOST R 34.10/GOST R 34.11 ECGOST Signature with Streebog Hash
  • + *
  • GOST 28147-MAC MAC base on GOST 28147
  • + *
  • GOST R 34.12-MAC MAC base on GOST R 43.12
  • + *
  • GOST R 34.11-HMAC HMAC base on GOST 34.11
  • + *
  • SHA-HMAC HMAC base on SHA
  • + *
+ * For additional modes see {@link GostSign}, {@link GostDigest} and {@link GostCipher} + * + * @memberOf SubtleCrypto + * @method sign + * @instance + * @param {AlgorithmIdentifier} algorithm Algorithm identifier + * @param {Key} key Key object + * @param {CryptoOperationData} data Operation data + * @returns {Promise} Promise that resolves with {@link CryptoOperationData} + */ +SubtleCrypto.prototype.sign = function (algorithm, key, data) // +{ + return new Promise(call).then(function () { + if (checkNative(algorithm)) + return rootCrypto.subtle.sign(algorithm, key, data); + + algorithm = normalize(algorithm, 'sign'); + var value = execute(algorithm, 'sign', + [extractKey('sign', algorithm, key), data]).then(function (data) { + if (algorithm.procreator === 'SC' && algorithm.mode === 'SIGN') { + data = gostCrypto.asn1.GostSignature.encode(data); + } + return data; + }); + return value; + }); +}; // + +/** + * The verify method returns a new Promise object that will verify data + * using the specified algorithm identifier with the supplied Key. + * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-verify}

+ * + * Supported algorithm names: + *
    + *
  • GOST R 34.10-94 GOST Signature
  • + *
  • GOST R 34.10-94/GOST R 34.11-94 GOST Signature with Hash
  • + *
  • GOST R 34.10 ECGOST Signature
  • + *
  • GOST R 34.10/GOST R 34.11-94 ECGOST Signature with Old-Style Hash
  • + *
  • GOST R 34.10/GOST R 34.11 ECGOST Signature with Streebog Hash
  • + *
  • GOST 28147-MAC MAC base on GOST 28147
  • + *
  • GOST R 34.12-MAC MAC base on GOST R 34.12
  • + *
  • GOST R 34.11-HMAC HMAC base on GOST 34.11
  • + *
  • SHA-HMAC HMAC base on SHA
  • + *
+ * For additional modes see {@link GostSign}, {@link GostDigest} and {@link GostCipher} + * + * @memberOf SubtleCrypto + * @method verify + * @instance + * @param {AlgorithmIdentifier} algorithm Algorithm identifier + * @param {Key} key Key object + * @param {CryptoOperationData} signature Signature data + * @param {CryptoOperationData} data Operation data + * @returns {Promise} Promise that resolves with boolean value of verification result + */ +SubtleCrypto.prototype.verify = function (algorithm, key, signature, data) // +{ + return new Promise(call).then(function () { + if (checkNative(algorithm)) + return rootCrypto.subtle.verify(algorithm, key, signature, data); + + algorithm = normalize(algorithm, 'verify'); + if (algorithm.procreator === 'SC' && algorithm.mode === 'SIGN') { + var obj = gostCrypto.asn1.GostSignature.decode(signature); + signature = {r: obj.r, s: obj.s}; + } + return execute(algorithm, 'verify', + [extractKey('verify', algorithm, key), signature, data]); + }); +}; // + +/** + * The digest method returns a new Promise object that will digest data + * using the specified algorithm identifier. + * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-digest}

+ * + * Supported algorithm names: + *
    + *
  • GOST R 34.11-94 Old-Style GOST Hash
  • + *
  • GOST R 34.11 GOST Streebog Hash
  • + *
  • SHA SHA Hash
  • + *
+ * For additional modes see {@link GostDigest} + * + * @memberOf SubtleCrypto + * @method digest + * @instance + * @param {AlgorithmIdentifier} algorithm Algorithm identifier + * @param {CryptoOperationData} data Operation data + * @returns {Promise} Promise that resolves with {@link CryptoOperationData} + */ +SubtleCrypto.prototype.digest = function (algorithm, data) // +{ + return new Promise(call).then(function () { + if (checkNative(algorithm)) + return rootCrypto.subtle.digest(algorithm, data); + + algorithm = normalize(algorithm, 'digest'); + return execute(algorithm, 'digest', [data]); + }); +}; // + +/** + * The generateKey method returns a new Promise object that will key(s) using + * the specified algorithm identifier. Key can be used in according with + * KeyUsages sequence. The recognized key usage values are "encrypt", "decrypt", + * "sign", "verify", "deriveKey", "deriveBits", "wrapKey" and "unwrapKey". + * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-generateKey}

+ * + * Supported algorithm names: + *
    + *
  • GOST R 34.10 ECGOST Key Pairs
  • + *
  • GOST 28147 Key for encryption GOST 28147 modes
  • + *
  • GOST 28147-KW Key for wrapping GOST 28147 modes
  • + *
  • GOST R 34.12 Key for encryption GOST R 34.12 modes
  • + *
  • GOST R 34.12-KW Key for wrapping GOST R 34.12 modes
  • + *
  • GOST R 34.11-KDF Key for Derivation Algorithm
  • + *
+ * For additional modes see {@link GostSign}, {@link GostDigest} and {@link GostCipher}
+ * Note: Generation key for GOST R 34.10-94 not supported. + * + * @memberOf SubtleCrypto + * @method generateKey + * @instance + * @param {AlgorithmIdentifier} algorithm Key algorithm identifier + * @param {boolean} extractable Whether or not the raw keying material may be exported by the application + * @param {KeyUsages} keyUsages Key usage array: type of operation that may be performed using a key + * @returns {Promise} Promise that resolves with {@link Key} or {@link KeyPair} in according to key algorithm + */ +SubtleCrypto.prototype.generateKey = function (algorithm, extractable, keyUsages) // +{ + return new Promise(call).then(function () { + if (checkNative(algorithm)) + return rootCrypto.subtle.generateKey(algorithm, extractable, keyUsages); + + var privateAlgorithm = algorithm.privateKey, + publicAlgorithm = algorithm.publicKey; + algorithm = normalize(algorithm, 'generateKey'); + if (privateAlgorithm) + privateAlgorithm = normalize(privateAlgorithm, 'generateKey'); + else + privateAlgorithm = algorithm; + if (publicAlgorithm) + publicAlgorithm = normalize(publicAlgorithm, 'generateKey'); + else + publicAlgorithm = algorithm; + return execute(algorithm, 'generateKey', []).then(function (data) { + if (data.publicKey && data.privateKey) + return convertKeyPair(publicAlgorithm, privateAlgorithm, extractable, keyUsages, data.publicKey, data.privateKey); + else + return convertKey(algorithm, extractable, keyUsages, data); + }); + }); +}; // + +/** + * The deriveKey method returns a new Promise object that will key(s) using + * the specified algorithm identifier. Key can be used in according with + * KeyUsage sequence. The recognized key usage values are "encrypt", "decrypt", + * "sign", "verify", "deriveKey", "deriveBits", "wrapKey" and "unwrapKey". + * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-deriveKey}

+ * + * Supported algorithm names: + *
    + *
  • GOST R 34.10-DH ECDH Key Agreement mode
  • + *
  • GOST R 34.11-KDF Key for Derivation Algorithm
  • + *
  • GOST R 34.11-PBKDF2 Password Based Key for Derivation Algorithm
  • + *
  • GOST R 34.11-PFXKDF PFX Key for Derivation Algorithm
  • + *
  • GOST R 34.11-CPKDF Password Based Key for CryptoPro Derivation Algorithm
  • + *
  • SHA-PBKDF2 Password Based Key for Derivation Algorithm
  • + *
  • SHA-PFXKDF PFX Key for Derivation Algorithm
  • + *
+ * For additional modes see {@link GostSign} and {@link GostDigest} + * + * @memberOf SubtleCrypto + * @method deriveKey + * @instance + * @param {AlgorithmIdentifier} algorithm Algorithm identifier + * @param {Key} baseKey Derivation key object + * @param {AlgorithmIdentifier} derivedKeyType Derived key algorithm identifier + * @param {boolean} extractable Whether or not the raw keying material may be exported by the application + * @param {KeyUsages} keyUsages Key usage array: type of operation that may be performed using a key + * @returns {Promise} Promise that resolves with {@link Key} + */ +SubtleCrypto.prototype.deriveKey = function (algorithm, baseKey, + derivedKeyType, extractable, keyUsages) // +{ + return new Promise(call).then(function () { + if (checkNative(algorithm)) + return rootCrypto.subtle.deriveKey(algorithm, baseKey, + derivedKeyType, extractable, keyUsages); + + algorithm = normalize(algorithm, 'deriveKey'); + derivedKeyType = normalize(derivedKeyType, 'generateKey'); + algorithm.keySize = derivedKeyType.keySize; + if (algorithm['public']) { + algorithm['public'].algorithm = normalize(algorithm['public'].algorithm); + algorithm['public'] = extractKey('deriveKey', algorithm, algorithm['public']); + } + return execute(algorithm, 'deriveKey', [extractKey('deriveKey', algorithm, baseKey)]).then(function (data) { + return convertKey(derivedKeyType, extractable, keyUsages, data); + }); + }); +}; // + +/** + * The deriveBits method returns length bits on baseKey using the + * specified algorithm identifier. + * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-deriveBits}

+ * + * Supported algorithm names: + *
    + *
  • GOST R 34.10-DH ECDH Key Agreement mode
  • + *
  • GOST R 34.11-KDF Key for Derivation Algorithm
  • + *
  • GOST R 34.11-PBKDF2 Password Based Key for Derivation Algorithm
  • + *
  • GOST R 34.11-PFXKDF PFX Key for Derivation Algorithm
  • + *
  • GOST R 34.11-CPKDF Password Based Key for CryptoPro Derivation Algorithm
  • + *
  • SHA-PBKDF2 Password Based Key for Derivation Algorithm
  • + *
  • SHA-PFXKDF PFX Key for Derivation Algorithm
  • + *
+ * For additional modes see {@link GostSign} and {@link GostDigest} + * + * @memberOf SubtleCrypto + * @method deriveBits + * @instance + * @param {AlgorithmIdentifier} algorithm Algorithm identifier + * @param {Key} baseKey Derivation key object + * @param {number} length Length bits + * @returns {Promise} Promise that resolves with {@link CryptoOperationData} + */ +SubtleCrypto.prototype.deriveBits = function (algorithm, baseKey, length) // +{ + return new Promise(call).then(function () { + if (checkNative(algorithm)) + return rootCrypto.subtle.deriveBits(algorithm, baseKey, length); + + algorithm = normalize(algorithm, 'deriveBits'); + if (algorithm['public']) + algorithm['public'] = extractKey('deriveBits', algorithm, algorithm['public']); + return execute(algorithm, 'deriveBits', [extractKey('deriveBits', algorithm, baseKey), length]); + }); +}; // + +/** + * The importKey method returns a new Promise object that will key(s) using + * the specified algorithm identifier. Key can be used in according with + * KeyUsage sequence. The recognized key usage values are "encrypt", "decrypt", + * "sign", "verify", "deriveKey", "deriveBits", "wrapKey" and "unwrapKey".

+ * Parameter keyData contains data in defined format. + * The suppored key format values are: + *
    + *
  • 'raw' - An unformatted sequence of bytes. Intended for secret keys.
  • + *
  • 'pkcs8' - The DER encoding of the PrivateKeyInfo structure from RFC 5208.
  • + *
  • 'spki' - The DER encoding of the SubjectPublicKeyInfo structure from RFC 5280.
  • + *
+ * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-importKey}

+ * + * Supported algorithm names: + *
    + *
  • GOST R 34.10-94 GOST Private and Public keys
  • + *
  • GOST R 34.10 ECGOST Private and Public keys
  • + *
  • GOST 28147 Key for encryption GOST 28147 modes
  • + *
  • GOST 28147-KW Key for key wrapping GOST 28147 modes
  • + *
  • GOST R 34.12 Key for encryption GOST 34.12 modes
  • + *
  • GOST R 34.12-KW Key for key wrapping GOST 34.12 modes
  • + *
  • GOST R 34.11-KDF Key for Derivation Algorithm
  • + *
+ * For additional modes see {@link GostSign}, {@link GostDigest} and {@link GostCipher}
+ * + * @memberOf SubtleCrypto + * @method importKey + * @instance + * @param {KeyFormat} format Key format Format specifies a serialization format for a key + * @param {CryptoOperationData} keyData + * @param {AlgorithmIdentifier} algorithm Key algorithm identifier + * @param {boolean} extractable Whether or not the raw keying material may be exported by the application + * @param {KeyUsages} keyUsages Key usage array: type of operation that may be performed using a key + * @returns {Promise} Promise that resolves with {@link Key} + */ +SubtleCrypto.prototype.importKey = function (format, keyData, algorithm, extractable, keyUsages) // +{ + var type; + return new Promise(call).then(function () { + if (checkNative(algorithm)) + return rootCrypto.subtle.importKey(format, keyData, algorithm, extractable, keyUsages); + + if (format === 'raw') { + algorithm = normalize(algorithm, 'importKey'); + if (keyUsages && keyUsages.indexOf) { + var name = algorithm.name.toUpperCase().replace(/[\.\s]/g, ''); + if (name.indexOf('3410') >= 0 && keyUsages.indexOf('sign') >= 0) + type = 'private'; + else if (name.indexOf('3410') >= 0 && keyUsages.indexOf('verify') >= 0) + type = 'public'; + } + return keyData; + } else { + var key; + if (format === 'pkcs8') + key = gostCrypto.asn1.GostPrivateKeyInfo.decode(keyData).object; + else if (format === 'spki') + key = gostCrypto.asn1.GostSubjectPublicKeyInfo.decode(keyData).object; + else + throw new NotSupportedError('Key format not supported'); + + algorithm = normalize(key.algorithm, 'importKey'); + type = key.type; + if (extractable !== false) + extractable = extractable || key.extractable; + if (keyUsages) { + for (var i = 0; i < keyUsages.length; i++) { + if (key.usages.indexOf(keyUsages[i]) < 0) + throw DataError('Key usage not valid for this key'); + } + } else + keyUsages = key.usages; + var data = key.buffer, keySize = algorithm.keySize, dataLen = data.byteLength; + if (type === 'public' || keySize === dataLen) + return data; + else { + // Remove private key masks + if (dataLen % keySize > 0) + throw new DataError('Invalid key size'); + algorithm.mode = 'MASK'; + algorithm.procreator = 'VN'; + var chain = []; + for (var i = keySize; i < dataLen; i += keySize) { + chain.push((function (mask) { + return function (data) { + return execute(algorithm, 'unwrapKey', [mask, data]).then(function (data) { + var next = chain.pop(); + if (next) + return next(data); + else { + delete algorithm.mode; + return data; + } + }); + }; + })(new Uint8Array(data, i, keySize))); + } + return chain.pop()(new Uint8Array(data, 0, keySize)); + } + } + }).then(function (data) { + return convertKey(algorithm, extractable, keyUsages, data, type); + }); +}; // + +/** + * The exportKey method returns a new Promise object that will key data in + * defined format.

+ * The suppored key format values are: + *
    + *
  • 'raw' - An unformatted sequence of bytes. Intended for secret keys.
  • + *
  • 'pkcs8' - The DER encoding of the PrivateKeyInfo structure from RFC 5208.
  • + *
  • 'spki' - The DER encoding of the SubjectPublicKeyInfo structure from RFC 5280.
  • + *
+ * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-exportKey}

+ * + * Supported algorithm names: + *
    + *
  • GOST R 34.10-94 GOST Private and Public keys
  • + *
  • GOST R 34.10 ECGOST Private and Public keys
  • + *
  • GOST 28147 Key for encryption GOST 28147 modes
  • + *
  • GOST 28147-KW Key for key wrapping GOST 28147 modes
  • + *
  • GOST R 34.12 Key for encryption GOST R 34.12 modes
  • + *
  • GOST R 34.12-KW Key for key wrapping GOST R 34.12 modes
  • + *
  • GOST R 34.11-KDF Key for Derivation Algorithm
  • + *
  • GOST R 34.11-PBKDF2 Import Password for Key for Derivation Algorithm
  • + *
  • GOST R 34.11-PFXKDF Import PFX Key for Derivation Algorithm
  • + *
  • GOST R 34.11-CPKDF Import Password Key for CryptoPro Derivation Algorithm
  • + *
  • SHA-PBKDF2 Import Password for Key for Derivation Algorithm
  • + *
  • SHA-PFXKDF Import PFX Key for Derivation Algorithm
  • + *
+ * For additional modes see {@link GostSign}, {@link GostDigest} and {@link GostCipher}
+ * + * @memberOf SubtleCrypto + * @method exportKey + * @instance + * @param {KeyFormat} format Format specifies a serialization format for a key + * @param {Key} key Key object + * @returns {Promise} Promise that resolves with {@link CryptoOperationData} + */ +SubtleCrypto.prototype.exportKey = function (format, key) // +{ + return new Promise(call).then(function () { + if (key && checkNative(key.algorithm)) + return rootCrypto.subtle.exportKey(format, key); + + if (!key.extractable) + throw new InvalidAccessError('Key not extractable'); + + var raw = extractKey(null, null, key); + if (format === 'raw') + return raw; + else if (format === 'pkcs8' && key?.algorithm?.id) { + if (key.algorithm.procreator === 'VN') { + // Add masks for ViPNet + var algorithm = key.algorithm, mask; + algorithm.mode = 'MASK'; + return execute(algorithm, 'generateKey').then(function (data) { + mask = data; + return execute(algorithm, 'wrapKey', [mask, key.buffer]); + }).then(function (data) { + delete algorithm.mode; + var d = new Uint8Array(data.byteLength + mask.byteLength); + d.set(new Uint8Array(data, 0, data.byteLength)); + d.set(new Uint8Array(mask, 0, mask.byteLength), data.byteLength); + var buffer = d.buffer; + buffer.enclosed = true; + return gostCrypto.asn1.GostPrivateKeyInfo.encode({ + algorithm: algorithm, + buffer: buffer + }); + }); + } else + return gostCrypto.asn1.GostPrivateKeyInfo.encode(key); + } else if (format === 'spki' && key?.algorithm?.id) + return gostCrypto.asn1.GostSubjectPublicKeyInfo.encode(key); + else + throw new NotSupportedError('Key format not supported'); + }); +}; // + +/** + * The wrapKey method returns a new Promise object that will wrapped key(s). + * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-wrapKey}

+ * + * Supported algorithm names: + *
    + *
  • GOST 28147-KW Key Wrapping GOST 28147 modes
  • + *
  • GOST R 34.12-KW Key Wrapping GOST R 34.12 modes
  • + *
  • GOST 28147-MASK Key Mask GOST 28147 modes
  • + *
  • GOST R 34.12-MASK Key Mask GOST R 34.12 modes
  • + *
  • GOST R 34.10-MASK Key Mask GOST R 34.10 modes
  • + *
+ * For additional modes see {@link GostCipher}
+ * + * @memberOf SubtleCrypto + * @method wrapKey + * @instance + * @param {KeyFormat} format Format specifies a serialization format for a key. Now suppored only 'raw' key format. + * @param {Key} key Key object + * @param {Key} wrappingKey Wrapping key object + * @param {AlgorithmIdentifier} wrapAlgorithm Algorithm identifier + * @returns {Promise} Promise that resolves with {@link CryptoOperationData} + */ +SubtleCrypto.prototype.wrapKey = function (format, key, wrappingKey, wrapAlgorithm) // +{ + return new Promise(call).then(function () { + if (checkNative(wrapAlgorithm)) + return rootCrypto.subtle.wrapKey(format, key, wrappingKey, wrapAlgorithm); + + wrapAlgorithm = normalize(wrapAlgorithm, 'wrapKey'); + var keyData = extractKey(null, null, key); + if (wrapAlgorithm.procreator === 'SC' && key.type === 'private') + keyData = swapBytes(keyData); + return execute(wrapAlgorithm, 'wrapKey', + [extractKey('wrapKey', wrapAlgorithm, wrappingKey), keyData]).then(function (data) { + if (format === 'raw') + return data; + else + throw new NotSupportedError('Key format not supported'); + }); + }); +}; // + +/** + * The unwrapKey method returns a new Promise object that will unwrapped key(s). + * WebCrypto API reference {@link http://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-unwrapKey}

+ * + * Supported algorithm names: + *
    + *
  • GOST 28147-KW Key Wrapping GOST 28147 modes
  • + *
  • GOST R 34.12-KW Key Wrapping GOST R 34.12 modes
  • + *
  • GOST 28147-MASK Key Mask GOST 28147 modes
  • + *
  • GOST R 34.12-MASK Key Mask GOST R 34.12 modes
  • + *
  • GOST R 34.10-MASK Key Mask GOST R 34.10 modes
  • + *
+ * For additional modes see {@link GostCipher}
+ * + * @memberOf SubtleCrypto + * @method unwrapKey + * @instance + * @param {KeyFormat} format Format specifies a serialization format for a key. Now suppored only 'raw' key format. + * @param {CryptoOperationData} wrappedKey Wrapped key data + * @param {Key} unwrappingKey Unwrapping key object + * @param {AlgorithmIdentifier} unwrapAlgorithm Algorithm identifier + * @param {AlgorithmIdentifier} unwrappedKeyAlgorithm Key algorithm identifier + * @param {boolean} extractable Whether or not the raw keying material may be exported by the application + * @param {KeyUsages} keyUsages Key usage array: type of operation that may be performed using a key + * @returns {Promise} Promise that resolves with {@link Key} + */ +SubtleCrypto.prototype.unwrapKey = function (format, wrappedKey, unwrappingKey, + unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages) // +{ + return new Promise(call).then(function () { + if (checkNative(unwrapAlgorithm)) + return rootCrypto.subtle.unwrapKey(format, wrappedKey, unwrappingKey, + unwrapAlgorithm, unwrappedKeyAlgorithm, extractable, keyUsages); + + unwrapAlgorithm = normalize(unwrapAlgorithm, 'unwrapKey'); + unwrappedKeyAlgorithm = normalize(unwrappedKeyAlgorithm, 'importKey'); + if (format !== 'raw') + throw new NotSupportedError('Key format not supported'); + + return execute(unwrapAlgorithm, 'unwrapKey', [extractKey('unwrapKey', unwrapAlgorithm, unwrappingKey), wrappedKey]).then(function (data) { + var type; + if (unwrappedKeyAlgorithm && unwrappedKeyAlgorithm.name) { + var name = unwrappedKeyAlgorithm.name.toUpperCase().replace(/[\.\s]/g, ''); + if (name.indexOf('3410') >= 0 && keyUsages.indexOf('sign') >= 0) + type = 'private'; + else if (name.indexOf('3410') >= 0 && keyUsages.indexOf('verify') >= 0) + type = 'public'; + } + if (unwrapAlgorithm.procreator === 'SC' && type === 'private') + data = swapBytes(data); + return convertKey(unwrappedKeyAlgorithm, extractable, keyUsages, data, type); + }); + }); +}; // + +/** + * The subtle attribute provides an instance of the SubtleCrypto + * interface which provides low-level cryptographic primitives and + * algorithms. + * + * @memberOf gostCrypto + * @type SubtleCrypto + */ +gostCrypto.subtle = new SubtleCrypto(); + +/** + * The getRandomValues method generates cryptographically random values. + * + * First try to use Web Crypto random genereator. Next make random + * bytes based on standart Math.random mixed with time and mouse pointer + * + * @memberOf gostCrypto + * @param {(CryptoOperationData)} array Destination buffer for random data + */ +gostCrypto.getRandomValues = function (array) // +{ + // Execute randomizer + GostRandom = GostRandom || root.GostRandom; + var randomSource = GostRandom ? new GostRandom() : rootCrypto; + if (randomSource.getRandomValues) + randomSource.getRandomValues(array); + else + throw new NotSupportedError('Random generator not found'); +}; // +//
+ +export default gostCrypto; diff --git a/plugins/srktoolbox/src/core/vendor/gost/gostDigest.mjs b/plugins/srktoolbox/src/core/vendor/gost/gostDigest.mjs new file mode 100644 index 00000000..4d5a04e1 --- /dev/null +++ b/plugins/srktoolbox/src/core/vendor/gost/gostDigest.mjs @@ -0,0 +1,1260 @@ +/** + * GOST R 34.11-94 / GOST R 34.11-12 implementation + * 1.76 + * 2014-2016, Rudolf Nickolaev. All rights reserved. + * + * Exported for CyberChef by mshwed [m@ttshwed.com] + */ + +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Converted to JavaScript from source https://www.streebog.net/ + * Copyright (c) 2013, Alexey Degtyarev. + * All rights reserved. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + import GostRandom from './gostRandom.mjs'; + import GostCipher from './gostCipher.mjs'; + import crypto from 'crypto'; + +/* + * GOST R 34.11 + * Common methods + * + */ // + +var root = {}; +var rootCrypto = crypto + +var DataError = Error, + NotSupportedError = Error; + +// Copy len values from s[sOfs] to d[dOfs] +function arraycopy(s, sOfs, d, dOfs, len) { + for (var i = 0; i < len; i++) + d[dOfs + i] = s[sOfs + i]; +} + +// Swap bytes in buffer +function swap(s) { + var src = new Uint8Array(s), + dst = new Uint8Array(src.length); + for (var i = 0, n = src.length; i < n; i++) + dst[n - i - 1] = src[i]; + return dst.buffer; +} + +// Convert BASE64 string to Uint8Array +// for decompression of constants and precalc values +function b64decode(s) { + // s = s.replace(/[^A-Za-z0-9\+\/]/g, ''); + var n = s.length, + k = n * 3 + 1 >> 2, r = new Uint8Array(k); + + for (var m3, m4, u24 = 0, j = 0, i = 0; i < n; i++) { + m4 = i & 3; + var c = s.charCodeAt(i); + + c = c > 64 && c < 91 ? + c - 65 : c > 96 && c < 123 ? + c - 71 : c > 47 && c < 58 ? + c + 4 : c === 43 ? + 62 : c === 47 ? + 63 : 0; + + u24 |= c << 18 - 6 * m4; + if (m4 === 3 || n - i === 1) { + for (m3 = 0; m3 < 3 && j < k; m3++, j++) { + r[j] = u24 >>> (16 >>> m3 & 24) & 255; + } + u24 = 0; + + } + } + return r.buffer; +} + +// Random seed +function getSeed(length) { + GostRandom = GostRandom || root.GostRandom; + var randomSource = GostRandom ? new (GostRandom || root.GostRandom) : rootCrypto; + if (randomSource.getRandomValues) { + var d = new Uint8Array(Math.ceil(length / 8)); + randomSource.getRandomValues(d); + return d; + } else + throw new NotSupportedError('Random generator not found'); +} + +// Check buffer +function buffer(d) { + if (d instanceof ArrayBuffer) + return d; + else if (d && d?.buffer instanceof ArrayBuffer) + return d.byteOffset === 0 && d.byteLength === d.buffer.byteLength ? + d.buffer : new Uint8Array(new Uint8Array(d, d.byteOffset, d.byteLength)).buffer; + else + throw new DataError('ArrayBuffer or ArrayBufferView required'); +} // + +/** + * Algorithm name GOST R 34.11 or GOST R 34.11-12

+ * + * http://tools.ietf.org/html/rfc6986 + * + * The digest method returns digest data in according to GOST R 4311-2012.
+ * Size of digest also defines in algorithm name. + *
    + *
  • GOST R 34.11-256-12 - 256 bits digest
  • + *
  • GOST R 34.11-512-12 - 512 bits digest
  • + *
+ * + * @memberOf GostDigest + * @method digest + * @instance + * @param {(ArrayBuffer|TypedArray)} data Data + * @returns {ArrayBuffer} Digest of data + */ +var digest2012 = (function () // +{ + // Constants + var buffer0 = new Int32Array(16); // [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + + var buffer512 = new Int32Array(16); // [512, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + buffer512[0] = 512; + + // Constant C + var C = (function (s) { + var h = new Int32Array(b64decode(s)), + r = new Array(12); + for (var i = 0; i < 12; i++) + r[i] = new Int32Array(h.buffer, i * 64, 16); + return r; + })( + 'B0Wm8lllgN0jTXTMNnR2BRXTYKQIKkKiAWlnkpHgfEv8xIV1jbhOcRbQRS5DdmovH3xlwIEvy+vp2soe2lsIsbebsSFwBHnmVs3L1xui3VXKpwrbwmG1XFiZ1hJrF7WaMQG1Fg9e1WGYKyMKcur+89e1cA9GneNPGi+dqYq1o2+yCroK9ZYemTHbeoZD9LbCCdtiYDc6ycGxnjWQ5A/i03t7KbEUderyix+cUl9e8QY1hD1qKPw5Cscvzius3HT1LtHjhLy+DCLxN+iToepTNL4DUpMzE7fYddYD7YIs16k/NV5orRxynX08XDN+hY5I3eRxXaDhSPnSZhXos98f71f+bHz9WBdg9WPqqX6iVnoWGicjtwD/36P1OiVHF82/vf8PgNc1njVKEIYWHxwVf2MjqWwMQT+amUdHraxr6ktufWRGekBo+jVPkDZyxXG/tsa+wmYf8gq0t5oct6b6z8aO8Jq0mn8YbKRCUfnEZi3AOTB6O8Okb9nTOh2urk+uk9QUOk1WhojzSjyiTEUXNQQFSiiDaUcGNyyCLcWrkgnJk3oZMz5H08mHv+bHxp45VAkkv/6GrFHsxaruFg7H9B7nAr/UDX+k' + + '2ahRWTXCrDYvxKXRK43RaZAGm5LLK4n0msTbTTtEtIke3jaccfi3TkFBbgwCqucDp8mTTUJbH5vbWiODUURhcmAqH8uS3DgOVJwHppqKK3uxzrLbC0QKgIQJDeC3Vdk8JEKJJRs6fTreXxbs2JpMlJsiMRZUWo837ZxFmPvHtHTDtjsV0fqYNvRSdjswbB56SzNprwJn558DYTMbiuH/H9t4iv8c50GJ8/PkskjlKjhSbwWApt6+qxst84HNpMprXdhvwEpZot6Ybkd9Hc2678q5SOrvcR2KeWaEFCGAASBhB6vru2v62JT+WmPNxgIw+4nI79CezXsg1xvxSpK8SJkbstnVF/T6UijhiKqkHeeGzJEYne+AXZufITDUEiD4dx3fvDI8pM16sUkEsIAT0roxFvFn5443'); + + // Precalc Ax + var Ax = (function (s) { + return new Int32Array(b64decode(s)); + })( + '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'); //== + + // Variables + var sigma, N, h; + + // 64bit tools + function get8(x, i) { + return (x[i >> 2] >> ((i & 3) << 3)) & 0xff; + } + + // 512bit tools + function add512(x, y) { + var CF = 0, w0, w1; + for (var i = 0; i < 16; i++) { + w0 = (x[i] & 0xffff) + (y[i] & 0xffff) + (CF || 0); + w1 = (x[i] >>> 16) + (y[i] >>> 16) + (w0 >>> 16); + x[i] = (w0 & 0xffff) | (w1 << 16); + CF = (w1 >>> 16); + } + } + + function get512(d) { + return new Int32Array(d.buffer, d.byteOffset, 16); + } + + + function copy512(r, d) { + for (var i = 0; i < 16; i++) + r[i] = d[i]; + } + + function new512() { + return new Int32Array(16); + } + + // Core private algorithms + function xor512(x, y) { + for (var i = 0; i < 16; i++) + x[i] = x[i] ^ y[i]; + } + + + var r = new512(); + function XLPS(x, y) { + copy512(r, x); + xor512(r, y); + for (var i = 0; i < 8; i++) { + var z0, z1, k = get8(r, i) << 1; + z0 = Ax[k]; + z1 = Ax[k + 1]; + for (var j = 1; j < 8; j++) { + k = (j << 9) + (get8(r, (j << 3) + i) << 1); + z0 = z0 ^ Ax[k]; + z1 = z1 ^ Ax[k + 1]; + } + x[i << 1] = z0; + x[(i << 1) + 1] = z1; + } + } + + var data = new512(), Ki = new512(); + function g(h, N, m) + { + var i; + + copy512(data, h); + XLPS(data, N); + + /* Starting E() */ + copy512(Ki, data); + XLPS(data, m); + + for (i = 0; i < 11; i++) { + XLPS(Ki, C[i]); + XLPS(data, Ki); + } + + XLPS(Ki, C[11]); + xor512(data, Ki); + /* E() done */ + + xor512(h, data); + xor512(h, m); + } + + // Stages + function stage2(d) { + var m = get512(d); + g(h, N, m); + + add512(N, buffer512); + add512(sigma, m); + } + + function stage3(d) { + var n = d.length; + if (n > 63) + return; + + var b0 = new Int32Array(16); + b0[0] = n << 3; + + var b = new Uint8Array(64); + for (var i = 0; i < n; i++) + b[i] = d[i]; + b[n] = 0x01; + + var m = get512(b), m0 = get512(b0); + g(h, N, m); + + add512(N, m0); + add512(sigma, m); + + g(h, buffer0, N); + g(h, buffer0, sigma); + } + + return function (data) { + + // Cleanup + sigma = new512(); + N = new512(); + + // Initial vector + h = new512(); + for (var i = 0; i < 16; i++) + if (this.bitLength === 256) + h[i] = 0x01010101; + + // Make data + var d = new Uint8Array(buffer(data)); + + var n = d.length; + var r = n % 64, q = (n - r) / 64; + + for (var i = 0; i < q; i++) + stage2.call(this, new Uint8Array(d.buffer, i * 64, 64)); + + stage3.call(this, new Uint8Array(d.buffer, q * 64, r)); + + var digest; + if (this.bitLength === 256) { + digest = new Int32Array(8); + for (var i = 0; i < 8; i++) + digest[i] = h[8 + i]; + } else { + digest = new Int32Array(16); + for (var i = 0; i < 16; i++) + digest[i] = h[i]; + } + // Swap hash for SignalCom + if (this.procreator === 'SC' || this.procreator === 'VN') + return swap(digest.buffer); + else + return digest.buffer; + }; +} // +)(); + +/** + * Algorithm name GOST R 34.11-94

+ * + * http://tools.ietf.org/html/rfc5831 + * + * The digest method returns digest data in according to GOST R 34.11-94. + * @memberOf GostDigest + * @method digest + * @instance + * @param {(ArrayBuffer|TypedArray)} data Data + * @returns {ArrayBuffer} Digest of data + */ +var digest94 = (function () // +{ + var C, H, M, Sum; + + // (i + 1 + 4(k - 1)) = 8i + k i = 0-3, k = 1-8 + function P(d) { + var K = new Uint8Array(32); + + for (var k = 0; k < 8; k++) { + K[4 * k] = d[k]; + K[1 + 4 * k] = d[ 8 + k]; + K[2 + 4 * k] = d[16 + k]; + K[3 + 4 * k] = d[24 + k]; + } + + return K; + } + + //A (x) = (x0 ^ x1) || x3 || x2 || x1 + function A(d) + { + var a = new Uint8Array(8); + + for (var j = 0; j < 8; j++) + { + a[j] = (d[j] ^ d[j + 8]); + } + + arraycopy(d, 8, d, 0, 24); + arraycopy(a, 0, d, 24, 8); + + return d; + } + + // (in:) n16||..||n1 ==> (out:) n1^n2^n3^n4^n13^n16||n16||..||n2 + function fw(d) { + var wS = new Uint16Array(d.buffer, 0, 16); + var wS15 = wS[0] ^ wS[1] ^ wS[2] ^ wS[3] ^ wS[12] ^ wS[15]; + arraycopy(wS, 1, wS, 0, 15); + wS[15] = wS15; + } + + //Encrypt function, ECB mode + function encrypt(key, s, sOff, d, dOff) { + var t = new Uint8Array(8); + arraycopy(d, dOff, t, 0, 8); + var r = new Uint8Array(this.cipher.encrypt(key, t)); + arraycopy(r, 0, s, sOff, 8); + } + + // block processing + function process(d, dOff) { + var S = new Uint8Array(32), U = new Uint8Array(32), + V = new Uint8Array(32), W = new Uint8Array(32); + + arraycopy(d, dOff, M, 0, 32); + + //key step 1 + + // H = h3 || h2 || h1 || h0 + // S = s3 || s2 || s1 || s0 + arraycopy(H, 0, U, 0, 32); + arraycopy(M, 0, V, 0, 32); + for (var j = 0; j < 32; j++) + { + W[j] = (U[j] ^ V[j]); + } + // Encrypt GOST 28147-ECB + encrypt.call(this, P(W), S, 0, H, 0); // s0 = EK0 [h0] + + //keys step 2,3,4 + for (var i = 1; i < 4; i++) { + var tmpA = A(U); + for (var j = 0; j < 32; j++) { + U[j] = (tmpA[j] ^ C[i][j]); + } + V = A(A(V)); + for (var j = 0; j < 32; j++) { + W[j] = (U[j] ^ V[j]); + } + // Encrypt GOST 28147-ECB + encrypt.call(this, P(W), S, i * 8, H, i * 8); // si = EKi [hi] + } + + // x(M, H) = y61(H^y(M^y12(S))) + for (var n = 0; n < 12; n++) { + fw(S); + } + for (var n = 0; n < 32; n++) { + S[n] = (S[n] ^ M[n]); + } + + fw(S); + + for (var n = 0; n < 32; n++) { + S[n] = (H[n] ^ S[n]); + } + for (var n = 0; n < 61; n++) { + fw(S); + } + arraycopy(S, 0, H, 0, H.length); + } + + + // 256 bitsblock modul -> (Sum + a mod (2^256)) + function summing(d) + { + var carry = 0; + for (var i = 0; i < Sum.length; i++) + { + var sum = (Sum[i] & 0xff) + (d[i] & 0xff) + carry; + + Sum[i] = sum; + + carry = sum >>> 8; + } + } + + // reset the chaining variables to the IV values. + var C2 = new Uint8Array([ + 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF + ]); + + return function (data) { + + // Reset buffers + H = new Uint8Array(32); + M = new Uint8Array(32); + Sum = new Uint8Array(32); + + // Reset IV value + C = new Array(4); + for (var i = 0; i < 4; i++) + C[i] = new Uint8Array(32); + arraycopy(C2, 0, C[2], 0, C2.length); + + // Make data + var d = new Uint8Array(buffer(data)); + + var n = d.length; + var r = n % 32, q = (n - r) / 32; + + // Proccess full blocks + for (var i = 0; i < q; i++) { + var b = new Uint8Array(d.buffer, i * 32, 32); + + summing.call(this, b); // calc sum M + process.call(this, b, 0); + } + + // load d the remadder with padding zero; + if (r > 0) { + var b = new Uint8Array(d.buffer, q * 32), + c = new Uint8Array(32); + arraycopy(b, 0, c, 0, r); + summing.call(this, c); // calc sum M + process.call(this, c, 0); + + } + + // get length into L (byteCount * 8 = bitCount) in little endian. + var L = new Uint8Array(32), n8 = n * 8, k = 0; + while (n8 > 0) { + L[k++] = n8 & 0xff; + n8 = Math.floor(n8 / 256); + } + process.call(this, L, 0); + process.call(this, Sum, 0); + + var h = H.buffer; + + // Swap hash for SignalCom + if (this.procreator === 'SC') + h = swap(h); + + return h; + }; + +} // +)(); + +/** + * Algorithm name SHA-1

+ * + * https://tools.ietf.org/html/rfc3174 + * + * The digest method returns digest data in according to SHA-1.
+ * + * @memberOf GostDigest + * @method digest + * @instance + * @param {(ArrayBuffer|TypedArray)} data Data + * @returns {ArrayBuffer} Digest of data + */ +var digestSHA1 = (function () // +{ + + // Create a buffer for each 80 word block. + var state, block = new Uint32Array(80); + + function common(a, e, w, k, f) { + return (f + e + w + k + ((a << 5) | (a >>> 27))) >>> 0; + } + + function f1(a, b, c, d, e, w) { + return common(a, e, w, 0x5A827999, d ^ (b & (c ^ d))); + } + + function f2(a, b, c, d, e, w) { + return common(a, e, w, 0x6ED9EBA1, b ^ c ^ d); + } + + function f3(a, b, c, d, e, w) { + return common(a, e, w, 0x8F1BBCDC, (b & c) | (d & (b | c))); + } + + function f4(a, b, c, d, e, w) { + return common(a, e, w, 0xCA62C1D6, b ^ c ^ d); + } + + function cycle(state, block) { + var a = state[0], + b = state[1], + c = state[2], + d = state[3], + e = state[4]; + + // Partially unroll loops so we don't have to shift variables. + var fn = f1; + for (var i = 0; i < 80; i += 5) { + if (i === 20) { + fn = f2; + } + else if (i === 40) { + fn = f3; + } + else if (i === 60) { + fn = f4; + } + e = fn(a, b, c, d, e, block[i]); + b = ((b << 30) | (b >>> 2)) >>> 0; + d = fn(e, a, b, c, d, block[i + 1]); + a = ((a << 30) | (a >>> 2)) >>> 0; + c = fn(d, e, a, b, c, block[i + 2]); + e = ((e << 30) | (e >>> 2)) >>> 0; + b = fn(c, d, e, a, b, block[i + 3]); + d = ((d << 30) | (d >>> 2)) >>> 0; + a = fn(b, c, d, e, a, block[i + 4]); + c = ((c << 30) | (c >>> 2)) >>> 0; + } + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + } + + // Swap bytes for 32bits word + function swap32(b) { + return ((b & 0xff) << 24) + | ((b & 0xff00) << 8) + | ((b >> 8) & 0xff00) + | ((b >> 24) & 0xff); + } + + // input is a Uint8Array bitstream of the data + return function (data) { + var d = new Uint8Array(buffer(data)), dlen = d.length; + + // Pad the input string length. + var len = dlen + 9; + if (len % 64) { + len += 64 - (len % 64); + } + + state = new Uint32Array(5); + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; + state[4] = 0xc3d2e1f0; + + for (var ofs = 0; ofs < len; ofs += 64) { + + // Copy input to block and write padding as needed + for (var i = 0; i < 64; i++) { + var b = 0, + o = ofs + i; + if (o < dlen) { + b = d[o]; + } + else if (o === dlen) { + b = 0x80; + } + else { + // Write original bit length as a 64bit big-endian integer to the end. + var x = len - o - 1; + if (x >= 0 && x < 4) { + b = (dlen << 3 >>> (x * 8)) & 0xff; + } + } + + // Interpret the input bytes as big-endian per the spec + if (i % 4 === 0) { + block[i >> 2] = b << 24; + } + else { + block[i >> 2] |= b << ((3 - (i % 4)) * 8); + } + } + + // Extend the block + for (var i = 16; i < 80; i++) { + var w = block[i - 3] ^ block[i - 8] ^ block[i - 14] ^ block[i - 16]; + block[i] = (w << 1) | (w >>> 31); + } + + cycle(state, block); + + } + + // Swap the bytes around since they are big endian internally + for (var i = 0; i < 5; i++) + state[i] = swap32(state[i]); + return state.buffer; + }; + +} // +)(); + +/** + * Algorithm name GOST R 34.11-HMAC

+ * + * HMAC with the specified hash function. + * @memberOf GostDigest + * @method sign + * @instance + * @param {ArrayBuffer} key The key for HMAC. + * @param {Hash} data Data + */ +function signHMAC(key, data) // +{ + // GOST R 34.11-94 - B=32b, L=32b + // GOST R 34.11-256 - B=64b, L=32b + // GOST R 34.11-512 - B=64b, L=64b + var b = (this.digest === digest94) ? 32 : 64, + l = this.bitLength / 8, + k = buffer(key), + d = buffer(data), k0; + if (k.byteLength === b) + k0 = new Uint8Array(k); + else { + var k0 = new Uint8Array(b); + if (k.byteLength > b) { + k0.set(new Uint8Array(this.digest(k))); + } else { + k0.set(new Uint8Array(k)); + } + } + var s0 = new Uint8Array(b + d.byteLength), + s1 = new Uint8Array(b + l); + for (var i = 0; i < b; i++) { + s0[i] = k0[i] ^ 0x36; + s1[i] = k0[i] ^ 0x5C; + } + s0.set(new Uint8Array(d), b); + s1.set(new Uint8Array(this.digest(s0)), b); + return this.digest(s1); +} // + +/** + * Algorithm name GOST R 34.11-HMAC

+ * + * Verify HMAC based on GOST R 34.11 hash + * + * @memberOf GostDigest + * @method verify + * @instance + * @param {(ArrayBuffer|TypedArray)} key Key which used for HMAC generation + * @param {(ArrayBuffer|TypedArray)} signature generated HMAC + * @param {(ArrayBuffer|TypedArray)} data Data + * @returns {boolean} HMAC verified = true + */ +function verifyHMAC(key, signature, data) // +{ + var hmac = new Uint8Array(this.sign(key, data)), + test = new Uint8Array(signature); + if (hmac.length !== test.length) + return false; + for (var i = 0, n = hmac.length; i < n; i++) + if (hmac[i] !== test[i]) + return false; + return true; +} // + + +/** + * Algorithm name GOST R 34.11-KDF

+ * + * Simple generate key 256/512 bit random seed for derivation algorithms + * + * @memberOf GostDigest + * @method generateKey + * @instance + * @returns {ArrayBuffer} Generated key + */ +function generateKey() // +{ + return getSeed(this.bitLength).buffer; +} // + +/** + * Algorithm name GOST R 34.11-PFXKDF

+ * + * Derive bits from password (PKCS12 mode) + *
    + *
  • algorithm.salt - random value, salt
  • + *
  • algorithm.iterations - number of iterations
  • + *
+ * @memberOf GostDigest + * @method deriveBits + * @instance + * @param {ArrayBuffer} baseKey - password after UTF-8 decoding + * @param {number} length output bit-length + * @returns {ArrayBuffer} result + */ +function deriveBitsPFXKDF(baseKey, length) // +{ + if (length % 8 > 0) + throw new DataError('Length must multiple of 8'); + var u = this.bitLength / 8, v = (this.digest === digest94) ? 32 : 64, + n = length / 8, r = this.iterations; + // 1. Construct a string, D (the "diversifier"), by concatenating v/8 + // copies of ID. + var ID = this.diversifier, D = new Uint8Array(v); + for (var i = 0; i < v; i++) + D[i] = ID; + // 2. Concatenate copies of the salt together to create a string S of + // length v(ceiling(s/v)) bits (the final copy of the salt may be + // truncated to create S). Note that if the salt is the empty + // string, then so is S. + var S0 = new Uint8Array(buffer(this.salt)), s = S0.length, + slen = v * Math.ceil(s / v), S = new Uint8Array(slen); + for (var i = 0; i < slen; i++) + S[i] = S0[i % s]; + // 3. Concatenate copies of the password together to create a string P + // of length v(ceiling(p/v)) bits (the final copy of the password + // may be truncated to create P). Note that if the password is the + // empty string, then so is P. + var P0 = new Uint8Array(buffer(baseKey)), p = P0.length, + plen = v * Math.ceil(p / v), P = new Uint8Array(plen); + for (var i = 0; i < plen; i++) + P[i] = P0[i % p]; + // 4. Set I=S||P to be the concatenation of S and P. + var I = new Uint8Array(slen + plen); + arraycopy(S, 0, I, 0, slen); + arraycopy(P, 0, I, slen, plen); + // 5. Set c=ceiling(n/u). + var c = Math.ceil(n / u); + // 6. For i=1, 2, ..., c, do the following: + var A = new Uint8Array(c * u); + for (var i = 0; i < c; i++) { + // A. Set A2=H^r(D||I). (i.e., the r-th hash of D||1, + // H(H(H(... H(D||I)))) + var H = new Uint8Array(v + slen + plen); + arraycopy(D, 0, H, 0, v); + arraycopy(I, 0, H, v, slen + plen); + for (var j = 0; j < r; j++) + H = new Uint8Array(this.digest(H)); + arraycopy(H, 0, A, i * u, u); + // B. Concatenate copies of Ai to create a string B of length v + // bits (the final copy of Ai may be truncated to create B). + var B = new Uint8Array(v); + for (var j = 0; j < v; j++) + B[j] = H[j % u]; + // C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit + // blocks, where k=ceiling(s/v)+ceiling(p/v), modify I by + // setting I_j=(I_j+B+1) mod 2^v for each j. + var k = (slen + plen) / v; + for (j = 0; j < k; j++) { + var cf = 1, w; + for (var l = v - 1; l >= 0; --l) { + w = I[v * j + l] + B[l] + cf; + cf = w >>> 8; + I[v * j + l] = w & 0xff; + } + } + } + // 7. Concatenate A_1, A_2, ..., A_c together to form a pseudorandom + // bit string, A. + // 8. Use the first n bits of A as the output of this entire process. + var R = new Uint8Array(n); + arraycopy(A, 0, R, 0, n); + return R.buffer; +} // + +/** + * Algorithm name GOST R 34.11-KDF

+ * + * Derive bits for KEK deversification in 34.10-2012 algorithm + * KDF(KEK, UKM, label) = HMAC256 (KEK, 0x01|label|0x00|UKM|0x01|0x00) + * Default label = 0x26|0xBD|0xB8|0x78 + * + * @memberOf GostDigest + * @method deriveBits + * @instance + * @param {(ArrayBuffer|TypedArray)} baseKey base key for deriviation + * @param {number} length output bit-length + * @returns {ArrayBuffer} result + */ +function deriveBitsKDF(baseKey, length) // +{ + if (length % 8 > 0) + throw new DataError('Length must be multiple of 8'); + var rlen = length / 8, label, context = new Uint8Array(buffer(this.context)), + blen = this.bitLength / 8, n = Math.ceil(rlen / blen); + if (this.label) + label = new Uint8Array(buffer(this.label)); + else + label = new Uint8Array([0x26, 0xBD, 0xB8, 0x78]); + var result = new Uint8Array(rlen); + for (var i = 0; i < n; i++) { + var data = new Uint8Array(label.length + context.length + 4); + data[0] = i + 1; + data.set(label, 1); + data[label.length + 1] = 0x00; + data.set(context, label.length + 2); + data[data.length - 2] = length >>> 8; + data[data.length - 1] = length & 0xff; + result.set(new Uint8Array(signHMAC.call(this, baseKey, data), 0, + i < n - 1 ? blen : rlen - i * blen), i * blen); + } + return result.buffer; +} // + +/** + * Algorithm name GOST R 34.11-PBKDF1

+ * + * Derive bits from password + *
    + *
  • algorithm.salt - random value, salt
  • + *
  • algorithm.iterations - number of iterations
  • + *
+ * @memberOf GostDigest + * @method deriveBits + * @instance + * @param {ArrayBuffer} baseKey - password after UTF-8 decoding + * @param {number} length output bit-length + * @returns {ArrayBuffer} result + */ +function deriveBitsPBKDF1(baseKey, length) // +{ + if (length < this.bitLength / 2 || length % 8 > 0) + throw new DataError('Length must be more than ' + this.bitLength / 2 + ' bits and multiple of 8'); + var hLen = this.bitLength / 8, dkLen = length / 8, + c = this.iterations, + P = new Uint8Array(buffer(baseKey)), + S = new Uint8Array(buffer(this.salt)), + slen = S.length, plen = P.length, + T = new Uint8Array(plen + slen), + DK = new Uint8Array(dkLen); + if (dkLen > hLen) + throw new DataError('Invalid parameters: Length value'); + arraycopy(P, 0, T, 0, plen); + arraycopy(S, 0, T, plen, slen); + for (var i = 0; i < c; i++) + T = new Uint8Array(this.digest(T)); + arraycopy(T, 0, DK, 0, dkLen); + return DK.buffer; +} // + +/** + * Algorithm name GOST R 34.11-PBKDF2

+ * + * Derive bits from password + *
    + *
  • algorithm.salt - random value, salt
  • + *
  • algorithm.iterations - number of iterations
  • + *
+ * @memberOf GostDigest + * @method deriveBits + * @instance + * @param {ArrayBuffer} baseKey - password after UTF-8 decoding + * @param {number} length output bit-length + * @returns {ArrayBuffer} result + */ +function deriveBitsPBKDF2(baseKey, length) // +{ + var diversifier = this.diversifier || 1; // For PKCS12 MAC required 3*length + length = length * diversifier; + if (length < this.bitLength / 2 || length % 8 > 0) + throw new DataError('Length must be more than ' + this.bitLength / 2 + ' bits and multiple of 8'); + var hLen = this.bitLength / 8, dkLen = length / 8, + c = this.iterations, + P = new Uint8Array(buffer(baseKey)), + S = new Uint8Array(buffer(this.salt)); + var slen = S.byteLength, + data = new Uint8Array(slen + 4); + arraycopy(S, 0, data, 0, slen); + + if (dkLen > (0xffffffff - 1) * 32) + throw new DataError('Invalid parameters: Length value'); + var n = Math.ceil(dkLen / hLen), + DK = new Uint8Array(dkLen); + for (var i = 1; i <= n; i++) { + data[slen] = i >>> 24 & 0xff; + data[slen + 1] = i >>> 16 & 0xff; + data[slen + 2] = i >>> 8 & 0xff; + data[slen + 3] = i & 0xff; + + var U = new Uint8Array(signHMAC.call(this, P, data)), Z = U; + for (var j = 1; j < c; j++) { + U = new Uint8Array(signHMAC.call(this, P, U)); + for (var k = 0; k < hLen; k++) + Z[k] = U[k] ^ Z[k]; + } + var ofs = (i - 1) * hLen; + arraycopy(Z, 0, DK, ofs, Math.min(hLen, dkLen - ofs)); + } + if (diversifier > 1) { + var rLen = dkLen / diversifier, R = new Uint8Array(rLen); + arraycopy(DK, dkLen - rLen, R, 0, rLen); + return R.buffer; + } else + return DK.buffer; +} // + +/** + * Algorithm name GOST R 34.11-CPKDF

+ * + * Derive bits from password. CryptoPro algorithm + *
    + *
  • algorithm.salt - random value, salt
  • + *
  • algorithm.iterations - number of iterations
  • + *
+ * @memberOf GostDigest + * @method deriveBits + * @instance + * @param {ArrayBuffer} baseKey - password after UTF-8 decoding + * @param {number} length output bit-length + * @returns {ArrayBuffer} result + */ +function deriveBitsCP(baseKey, length) { + if (length > this.bitLength || length % 8 > 0) + throw new DataError('Length can\'t be more than ' + this.bitLength + ' bits and multiple of 8'); + // GOST R 34.11-94 - B=32b, L=32b + // GOST R 34.11-256 - B=64b, L=32b + // GOST R 34.11-512 - B=64b, L=64b + var b = (this.digest === digest94) ? 32 : 64, + l = this.bitLength / 8, + p = baseKey && baseKey.byteLength > 0 ? new Uint8Array(buffer(baseKey)) : false, + plen = p ? p.length : 0, + iterations = this.iterations, + salt = new Uint8Array(buffer(this.salt)), + slen = salt.length, + d = new Uint8Array(slen + plen); + arraycopy(salt, 0, d, 0, slen); + if (p) + arraycopy(p, 0, d, slen, plen); + + var h = new Uint8Array(this.digest(d)), + k = new Uint8Array(b), + s0 = new Uint8Array(b), + s1 = new Uint8Array(b); + var c = 'DENEFH028.760246785.IUEFHWUIO.EF'; + for (var i = 0; i < c.length; i++) + k[i] = c.charCodeAt(i); + + d = new Uint8Array(2 * (b + l)); + for (var j = 0; j < iterations; j++) { + for (var i = 0; i < b; i++) { + s0[i] = k[i] ^ 0x36; + s1[i] = k[i] ^ 0x5C; + k[i] = 0; + } + arraycopy(s0, 0, d, 0, b); + arraycopy(h, 0, d, b, l); + arraycopy(s1, 0, d, b + l, b); + arraycopy(h, 0, d, b + l + b, l); + arraycopy(new Uint8Array(this.digest(d)), 0, k, 0, l); + } + for (var i = 0; i < l; i++) { + s0[i] = k[i] ^ 0x36; + s1[i] = k[i] ^ 0x5C; + k[i] = 0; + } + d = new Uint8Array(2 * l + slen + plen); + arraycopy(s0, 0, d, 0, l); + arraycopy(salt, 0, d, l, slen); + arraycopy(s1, 0, d, l + slen, l); + if (p) + arraycopy(p, 0, d, l + slen + l, plen); + h = this.digest(this.digest(d)); + if (length === this.bitLength) + return h; + else { + var rlen = length / 8, r = new Uint8Array(rlen); + arraycopy(h, 0, r, 0, rlen); + return r.buffer; + } +} + +/** + * Algorithm name GOST R 34.11-KDF or GOST R 34.11-PBKDF2 or other

+ * + * Derive key from derive bits subset + * + * @memberOf GostDigest + * @method deriveKey + * @instance + * @param {ArrayBuffer} baseKey + * @returns {ArrayBuffer} + */ +function deriveKey(baseKey) // +{ + return this.deriveBits(baseKey, this.keySize * 8); +} // + +/** + * GOST R 34.11 Algorithm

+ * + * References: {@link http://tools.ietf.org/html/rfc6986} and {@link http://tools.ietf.org/html/rfc5831}

+ * + * Normalized algorithm identifier common parameters: + * + *
    + *
  • name Algorithm name 'GOST R 34.11'
  • + *
  • version Algorithm version + *
      + *
    • 1994 old-style 256 bits digest based on GOST 28147-89
    • + *
    • 2012 256 ro 512 bits digest algorithm "Streebog" GOST R 34.11-2012 (default)
    • + *
    + *
  • + *
  • length Digest length + *
      + *
    • 256 256 bits digest
    • + *
    • 512 512 bits digest, valid only for algorithm "Streebog"
    • + *
    + *
  • + *
  • mode Algorithm mode + *
      + *
    • HASH simple digest mode (default)
    • + *
    • HMAC HMAC algorithm based on GOST R 34.11
    • + *
    • KDF Derive bits for KEK deversification
    • + *
    • PBKDF2 Password based key dirivation algorithms PBKDF2 (based on HMAC)
    • + *
    • PFXKDF Password based PFX key dirivation algorithms
    • + *
    • CPKDF CpyptoPro Password based key dirivation algorithms
    • + *
    + *
  • + *
  • sBox Paramset sBox for GOST 28147-89. Used only if version = 1994
  • + *
+ * + * Supported algorithms, modes and parameters: + * + *
    + *
  • Digest HASH mode (default)
  • + *
  • Sign/Verify HMAC modes parameters depends on version and length + *
      + *
    • version: 1994 HMAC parameters (B = 32, L = 32)
    • + *
    • version: 2012, length: 256 HMAC parameters (B = 64, L = 32)
    • + *
    • version: 2012, length: 512 HMAC parameters (B = 64, L = 64)
    • + *
    + *
  • + *
  • DeriveBits/DeriveKey KDF mode + *
      + *
    • context {@link CryptoOperationData} Context of the key derivation
    • + *
    • label {@link CryptoOperationData} Label that identifies the purpose for the derived keying material
    • + *
    + *
  • + *
  • DeriveBits/DeriveKey PBKDF2 mode + *
      + *
    • salt {@link CryptoOperationData} Random salt as input for HMAC algorithm
    • + *
    • iterations Iteration count. GOST recomended value 1000 (default) or 2000
    • + *
    • diversifier Deversifier, ID=1 - key material for performing encryption or decryption, ID=3 - integrity key for MACing
    • + *
    + *
  • + *
  • DeriveBits/DeriveKey PFXKDF mode + *
      + *
    • salt {@link CryptoOperationData} Random salt as input for HMAC algorithm
    • + *
    • iterations Iteration count. GOST recomended value 1000 (default) or 2000
    • + *
    • diversifier Deversifier, ID=1 - key material for performing encryption or decryption, + * ID=2 - IV (Initial Value) for encryption or decryption, ID=3 - integrity key for MACing
    • + *
    + *
  • + *
  • DeriveBits/DeriveKey CPKDF mode + *
      + *
    • salt {@link CryptoOperationData} Random salt as input for HMAC algorithm
    • + *
    • iterations Iteration count. GOST recomended value 1000 (default) or 2000
    • + *
    + *
  • + *
+ * + * @class GostDigest + * @param {AlgorithmIdentifier} algorithm WebCryptoAPI algorithm identifier + */ +function GostDigest(algorithm) // +{ + + algorithm = algorithm || {}; + + this.name = (algorithm.name || 'GOST R 34.10') + '-' + ((algorithm.version || 2012) % 100) + + ((algorithm.version || 2012) > 1 ? '-' + (algorithm.length || 256) : '') + + (((algorithm.mode || 'HASH') !== 'HASH') ? '-' + algorithm.mode : '') + + (algorithm.procreator ? '/' + algorithm.procreator : '') + + (typeof algorithm.sBox === 'string' ? '/' + algorithm.sBox : ''); + + // Algorithm procreator + this.procreator = algorithm.procreator; + + // Bit length + this.bitLength = algorithm.length || 256; + + switch (algorithm.version || 2012) { + case 1: // SHA-1 + this.digest = digestSHA1; + this.bitLength = 160; + break; + case 1994: + this.digest = digest94; + // Define chiper algorithm + this.sBox = (algorithm.sBox || (algorithm.procreator === 'SC' ? 'D-SC' : 'D-A')).toUpperCase(); + + //if (!GostCipher) + // GostCipher = root.GostCipher; + if (!GostCipher) + throw new NotSupportedError('Object GostCipher not found'); + + this.cipher = new GostCipher({ + name: 'GOST 28147', + block: 'ECB', + sBox: this.sBox, + procreator: this.procreator + }); + + break; + case 2012: + this.digest = digest2012; + break; + default: + throw new NotSupportedError('Algorithm version ' + algorithm.version + ' not supported'); + } + + // Key size + this.keySize = algorithm.keySize || (algorithm.version <= 2 ? this.bitLength / 8 : 32); + + switch (algorithm.mode || 'HASH') { + case 'HASH': + break; + case 'HMAC': + this.sign = signHMAC; + this.verify = verifyHMAC; + this.generateKey = generateKey; + break; + case 'KDF': + this.deriveKey = deriveKey; + this.deriveBits = deriveBitsKDF; + this.label = algorithm.label; + this.context = algorithm.context; + break; + case 'PBKDF2': + this.deriveKey = deriveKey; + this.deriveBits = deriveBitsPBKDF2; + this.generateKey = generateKey; + this.salt = algorithm.salt; + this.iterations = algorithm.iterations || 2000; + this.diversifier = algorithm.diversifier || 1; + break; + case 'PFXKDF': + this.deriveKey = deriveKey; + this.deriveBits = deriveBitsPFXKDF; + this.generateKey = generateKey; + this.salt = algorithm.salt; + this.iterations = algorithm.iterations || 2000; + this.diversifier = algorithm.diversifier || 1; + break; + case 'CPKDF': + this.deriveKey = deriveKey; + this.deriveBits = deriveBitsCP; + this.generateKey = generateKey; + this.salt = algorithm.salt; + this.iterations = algorithm.iterations || 2000; + break; + default: + throw new NotSupportedError('Algorithm mode ' + algorithm.mode + ' not supported'); + } +} // + +export default GostDigest; diff --git a/plugins/srktoolbox/src/core/vendor/gost/gostEngine.mjs b/plugins/srktoolbox/src/core/vendor/gost/gostEngine.mjs new file mode 100644 index 00000000..b54819c6 --- /dev/null +++ b/plugins/srktoolbox/src/core/vendor/gost/gostEngine.mjs @@ -0,0 +1,451 @@ +/** + * @file GOST 34.10-2012 signature function with 1024/512 bits digest + * @version 1.76 + * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved. + */ + +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +import GostRandom from './gostRandom.mjs'; +import GostCipher from './gostCipher.mjs'; +import GostDigest from './gostDigest.mjs'; +import GostSign from './gostSign.mjs'; + +/* + * Engine definition base on normalized algorithm identifier + * + */ // + +var root = {}; + +// Define engine +function defineEngine(method, algorithm) { + if (!algorithm) + throw new (root.SyntaxError || Error)('Algorithm not defined'); + + if (!algorithm.name) + throw new (root.SyntaxError || Error)('Algorithm name not defined'); + + var name = algorithm.name, mode = algorithm.mode; + if ((name === 'GOST 28147' || name === 'GOST R 34.12' || name === 'RC2') && (method === 'generateKey' || + (mode === 'MAC' && (method === 'sign' || method === 'verify')) || + ((mode === 'KW' || mode === 'MASK') && (method === 'wrapKey' || method === 'unwrapKey')) || + ((!mode || mode === 'ES') && (method === 'encrypt' || method === 'decrypt')))) { + return 'GostCipher'; + + } else if ((name === 'GOST R 34.11' || name === 'SHA') && (method === 'digest' || + (mode === 'HMAC' && (method === 'sign' || method === 'verify' || method === 'generateKey')) || + ((mode === 'KDF' || mode === 'PBKDF2' || mode === 'PFXKDF' || mode === 'CPKDF') && + (method === 'deriveKey' || method === 'deriveBits' || method === 'generateKey')))) { + return 'GostDigest'; + + } else if (name === 'GOST R 34.10' && (method === 'generateKey' || + ((!mode || mode === 'SIGN') && (method === 'sign' || method === 'verify')) || + (mode === 'MASK' && (method === 'wrapKey' || method === 'unwrapKey')) || + (mode === 'DH' && (method === 'deriveKey' || method === 'deriveBits')))) { + return 'GostSign'; + } else + throw new (root.NotSupportedError || Error)('Algorithm ' + name + '-' + mode + ' is not valid for ' + method); +} // + +/** + * Object implements dedicated Web Workers and provide a simple way to create + * and run GOST cryptographic algorithms in background thread. + * + * Object provide interface to GOST low-level cryptogric classes: + *
    + *
  • GostCipher - implementation of GOST 28147, GOST R 34.12, GOST R 34.13 Encryption algorithms. Reference {@link http://tools.ietf.org/html/rfc5830}
  • + *
  • GostDigest - implementation of GOST R 34.11 Hash Function algorithms. References {@link http://tools.ietf.org/html/rfc5831} and {@link http://tools.ietf.org/html/rfc6986}
  • + *
  • GostSign - implementation of GOST R 34.10 Digital Signature algorithms. References {@link http://tools.ietf.org/html/rfc5832} and {@link http://tools.ietf.org/html/rfc7091}
  • + *
+ * @namespace gostEngine + */ +var gostEngine = { + /** + * gostEngine.execute(algorithm, method, args) Entry point to execution + * all low-level GOST cryptographic methods + * + *
    + *
  • Determine the appropriate engine for a given execution method
  • + *
  • Create cipher object for determineted engine
  • + *
  • Execute method of cipher with given args
  • + *
+ * + * @memberOf gostEngine + * @param {AlgorithmIndentifier} algorithm Algorithm identifier + * @param {string} method Crypto method for execution + * @param {Array} args Method arguments (keys, data, additional parameters) + * @returns {(CryptoOperationData|Key|KeyPair|boolean)} Result of method execution + */ + execute: function (algorithm, method, args) // + { + // Define engine for GOST algorithms + var engine = defineEngine(method, algorithm); + // Create cipher + var cipher = this['get' + engine](algorithm); + // Execute method + return cipher[method].apply(cipher, args); + }, // + /** + * gostEngine.getGostCipher(algorithm) returns GOST 28147 / GOST R 34.12 cipher instance

+ * + * GOST 28147-89 / GOST R 34.12-15 Encryption Algorithm

+ * When keys and initialization vectors are converted to/from byte arrays, + * little-endian byte order is assumed.

+ * + * Normalized algorithm identifier common parameters: + * + *
    + *
  • name Algorithm name 'GOST 28147' or 'GOST R 34.12'
  • + *
  • version Algorithm version, number + *
      + *
    • 1989 Current version of standard
    • + *
    • 2015 New draft version of standard
    • + *
    + *
  • + *
  • length Block length + *
      + *
    • 64 64 bits length (default)
    • + *
    • 128 128 bits length (only for version 2015)
    • + *
    + *
  • + *
  • mode Algorithm mode, string + *
      + *
    • ES Encryption mode (default)
    • + *
    • MAC "imitovstavka" (MAC) mode
    • + *
    • KW Key wrapping mode
    • + *
    • MASK Key mask mode
    • + *
    + *
  • + *
  • sBox Paramset sBox for GOST 28147-89, string. Used only if version = 1989
  • + *
+ * + * Supported algorithms, modes and parameters: + * + *
    + *
  • Encript/Decrypt mode (ES) + *
      + *
    • block Block mode, string. Default ECB
    • + *
    • keyMeshing Key meshing mode, string. Default NO
    • + *
    • padding Padding mode, string. Default NO for CFB and CTR modes, or ZERO for others
    • + *
    • iv {@link CryptoOperationData} Initial vector with length of block. Default - zero block
    • + *
    + *
  • + *
  • Sign/Verify mode (MAC) + *
      + *
    • macLength Length of mac in bits (default - 32 bits)
    • + *
    • iv {@link CryptoOperationData} Initial vector with length of block. Default - zero block
    • + *
    + *
  • + *
  • Wrap/Unwrap key mode (KW) + *
      + *
    • keyWrapping Mode of keywrapping, string. Default NO - standard GOST key wrapping
    • + *
    • ukm {@link CryptoOperationData} User key material. Default - random generated value
    • + *
    + *
  • + *
  • Wrap/Unwrap key mode (MASK)
  • + *
+ * + * Supported paramters values: + * + *
    + *
  • Block modes (parameter 'block') + *
      + *
    • ECB "prostaya zamena" (ECB) mode (default)
    • + *
    • CFB "gammirovanie s obratnoj svyaziyu" (64-bit CFB) mode
    • + *
    • CTR "gammirovanie" (counter) mode
    • + *
    • CBC Cipher-Block-Chaining (CBC) mode
    • + *
    + *
  • + *
  • Key meshing modes (parameter 'keyMeshing') + *
      + *
    • NO No key wrapping (default)
    • + *
    • CP CryptoPor Key key meshing
    • + *
    + *
  • + *
  • Padding modes (parameter 'padding') + *
      + *
    • NO No padding only for CFB and CTR modes
    • + *
    • PKCS5 PKCS#5 padding mode
    • + *
    • ZERO Zero bits padding mode
    • + *
    • RANDOM Random bits padding mode
    • + *
    + *
  • + *
  • Wrapping key modes (parameter 'keyWrapping') + *
      + *
    • NO Ref. rfc4357 6.1 GOST 28147-89 Key wrapping
    • + *
    • CP CryptoPro Key wrapping mode
    • + *
    • SC SignalCom Key wrapping mode
    • + *
    + *
  • + *
+ * + * @memberOf gostEngine + * @param {AlgorithmIndentifier} algorithm Algorithm identifier + * @returns {GostCipher} Instance of GostCipher + */ + getGostCipher: function (algorithm) // + { + return new (GostCipher || (GostCipher = root.GostCipher))(algorithm); + }, // + /** + * gostEngine.getGostDigest(algorithm) returns GOST R 34.11 cipher instance

+ * + * Normalized algorithm identifier common parameters: + * + *
    + *
  • name Algorithm name 'GOST R 34.11'
  • + *
  • version Algorithm version + *
      + *
    • 1994 old-style 256 bits digest based on GOST 28147-89
    • + *
    • 2012 256 ro 512 bits digest algorithm "Streebog" GOST R 34.11-2012 (default)
    • + *
    + *
  • + *
  • length Digest length + *
      + *
    • 256 256 bits digest
    • + *
    • 512 512 bits digest, valid only for algorithm "Streebog"
    • + *
    + *
  • + *
  • mode Algorithm mode + *
      + *
    • HASH simple digest mode (default)
    • + *
    • HMAC HMAC algorithm based on GOST R 34.11
    • + *
    • KDF Derive bits for KEK deversification
    • + *
    • PBKDF2 Password based key dirivation algorithms PBKDF2 (based on HMAC)
    • + *
    • PFXKDF PFX key dirivation algorithms PFXKDF
    • + *
    • CPKDF CryptoPro Password based key dirivation algorithms
    • + *
    + *
  • + *
  • sBox Paramset sBox for GOST 28147-89. Used only if version = 1994
  • + *
+ * + * Supported algorithms, modes and parameters: + * + *
    + *
  • Digest HASH mode (default)
  • + *
  • Sign/Verify HMAC modes parameters depends on version and length + *
      + *
    • version: 1994 HMAC parameters (B = 32, L = 32)
    • + *
    • version: 2012, length: 256 HMAC parameters (B = 64, L = 32)
    • + *
    • version: 2012, length: 512 HMAC parameters (B = 64, L = 64)
    • + *
    + *
  • + *
  • DeriveBits/DeriveKey KDF mode + *
      + *
    • context {@link CryptoOperationData} Context of the key derivation
    • + *
    • label {@link CryptoOperationData} Label that identifies the purpose for the derived keying material
    • + *
    + *
  • + *
  • DeriveBits/DeriveKey PBKDF2 mode + *
      + *
    • salt {@link CryptoOperationData} Random salt as input for HMAC algorithm
    • + *
    • iterations Iteration count. GOST recomended value 1000 (default) or 2000
    • + *
    + *
  • + *
  • DeriveBits/DeriveKey PFXKDF mode + *
      + *
    • salt {@link CryptoOperationData} Random salt as input for HMAC algorithm
    • + *
    • iterations Iteration count. GOST recomended value 1000 (default) or 2000
    • + *
    • diversifier Deversifier, ID=1 - key material for performing encryption or decryption, + * ID=2 - IV (Initial Value) for encryption or decryption, ID=3 - integrity key for MACing
    • + *
    + *
  • + *
  • DeriveBits/DeriveKey CPKDF mode + *
      + *
    • salt {@link CryptoOperationData} Random salt as input for HMAC algorithm
    • + *
    • iterations Iteration count. GOST recomended value 1000 (default) or 2000
    • + *
    + *
  • + *
+ * + * @memberOf gostEngine + * @param {AlgorithmIndentifier} algorithm Algorithm identifier + * @returns {GostDigest} Instance of GostDigest + */ + getGostDigest: function (algorithm) // + { + return new (GostDigest || (GostDigest = root.GostDigest))(algorithm); + }, // + /** + * gostEngine.getGostSign(algorithm) returns GOST R 34.10 cipher instance

+ * + * Normalized algorithm identifier common parameters: + * + *
    + *
  • name Algorithm name 'GOST R 34.10'
  • + *
  • version Algorithm version + *
      + *
    • 1994 - Old-style GOST R 34.10-94 ExpMod algorithm with GOST R 34.11-94 hash
    • + *
    • 2001 - GOST R 34.10-2001 Eliptic curve algorithm with old GOST R 34.11-94 hash
    • + *
    • 2012 - GOST R 34.10-2012 Eliptic curve algorithm with GOST R 34.11-12 hash, default mode
    • + *
    + *
  • + *
  • length Length of hash and signature. Key length == hash length for EC algorithms and 2 * hash length for ExpMod algorithm + *
      + *
    • GOST R 34.10-256 - 256 bits digest, default mode
    • + *
    • GOST R 34.10-512 - 512 bits digest only for GOST R 34.11-2012 hash
    • + *
    + *
  • + *
  • mode Algorithm mode + *
      + *
    • SIGN Digital signature mode (default)
    • + *
    • DH Diffie-Hellman key generation and key agreement mode
    • + *
    • MASK Key mask mode
    • + *
    + *
  • + *
  • sBox Paramset sBox for GOST 34.11-94. Used only if version = 1994 or 2001
  • + *
+ * + * Supported algorithms, modes and parameters: + * + *
    + *
  • Sign/Verify mode (SIGN)
  • + *
  • Wrap/Unwrap mode (MASK)
  • + *
  • DeriveKey/DeriveBits mode (DH) + *
      + *
    • {@link CryptoOperationData} ukm User key material. Default - random generated value
    • + *
    • {@link CryptoOperationData} public The peer's EC public key data
    • + *
    + *
  • + *
  • GenerateKey mode (SIGN and DH and MASK) version = 1994 + *
      + *
    • namedParam Paramset for key generation algorithm. If specified no additianal parameters required
    • + *
    + * Additional parameters, if namedParam not specified + *
      + *
    • modulusLength Bit length of p (512 or 1024 bits). Default = 1024
    • + *
    • p {@link CryptoOperationData} Modulus, prime number, 2^(t-1) + *
    • q {@link CryptoOperationData} Order of cyclic group, prime number, 2^254 + *
    • a {@link CryptoOperationData} Generator, integer, 1 + *
    + *
  • + *
  • GenerateKey mode (SIGN and DH and MASK) version = 2001 or 2012 + *
      + *
    • namedCurve Paramset for key generation algorithm. If specified no additianal parameters required
    • + *
    + * Additional EC parameters, if namedCurve not specified + *
      + *
    • p {@link CryptoOperationData} Prime number - elliptic curve modulus
    • + *
    • a {@link CryptoOperationData} Coefficients a of the elliptic curve E
    • + *
    • b {@link CryptoOperationData} Coefficients b of the elliptic curve E
    • + *
    • q {@link CryptoOperationData} Prime number - order of cyclic group
    • + *
    • x {@link CryptoOperationData} Base point p x-coordinate
    • + *
    • y {@link CryptoOperationData} Base point p y-coordinate
    • + *
    + *
  • + *
+ * + * @memberOf gostEngine + * @param {AlgorithmIndentifier} algorithm Algorithm identifier + * @returns {GostSign} Instance of GostSign + */ + getGostSign: function (algorithm) // + { + return new (GostSign || (GostSign = root.GostSign))(algorithm); + } // +}; + +/* + * Worker method execution + * + */ // + +// Worker for gostCripto method execution +if (root.importScripts) { + + /** + * Method called when {@link SubtleCrypto} calls its own postMessage() + * method with data parameter: algorithm, method and arg.
+ * Call method execute and postMessage() results to onmessage event handler + * in the main process.
+ * If error occurred onerror event handler executed in main process. + * + * @memberOf gostEngine + * @name onmessage + * @param {MessageEvent} event Message event with data {algorithm, method, args} + */ + root.onmessage = function (event) { + try { + postMessage({ + id: event.data.id, + result: gostEngine.execute(event.data.algorithm, + event.data.method, event.data.args)}); + } catch (e) { + postMessage({ + id: event.data.id, + error: e.message + }); + } + }; +} else { + + // Load dependens + var baseUrl = '', nameSuffix = ''; + // Try to define from DOM model + if (typeof document !== 'undefined') { + (function () { + var regs = /^(.*)gostCrypto(.*)\.js$/i; + var list = document.querySelectorAll('script'); + for (var i = 0, n = list.length; i < n; i++) { + var value = list[i].getAttribute('src'); + var test = regs.exec(value); + if (test) { + baseUrl = test[1]; + nameSuffix = test[2]; + } + } + })(); + } + + // Local importScripts procedure for include dependens + var importScripts = function () { + for (var i = 0, n = arguments.length; i < n; i++) { + var name = arguments[i].split('.'), + src = baseUrl + name[0] + nameSuffix + '.' + name[1]; + var el = document.querySelector('script[src="' + src + '"]'); + if (!el) { + el = document.createElement('script'); + el.setAttribute('src', src); + document.head.appendChild(el); + } + } + }; + + // Import engines + if (!GostRandom) + importScripts('gostRandom.js'); + if (!GostCipher) + importScripts('gostCipher.js'); + if (!GostDigest) + importScripts('gostDigest.js'); + if (!GostSign) + importScripts('gostSign.js'); +} //
+ +export default gostEngine; + diff --git a/plugins/srktoolbox/src/core/vendor/gost/gostRandom.mjs b/plugins/srktoolbox/src/core/vendor/gost/gostRandom.mjs new file mode 100644 index 00000000..f9a38380 --- /dev/null +++ b/plugins/srktoolbox/src/core/vendor/gost/gostRandom.mjs @@ -0,0 +1,128 @@ +/** + * Implementation Web Crypto random generatore for GOST algorithms + * 1.76 + * 2014-2016, Rudolf Nickolaev. All rights reserved. + * + * Exported for CyberChef by mshwed [m@ttshwed.com] + */ + +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +import crypto from 'crypto'; + + +/** + * The gostCrypto provide general purpose cryptographic functionality for + * GOST standards including a cryptographically strong pseudo-random number + * generator seeded with truly random values. + * + * @Class GostRandom + * + */ // + +var root = {}; +var rootCrypto = crypto; + +var TypeMismatchError = Error; +var QuotaExceededError = Error; + +// Initialize mouse and time counters for random generator +var randomRing = { + seed: new Uint8Array(1024), + getIndex: 0, + setIndex: 0, + set: function (x) { + if (this.setIndex >= 1024) + this.setIndex = 0; + this.seed[this.setIndex++] = x; + }, + get: function () { + if (this.getIndex >= 1024) + this.getIndex = 0; + return this.seed[this.getIndex++]; + } +}; + +if (typeof document !== 'undefined') { + try { + // Mouse move event to fill random array + document.addEventListener('mousemove', function (e) { + randomRing.set((Date.now() & 255) ^ + ((e.clientX || e.pageX) & 255) ^ + ((e.clientY || e.pageY) & 255)); + }, false); + } catch (e) { + } + + try { + // Keypress event to fill random array + document.addEventListener('keydown', function (e) { + randomRing.set((Date.now() & 255) ^ + (e.keyCode & 255)); + }, false); + } catch (e) { + } +} // + +function GostRandom() { +} + +/** + * The getRandomValues method generates cryptographically random values.

+ * + * Random generator based on JavaScript Web Crypto random genereator + * (if it is possible) or Math.random mixed with time and parameters of + * mouse and keyboard events + * + * @memberOf GostRandom + * @param {(ArrayBuffer|ArrayBufferView)} array Destination buffer for random data + */ +GostRandom.prototype.getRandomValues = function (array) // +{ + + if (!array.byteLength) + throw new TypeMismatchError('Array is not of an integer type (Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, or Uint32Array)'); + + if (array.byteLength > 65536) + throw new QuotaExceededError('Byte length of array can\'t be greate then 65536'); + + var u8 = new Uint8Array(array.buffer, array.byteOffset, array.byteLength); + if (rootCrypto && rootCrypto.getRandomValues) { + // Native window cryptographic interface + rootCrypto.getRandomValues(u8); + } else { + // Standard Javascript method + for (var i = 0, n = u8.length; i < n; i++) + u8[i] = Math.floor(256 * Math.random()) & 255; + } + + // Mix bio randomizator + for (var i = 0, n = u8.length; i < n; i++) + u8[i] = u8[i] ^ randomRing.get(); + return array; +}; // + +export default GostRandom; diff --git a/plugins/srktoolbox/src/core/vendor/gost/gostSign.mjs b/plugins/srktoolbox/src/core/vendor/gost/gostSign.mjs new file mode 100644 index 00000000..36a87f63 --- /dev/null +++ b/plugins/srktoolbox/src/core/vendor/gost/gostSign.mjs @@ -0,0 +1,2023 @@ +/** + * @file GOST 34.10-2012 signature function with 1024/512 bits digest + * @version 1.76 + * @copyright 2014-2016, Rudolf Nickolaev. All rights reserved. + */ + +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Used library JSBN http://www-cs-students.stanford.edu/~tjw/jsbn/ + * Copyright (c) 2003-2005 Tom Wu (tjw@cs.Stanford.EDU) + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + + import GostRandom from './gostRandom.mjs'; + import GostDigest from './gostDigest.mjs'; + + import crypto from 'crypto'; + + /* + * Predefined curves and params collection + * + * http://tools.ietf.org/html/rfc5832 + * http://tools.ietf.org/html/rfc7091 + * http://tools.ietf.org/html/rfc4357 + * + */ // + +var root = {}; +var rootCrypto = crypto; +var CryptoOperationData = ArrayBuffer; + +var OperationError = Error, + DataError = Error, + NotSupportedError = Error; + +// Predefined named curve collection +var ECGostParams = { + 'S-256-TEST': { + a: 7, + b: '0x5FBFF498AA938CE739B8E022FBAFEF40563F6E6A3472FC2A514C0CE9DAE23B7E', + p: '0x8000000000000000000000000000000000000000000000000000000000000431', + q: '0x8000000000000000000000000000000150FE8A1892976154C59CFC193ACCF5B3', + x: 2, + y: '0x8E2A8A0E65147D4BD6316030E16D19C85C97F0A9CA267122B96ABBCEA7E8FC8' + }, + 'S-256-A': { + a: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94', + b: 166, + p: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97', + q: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C611070995AD10045841B09B761B893', + x: 1, + y: '0x8D91E471E0989CDA27DF505A453F2B7635294F2DDF23E3B122ACC99C9E9F1E14' + }, + 'S-256-B': { + a: '0x8000000000000000000000000000000000000000000000000000000000000C96', + b: '0x3E1AF419A269A5F866A7D3C25C3DF80AE979259373FF2B182F49D4CE7E1BBC8B', + p: '0x8000000000000000000000000000000000000000000000000000000000000C99', + q: '0x800000000000000000000000000000015F700CFFF1A624E5E497161BCC8A198F', + x: 1, + y: '0x3FA8124359F96680B83D1C3EB2C070E5C545C9858D03ECFB744BF8D717717EFC' + }, + 'S-256-C': { + a: '0x9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D7598', + b: 32858, + p: '0x9B9F605F5A858107AB1EC85E6B41C8AACF846E86789051D37998F7B9022D759B', + q: '0x9B9F605F5A858107AB1EC85E6B41C8AA582CA3511EDDFB74F02F3A6598980BB9', + x: 0, + y: '0x41ECE55743711A8C3CBF3783CD08C0EE4D4DC440D4641A8F366E550DFDB3BB67' + }, + 'P-256': { + p: '0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF', + a: '0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC', + b: '0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B', + x: '0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296', + y: '0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5', + q: '0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551' + }, + 'T-512-TEST': { + a: 7, + b: '0x1CFF0806A31116DA29D8CFA54E57EB748BC5F377E49400FDD788B649ECA1AC4361834013B2AD7322480A89CA58E0CF74BC9E540C2ADD6897FAD0A3084F302ADC', + p: '0x4531ACD1FE0023C7550D267B6B2FEE80922B14B2FFB90F04D4EB7C09B5D2D15DF1D852741AF4704A0458047E80E4546D35B8336FAC224DD81664BBF528BE6373', + q: '0x4531ACD1FE0023C7550D267B6B2FEE80922B14B2FFB90F04D4EB7C09B5D2D15DA82F2D7ECB1DBAC719905C5EECC423F1D86E25EDBE23C595D644AAF187E6E6DF', + x: '0x24D19CC64572EE30F396BF6EBBFD7A6C5213B3B3D7057CC825F91093A68CD762FD60611262CD838DC6B60AA7EEE804E28BC849977FAC33B4B530F1B120248A9A', + y: '0x2BB312A43BD2CE6E0D020613C857ACDDCFBF061E91E5F2C3F32447C259F39B2C83AB156D77F1496BF7EB3351E1EE4E43DC1A18B91B24640B6DBB92CB1ADD371E' + }, + 'T-512-A': { + p: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7', + a: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC4', + b: '0xE8C2505DEDFC86DDC1BD0B2B6667F1DA34B82574761CB0E879BD081CFD0B6265EE3CB090F30D27614CB4574010DA90DD862EF9D4EBEE4761503190785A71C760', + q: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275', + x: 3, + y: '0x7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4' + }, + 'T-512-B': { + p: '0x8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006F', + a: '0x8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006C', + b: '0x687D1B459DC841457E3E06CF6F5E2517B97C7D614AF138BCBF85DC806C4B289F3E965D2DB1416D217F8B276FAD1AB69C50F78BEE1FA3106EFB8CCBC7C5140116', + q: '0x800000000000000000000000000000000000000000000000000000000000000149A1EC142565A545ACFDB77BD9D40CFA8B996712101BEA0EC6346C54374F25BD', + x: 2, + y: '0x1A8F7EDA389B094C2C071E3647A8940F3C123B697578C213BE6DD9E6C8EC7335DCB228FD1EDF4A39152CBCAAF8C0398828041055F94CEEEC7E21340780FE41BD' + } +}; +ECGostParams['X-256-A'] = ECGostParams['S-256-A']; +ECGostParams['X-256-B'] = ECGostParams['S-256-C']; +ECGostParams['T-256-TEST'] = ECGostParams['S-256-TEST']; +ECGostParams['T-256-A'] = ECGostParams['S-256-A']; +ECGostParams['T-256-B'] = ECGostParams['S-256-B']; +ECGostParams['T-256-C'] = ECGostParams['S-256-C']; + + +var GostParams = { + 'S-TEST': { + modulusLength: 512, // bit length of p (512 or 1024 bits) + p: '0xEE8172AE8996608FB69359B89EB82A69854510E2977A4D63BC97322CE5DC3386EA0A12B343E9190F23177539845839786BB0C345D165976EF2195EC9B1C379E3', + q: '0x98915E7EC8265EDFCDA31E88F24809DDB064BDC7285DD50D7289F0AC6F49DD2D', + a: '0x9e96031500c8774a869582d4afde2127afad2538b4b6270a6f7c8837b50d50f206755984a49e509304d648be2ab5aab18ebe2cd46ac3d8495b142aa6ce23e21c' + }, + 'S-A': { + modulusLength: 1024, + p: '0xB4E25EFB018E3C8B87505E2A67553C5EDC56C2914B7E4F89D23F03F03377E70A2903489DD60E78418D3D851EDB5317C4871E40B04228C3B7902963C4B7D85D52B9AA88F2AFDBEB28DA8869D6DF846A1D98924E925561BD69300B9DDD05D247B5922D967CBB02671881C57D10E5EF72D3E6DAD4223DC82AA1F7D0294651A480DF', + q: '0x972432A437178B30BD96195B773789AB2FFF15594B176DD175B63256EE5AF2CF', + a: '0x8FD36731237654BBE41F5F1F8453E71CA414FFC22C25D915309E5D2E62A2A26C7111F3FC79568DAFA028042FE1A52A0489805C0DE9A1A469C844C7CABBEE625C3078888C1D85EEA883F1AD5BC4E6776E8E1A0750912DF64F79956499F1E182475B0B60E2632ADCD8CF94E9C54FD1F3B109D81F00BF2AB8CB862ADF7D40B9369A' + }, + 'S-B': { + modulusLength: 1024, + p: '0xC6971FC57524B30C9018C5E621DE15499736854F56A6F8AEE65A7A404632B1BCF0349FFCAFCB0A103177971FC1612ADCDB8C8CC938C70225C8FD12AFF01B1D064E0AD6FDE6AB9159166CB9F2FC171D92F0CC7B6A6B2CD7FA342ACBE2C9315A42D576B1ECCE77A963157F3D0BD96A8EB0B0F3502AD238101B05116334F1E5B7AB', + q: '0xB09D634C10899CD7D4C3A7657403E05810B07C61A688BAB2C37F475E308B0607', + a: '0x3D26B467D94A3FFC9D71BF8DB8934084137264F3C2E9EB16DCA214B8BC7C872485336744934FD2EF5943F9ED0B745B90AA3EC8D70CDC91682478B664A2E1F8FB56CEF2972FEE7EDB084AF746419B854FAD02CC3E3646FF2E1A18DD4BEB3C44F7F2745588029649674546CC9187C207FB8F2CECE8E2293F68395C4704AF04BAB5' + }, + 'S-C': { + modulusLength: 1024, + p: '0x9D88E6D7FE3313BD2E745C7CDD2AB9EE4AF3C8899E847DE74A33783EA68BC30588BA1F738C6AAF8AB350531F1854C3837CC3C860FFD7E2E106C3F63B3D8A4C034CE73942A6C3D585B599CF695ED7A3C4A93B2B947B7157BB1A1C043AB41EC8566C6145E938A611906DE0D32E562494569D7E999A0DDA5C879BDD91FE124DF1E9', + q: '0xFADD197ABD19A1B4653EECF7ECA4D6A22B1F7F893B641F901641FBB555354FAF', + a: '0x7447ED7156310599070B12609947A5C8C8A8625CF1CF252B407B331F93D639DDD1BA392656DECA992DD035354329A1E95A6E32D6F47882D960B8F10ACAFF796D13CD9611F853DAB6D2623483E46788708493937A1A29442598AEC2E0742022563440FE9C18740ECE6765AC05FAF024A64B026E7E408840819E962E7E5F401AE3' + }, + 'S-D': { + modulusLength: 1024, + p: '0x80F102D32B0FD167D069C27A307ADAD2C466091904DBAA55D5B8CC7026F2F7A1919B890CB652C40E054E1E9306735B43D7B279EDDF9102001CD9E1A831FE8A163EED89AB07CF2ABE8242AC9DEDDDBF98D62CDDD1EA4F5F15D3A42A6677BDD293B24260C0F27C0F1D15948614D567B66FA902BAA11A69AE3BCEADBB83E399C9B5', + q: '0xF0F544C418AAC234F683F033511B65C21651A6078BDA2D69BB9F732867502149', + a: '0x6BCC0B4FADB3889C1E06ADD23CC09B8AB6ECDEDF73F04632595EE4250005D6AF5F5ADE44CB1E26E6263C672347CFA26F9E9393681E6B759733784CDE5DBD9A14A39369DFD99FA85CC0D10241C4010343F34A91393A706CF12677CBFA1F578D6B6CFBE8A1242CFCC94B3B653A476E145E3862C18CC3FED8257CFEF74CDB205BF1' + }, + 'X-A': { + modulusLength: 1024, + p: '0xCA3B3F2EEE9FD46317D49595A9E7518E6C63D8F4EB4D22D10D28AF0B8839F079F8289E603B03530784B9BB5A1E76859E4850C670C7B71C0DF84CA3E0D6C177FE9F78A9D8433230A883CD82A2B2B5C7A3306980278570CDB79BF01074A69C9623348824B0C53791D53C6A78CAB69E1CFB28368611A397F50F541E16DB348DBE5F', + q: '0xCAE4D85F80C147704B0CA48E85FB00A9057AA4ACC44668E17F1996D7152690D9', + a: '0xBE27D652F2F1E339DA734211B85B06AE4DE236AA8FBEEB3F1ADCC52CD43853777E834A6A518138678A8ADBD3A55C70A7EAB1BA7A0719548677AAF4E609FFB47F6B9D7E45B0D06D83D7ADC53310ABD85783E7317F7EC73268B6A9C08D260B85D8485696CA39C17B17F044D1E050489036ABD381C5E6BF82BA352A1AFF136601AF' + }, + 'X-B': { + modulusLength: 1024, + p: '0x9286DBDA91ECCFC3060AA5598318E2A639F5BA90A4CA656157B2673FB191CD0589EE05F4CEF1BD13508408271458C30851CE7A4EF534742BFB11F4743C8F787B11193BA304C0E6BCA25701BF88AF1CB9B8FD4711D89F88E32B37D95316541BF1E5DBB4989B3DF13659B88C0F97A3C1087B9F2D5317D557DCD4AFC6D0A754E279', + q: '0xC966E9B3B8B7CDD82FF0F83AF87036C38F42238EC50A876CD390E43D67B6013F', + a: '0x7E9C3096676F51E3B2F9884CF0AC2156779496F410E049CED7E53D8B7B5B366B1A6008E5196605A55E89C3190DABF80B9F1163C979FCD18328DAE5E9048811B370107BB7715F82091BB9DE0E33EE2FED6255474F8769FCE5EAFAEEF1CB5A32E0D5C6C2F0FC0B3447072947F5B4C387666993A333FC06568E534AD56D2338D729' + }, + 'X-C': { + modulusLength: 1024, + p: '0xB194036ACE14139D36D64295AE6C50FC4B7D65D8B340711366CA93F383653908EE637BE428051D86612670AD7B402C09B820FA77D9DA29C8111A8496DA6C261A53ED252E4D8A69A20376E6ADDB3BDCD331749A491A184B8FDA6D84C31CF05F9119B5ED35246EA4562D85928BA1136A8D0E5A7E5C764BA8902029A1336C631A1D', + q: '0x96120477DF0F3896628E6F4A88D83C93204C210FF262BCCB7DAE450355125259', + a: '0x3F1817052BAA7598FE3E4F4FC5C5F616E122CFF9EBD89EF81DC7CE8BF56CC64B43586C80F1C4F56DD5718FDD76300BE336784259CA25AADE5A483F64C02A20CF4A10F9C189C433DEFE31D263E6C9764660A731ECCAECB74C8279303731E8CF69205BC73E5A70BDF93E5BB681DAB4EEB9C733CAAB2F673C475E0ECA921D29782E' + } +}; // + +/* + * BigInteger arithmetic tools + * optimized release of http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js + * + */ // + +// Bits per one element +var DB = 28, DM = (1 << DB) - 1, DV = 1 << DB, + FV = Math.pow(2, 52), F1 = 52 - DB, F2 = 2 * DB - 52; + +function am(y, i, x, w, j, c, n) { + var xl = x & 0x3fff, xh = x >> 14; + while (--n >= 0) { + var l = y[i] & 0x3fff; + var h = y[i++] >> 14; + var m = xh * l + h * xl; + l = xl * l + ((m & 0x3fff) << 14) + w[j] + c; + c = (l >> 28) + (m >> 14) + xh * h; + w[j++] = l & 0xfffffff; + } + return c; +} + +function nbi(words) { + var r = new Array(Math.ceil(words)); + r.s = 0; + r.t = 0; + return r; +} + +function copyTo(x, r) { + for (var i = x.t - 1; i >= 0; --i) + r[i] = x[i]; + r.t = x.t; + r.s = x.s; + return r; +} + +function copy(x) { + return copyTo(x, nbi(x.t)); +} + +function setInt(x, i) { + x.t = 1; + x.s = (i < 0) ? -1 : 0; + if (i > 0) + x[0] = i; + else if (i < -1) + x[0] = i + DV; + else + x.t = 0; + return x; +} + +function nbv(i) { + var r = nbi(1); + setInt(r, i); + return r; +} + +var ZERO = nbv(0), ONE = nbv(1), THREE = nbv(3); + +function clamp(x) { + var c = x.s & DM; + while (x.t > 0 && x[x.t - 1] === c) + --x.t; + return x; +} + +function subTo(x, a, r) { + var i = 0, c = 0, m = Math.min(a.t, x.t); + while (i < m) { + c += x[i] - a[i]; + r[i++] = c & DM; + c >>= DB; + } + if (a.t < x.t) { + c -= a.s; + while (i < x.t) { + c += x[i]; + r[i++] = c & DM; + c >>= DB; + } + c += x.s; + } + else { + c += x.s; + while (i < a.t) { + c -= a[i]; + r[i++] = c & DM; + c >>= DB; + } + c -= a.s; + } + r.s = (c < 0) ? -1 : 0; + if (c < -1) + r[i++] = DV + c; + else if (c > 0) + r[i++] = c; + r.t = i; + return clamp(r); +} + +function sub(x, y) { + return subTo(x, y, nbi(x.t)); +} + +function addTo(x, a, r) { + var i = 0, c = 0, m = Math.min(a.t, x.t); + while (i < m) { + c += x[i] + a[i]; + r[i++] = c & DM; + c >>= DB; + } + if (a.t < x.t) { + c += a.s; + while (i < x.t) { + c += x[i]; + r[i++] = c & DM; + c >>= DB; + } + c += x.s; + } + else { + c += x.s; + while (i < a.t) { + c += a[i]; + r[i++] = c & DM; + c = c >> DB; + } + c += a.s; + } + r.s = (c < 0) ? -1 : 0; + if (c > 0) + r[i++] = c; + else if (c < -1) + r[i++] = DV + c; + r.t = i; + return clamp(r); +} + +function add(x, y) { + return addTo(x, y, nbi(x.t)); +} + +function negTo(x, r) { + return subTo(ZERO, x, r); +} + +function neg(x) { + return negTo(x, nbi(x.t)); +} + +function absTo(x, r) { + return (x.s < 0) ? negTo(r) : copyTo(r); +} + +function abs(x) { + return (x.s < 0) ? neg(x) : x; +} + +function compare(x, a) { + var r = x.s - a.s; + if (r !== 0) + return r; + var i = x.t; + r = i - a.t; + if (r !== 0) + return (x.s < 0) ? -r : r; + while (--i >= 0) + if ((r = x[i] - a[i]) !== 0) + return r; + return 0; +} + +function equals(x, y) { + return(compare(x, y) === 0); +} + +function min(x, y) { + return(compare(x, y) < 0) ? x : y; +} + +function max(x, y) { + return(compare(x, y) > 0) ? x : y; +} + +function nbits(x) { + var r = 1, t; + if ((t = x >>> 16) !== 0) { + x = t; + r += 16; + } + if ((t = x >> 8) !== 0) { + x = t; + r += 8; + } + if ((t = x >> 4) !== 0) { + x = t; + r += 4; + } + if ((t = x >> 2) !== 0) { + x = t; + r += 2; + } + if ((t = x >> 1) !== 0) { + x = t; + r += 1; + } + return r; +} + +function dshlTo(x, n, r) { + var i; + for (i = x.t - 1; i >= 0; --i) + r[i + n] = x[i]; + for (i = n - 1; i >= 0; --i) + r[i] = 0; + r.t = x.t + n; + r.s = x.s; + return r; +} +function dshrTo(x, n, r) { + for (var i = n; i < x.t; ++i) + r[i - n] = x[i]; + r.t = Math.max(x.t - n, 0); + r.s = x.s; + return r; +} + +function shlTo(x, n, r) { + var bs = n % DB; + var cbs = DB - bs; + var bm = (1 << cbs) - 1; + var ds = Math.floor(n / DB), c = (x.s << bs) & DM, i; + for (i = x.t - 1; i >= 0; --i) { + r[i + ds + 1] = (x[i] >> cbs) | c; + c = (x[i] & bm) << bs; + } + for (i = ds - 1; i >= 0; --i) + r[i] = 0; + r[ds] = c; + r.t = x.t + ds + 1; + r.s = x.s; + return clamp(r); +} + +function shrTo(x, n, r) { + r.s = x.s; + var ds = Math.floor(n / DB); + if (ds >= x.t) { + r.t = 0; + return; + } + var bs = n % DB; + var cbs = DB - bs; + var bm = (1 << bs) - 1; + r[0] = x[ds] >> bs; + for (var i = ds + 1; i < x.t; ++i) { + r[i - ds - 1] |= (x[i] & bm) << cbs; + r[i - ds] = x[i] >> bs; + } + if (bs > 0) + r[x.t - ds - 1] |= (x.s & bm) << cbs; + r.t = x.t - ds; + return clamp(r); +} + +function shl(x, n) { + var r = nbi(x.t); + if (n < 0) + shrTo(x, -n, r); + else + shlTo(x, n, r); + return r; +} + +function shr(x, n) { + var r = nbi(x.t); + if (n < 0) + shlTo(x, -n, r); + else + shrTo(x, n, r); + return r; +} + +function bitLength(x) { + if (x.t <= 0) + return 0; + return DB * (x.t - 1) + nbits(x[x.t - 1] ^ (x.s & DM)); +} + +function mulTo(b, a, r) { + var x = abs(b), y = abs(a); + var i = x.t; + r.t = i + y.t; + while (--i >= 0) + r[i] = 0; + for (i = 0; i < y.t; ++i) + r[i + x.t] = am(x, 0, y[i], r, i, 0, x.t); + r.s = 0; + if (b.s !== a.s) + subTo(ZERO, r, r); + return clamp(r); +} + +function mul(x, y) { + return mulTo(x, y, nbi(x.t + y.t)); +} + +function sqrTo(a, r) { + var x = abs(a); + var i = r.t = 2 * x.t; + while (--i >= 0) + r[i] = 0; + for (i = 0; i < x.t - 1; ++i) { + var c = am(x, i, x[i], r, 2 * i, 0, 1); + if ((r[i + x.t] += am(x, i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) { + r[i + x.t] -= x.DV; + r[i + x.t + 1] = 1; + } + } + if (r.t > 0) + r[r.t - 1] += am(x, i, x[i], r, 2 * i, 0, 1); + r.s = 0; + return clamp(r); +} + +function sqr(a) { + return sqrTo(a, nbi(a.t * 2)); +} + +function divRemTo(n, m, q, r) { + var pm = abs(m); + if (pm.t <= 0) + throw new OperationError('Division by zero'); + var pt = abs(n); + if (pt.t < pm.t) { + if (q) + setInt(q, 0); + if (r) + copyTo(n, r); + return q; + } + if (!r) + r = nbi(m.t); + var y = nbi(m.t), ts = n.s, ms = m.s; + var nsh = DB - nbits(pm[pm.t - 1]); + if (nsh > 0) { + shlTo(pm, nsh, y); + shlTo(pt, nsh, r); + } + else { + copyTo(pm, y); + copyTo(pt, r); + } + var ys = y.t; + var y0 = y[ys - 1]; + if (y0 === 0) + return q; + var yt = y0 * (1 << F1) + ((ys > 1) ? y[ys - 2] >> F2 : 0); + var d1 = FV / yt, d2 = (1 << F1) / yt, e = 1 << F2; + var i = r.t, j = i - ys, t = !q ? nbi(Math.max(n.t - m.t, 1)) : q; + dshlTo(y, j, t); + if (compare(r, t) >= 0) { + r[r.t++] = 1; + subTo(r, t, r); + } + dshlTo(ONE, ys, t); + subTo(t, y, y); + while (y.t < ys) + y[y.t++] = 0; + while (--j >= 0) { + var qd = (r[--i] === y0) ? DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2); + if ((r[i] += am(y, 0, qd, r, j, 0, ys)) < qd) { + dshlTo(y, j, t); + subTo(r, t, r); + while (r[i] < --qd) + subTo(r, t, r); + } + } + if (q) { + dshrTo(r, ys, q); + if (ts !== ms) + subTo(ZERO, q, q); + } + r.t = ys; + clamp(r); + if (nsh > 0) + shrTo(r, nsh, r); + if (ts < 0) + subTo(ZERO, r, r); + return q; +} + +function modTo(b, a, r) { + divRemTo(abs(b), a, null, r); + if (b.s < 0 && compare(r, ZERO) > 0) + subTo(a, r, r); + return r; +} + +function mod(b, a) { + return modTo(b, a, nbi(a.t)); +} + +function div(b, a) { + return divRemTo(b, a, nbi(Math.max(b.t - a.t, 1)), null); +} + +function isEven(x) { + + return ((x.t > 0) ? (x[0] & 1) : x.s) === 0; +} + +function isZero(x) { + return equals(x, ZERO); +} + +function sig(x) { + if (x.s < 0) + return -1; + else if (x.t <= 0 || (x.t === 1 && x[0] <= 0)) + return 0; + else + return 1; +} + +function invMod(x, m) { + var ac = isEven(m); + if ((isEven(x) && ac) || sig(m) === 0) + return ZERO; + var u = copy(m), v = copy(x); + var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1); + while (sig(u) !== 0) { + while (isEven(u)) { + shrTo(u, 1, u); + if (ac) { + if (!isEven(a) || !isEven(b)) { + addTo(a, x, a); + subTo(b, m, b); + } + shrTo(a, 1, a); + } + else if (!isEven(b)) + subTo(b, m, b); + shrTo(b, 1, b); + } + while (isEven(v)) { + shrTo(v, 1, v); + if (ac) { + if (!isEven(c) || !isEven(d)) { + addTo(c, x, c); + subTo(d, m, d); + } + shrTo(c, 1, c); + } + else if (!isEven(d)) + subTo(d, m, d); + shrTo(d, 1, d); + } + if (compare(u, v) >= 0) { + subTo(u, v, u); + if (ac) + subTo(a, c, a); + subTo(b, d, b); + } + else { + subTo(v, u, v); + if (ac) + subTo(c, a, c); + subTo(d, b, d); + } + } + if (compare(v, ONE) !== 0) + return ZERO; + if (compare(d, m) >= 0) + return subtract(d, m); + if (sig(d) < 0) + addTo(d, m, d); + else + return d; + if (sig(d) < 0) + return add(d, m); + else + return d; +} + +function testBit(x, n) { + var j = Math.floor(n / DB); + if (j >= x.t) + return (x.s !== 0); + return ((x[j] & (1 << (n % DB))) !== 0); +} + +function nothing(x) { + return x; +} + +function extend(c, o) { + for (var i in o) + c.prototype[i] = o[i]; +} // + +/* + * Classic, Barret, Mongomery reductions, optimized ExpMod algorithms + * optimized release of http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn2.js + * + */ // + +// Classic reduction +var Classic = function (m) { + this.m = m; +}; + +extend(Classic, { + convert: function (x) { + if (x.s < 0 || compare(x, this.m) >= 0) + return mod(x, this.m); + else + return x; + }, + revert: nothing, + reduce: function (x) { + modTo(x, this.m, x); + }, + sqrTo: function (x, r) { + sqrTo(x, r); + this.reduce(r); + }, + mulTo: function (x, y, r) { + mulTo(x, y, r); + this.reduce(r); + } +}); + +function invDig(a) { + if (a.t < 1) + return 0; + var x = a[0]; + if ((x & 1) === 0) + return 0; + var y = x & 3; + y = (y * (2 - (x & 0xf) * y)) & 0xf; + y = (y * (2 - (x & 0xff) * y)) & 0xff; + y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; + y = (y * (2 - x * y % DV)) % DV; + return (y > 0) ? DV - y : -y; +} + +// Montgomery reduction +var Montgomery = function (m) { + this.m = m; + this.mp = invDig(m); + this.mpl = this.mp & 0x7fff; + this.mph = this.mp >> 15; + this.um = (1 << (DB - 15)) - 1; + this.mt2 = 2 * m.t; +}; + +extend(Montgomery, { + // xR mod m + convert: function (x) { + var r = nbi(x.t); + dshlTo(abs(x), this.m.t, r); + divRemTo(r, this.m, null, r); + if (x.s < 0 && compare(r, ZERO) > 0) + subTo(this.m, r, r); + return r; + }, + // x/R mod m + revert: function (x) { + var r = nbi(x.t); + copyTo(x, r); + this.reduce(r); + return r; + }, + // x = x/R mod m (HAC 14.32) + reduce: function (x) { + while (x.t <= this.mt2) + x[x.t++] = 0; + for (var i = 0; i < this.m.t; ++i) { + var j = x[i] & 0x7fff; + var u0 = (j * this.mpl + (((j * this.mph + (x[i] >> 15) * this.mpl) & this.um) << 15)) & DM; + j = i + this.m.t; + x[j] += am(this.m, 0, u0, x, i, 0, this.m.t); + while (x[j] >= DV) { + x[j] -= DV; + x[++j]++; + } + } + clamp(x); + dshrTo(x, this.m.t, x); + if (compare(x, this.m) >= 0) + subTo(x, this.m, x); + }, + // r = "x^2/R mod m"; x != r + sqrTo: function (x, r) { + sqrTo(x, r); + this.reduce(r); + }, + // r = "xy/R mod m"; x,y != r + mulTo: function (x, y, r) { + mulTo(x, y, r); + this.reduce(r); + } +}); + +function dAddOffset(x, n, w) { + if (n === 0) + return; + while (x.t <= w) + x[x.t++] = 0; + x[w] += n; + while (x[w] >= DV) { + x[w] -= DV; + if (++w >= x.t) + x[x.t++] = 0; + ++x[w]; + } +} + +function mulLowerTo(x, a, n, r) { + var i = Math.min(x.t + a.t, n); + r.s = 0; // assumes a,x >= 0 + r.t = i; + while (i > 0) + r[--i] = 0; + var j; + for (j = r.t - x.t; i < j; ++i) + r[i + x.t] = am(x, 0, a[i], r, i, 0, x.t); + for (j = Math.min(a.t, n); i < j; ++i) + am(x, 0, a[i], r, i, 0, n - i); + return clamp(r); +} + +function mulUpperTo(x, a, n, r) { + --n; + var i = r.t = x.t + a.t - n; + r.s = 0; // assumes a,x >= 0 + while (--i >= 0) + r[i] = 0; + for (i = Math.max(n - x.t, 0); i < a.t; ++i) + r[x.t + i - n] = am(x, n - i, a[i], r, 0, 0, x.t + i - n); + clamp(r); + return dshrTo(r, 1, r); +} + +// Barrett modular reduction +function Barrett(m) { + // setup Barrett + this.r2 = nbi(2 * m.t); + this.q3 = nbi(2 * m.t); + dshlTo(ONE, 2 * m.t, this.r2); + this.mu = div(this.r2, m); + this.m = m; +} + +extend(Barrett, { + convert: function (x) { + if (x.s < 0 || x.t > 2 * this.m.t) + return mod(x, this.m); + else if (compare(x, this.m) < 0) + return x; + else { + var r = nbi(x.t); + copyTo(x, r); + this.reduce(r); + return r; + } + }, + revert: function (x) { + return x; + }, + // x = x mod m (HAC 14.42) + reduce: function (x) { + dshrTo(x, this.m.t - 1, this.r2); + if (x.t > this.m.t + 1) { + x.t = this.m.t + 1; + clamp(x); + } + mulUpperTo(this.mu, this.r2, this.m.t + 1, this.q3); + mulLowerTo(this.m, this.q3, this.m.t + 1, this.r2); + while (compare(x, this.r2) < 0) + dAddOffset(x, 1, this.m.t + 1); + subTo(x, this.r2, x); + while (compare(x, this.m) >= 0) + subTo(x, this.m, x); + }, + // r = x^2 mod m; x != r + sqrTo: function (x, r) { + sqrTo(x, r); + this.reduce(r); + }, + // r = x*y mod m; x,y != r + mulTo: function (x, y, r) { + mulTo(x, y, r); + this.reduce(r); + } + +}); + +// x^e % m (HAC 14.85) +function expMod(x, e, m) { + var i = bitLength(e), k, r = nbv(1), z; + if (i <= 0) + return r; + else if (i < 18) + k = 1; + else if (i < 48) + k = 3; + else if (i < 144) + k = 4; + else if (i < 768) + k = 5; + else + k = 6; + if (i < 8) + z = new Classic(m); + else if (isEven(m)) + z = new Barrett(m); + else + z = new Montgomery(m); + + // precomputation + var g = new Array(), n = 3, k1 = k - 1, km = (1 << k) - 1; + g[1] = z.convert(x); + if (k > 1) { + var g2 = nbi(m.t * 2); + z.sqrTo(g[1], g2); + while (n <= km) { + g[n] = nbi(m.t * 2); + z.mulTo(g2, g[n - 2], g[n]); + n += 2; + } + } + + var j = e.t - 1, w, is1 = true, r2 = nbi(m.t * 2), t; + i = nbits(e[j]) - 1; + while (j >= 0) { + if (i >= k1) + w = (e[j] >> (i - k1)) & km; + else { + w = (e[j] & ((1 << (i + 1)) - 1)) << (k1 - i); + if (j > 0) + w |= e[j - 1] >> (DB + i - k1); + } + + n = k; + while ((w & 1) == 0) { + w >>= 1; + --n; + } + if ((i -= n) < 0) { + i += DB; + --j; + } + if (is1) { // ret == 1, don't bother squaring or multiplying it + copyTo(g[w], r); + is1 = false; + } + else { + while (n > 1) { + z.sqrTo(r, r2); + z.sqrTo(r2, r); + n -= 2; + } + if (n > 0) + z.sqrTo(r, r2); + else { + t = r; + r = r2; + r2 = t; + } + z.mulTo(r2, g[w], r); + } + while (j >= 0 && (e[j] & (1 << i)) == 0) { + z.sqrTo(r, r2); + t = r; + r = r2; + r2 = t; + if (--i < 0) { + i = DB - 1; + --j; + } + } + } + return z.revert(r); +} // + +/* + * EC Field Elements, Points, Curves + * optimized release of http://www-cs-students.stanford.edu/~tjw/jsbn/ec.js + * + */ // + +// EC Field Elemets +function newFE(a, x) { + a.r.reduce(x); + x.q = a.q; + x.r = a.r; + return x; +} + +function copyFE(a, x) { + x.q = a.q; + x.r = a.r; + return x; +} + +function negFE(a) { + return copyFE(a, sub(a.q, a)); +} + +function addFE(a, b) { + var r = add(a, b); + if (compare(r, a.q) > 0) + subTo(r, a.q, r); + return copyFE(a, r); +} + +function subFE(a, b) { + var r = sub(a, b); + if (r.s < 0) + addTo(a.q, r, r); + return copyFE(a, r); +} + +function mulFE(a, b) { + return newFE(a, mul(a, b)); +} + +function sqrFE(a) { + return newFE(a, sqr(a)); +} + +function shlFE(a, i) { + return newFE(a, shl(a, i)); +} + +function invFE(a) { + return copyFE(a, invMod(a, a.q)); +} + +// EC Points +function newEC(curve, x, y, z) { + return { + curve: curve, + x: x, + y: y, + z: z || newFE(curve, ONE) + }; +} + +function getX(point) { + if (!point.zinv) + point.zinv = invFE(point.z); + return mulFE(point.x, point.zinv); +} + +function getY(point) { + if (!point.zinv) + point.zinv = invFE(point.z); + return mulFE(point.y, point.zinv); +} + +function isInfinity(a) { + if ((!a.x) && (!a.y)) + return true; + return isZero(a.z) && !isZero(a.y); +} + +function getInfinity(a) { + return a.curve.infinity; +} + +function equalsEC(a, b) { + if (a === b) + return true; + if (isInfinity(a)) + return isInfinity(b); + if (isInfinity(b)) + return isInfinity(a); + var u, v; + // u = Y2 * Z1 - Y1 * Z2 + u = subFE(mulFE(b.y, a.z), mulFE(a.y, b.z)); + if (!isZero(u)) + return false; + // v = X2 * Z1 - X1 * Z2 + v = subFE(mulFE(b.x, a.z), mulFE(a.x, b.z)); + return isZero(v); +} + +function negEC(a) { + return newEC(a.curve, a.x, negFE(a.y), a.z); +} + +function addEC(a, b) { + if (isInfinity(a)) + return b; + if (isInfinity(b)) + return a; + + // u = Y2 * Z1 - Y1 * Z2 + var u = subFE(mulFE(b.y, a.z), mulFE(a.y, b.z)); + // v = X2 * Z1 - X1 * Z2 + var v = subFE(mulFE(b.x, a.z), mulFE(a.x, b.z)); + + if (isZero(v)) { + if (isZero(u)) { + return twiceEC(a); // a == b, so double + } + return getInfinity(a); // a = -b, so infinity + } + + var x1 = a.x; + var y1 = a.y; + + var v2 = sqrFE(v); + var v3 = mulFE(v2, v); + var x1v2 = mulFE(x1, v2); + var zu2 = mulFE(sqrFE(u), a.z); + + // x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3) + var x3 = mulFE(subFE(mulFE(subFE(zu2, shlFE(x1v2, 1)), b.z), v3), v); + // y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3 + var y3 = addFE(mulFE(subFE(subFE(mulFE(mulFE(x1v2, THREE), u), mulFE(y1, v3)), mulFE(zu2, u)), b.z), mulFE(u, v3)); + // z3 = v^3 * z1 * z2 + var z3 = mulFE(mulFE(v3, a.z), b.z); + + return newEC(a.curve, x3, y3, z3); +} + +function twiceEC(b) { + if (isInfinity(b)) + return b; + if (sig(b.y) === 0) + return getInfinity(b); + + var x1 = b.x; + var y1 = b.y; + + var y1z1 = mulFE(y1, b.z); + var y1sqz1 = mulFE(y1z1, y1); + var a = b.curve.a; + + // w = 3 * x1^2 + a * z1^2 + var w = mulFE(sqrFE(x1), THREE); + if (!isZero(a)) { + w = addFE(w, mulFE(sqrFE(b.z), a)); + } + + // x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1) + var x3 = mulFE(shlFE(subFE(sqrFE(w), mulFE(shlFE(x1, 3), y1sqz1)), 1), y1z1); + // y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3 + var y3 = subFE(mulFE(shlFE(subFE(mulFE(mulFE(w, THREE), x1), shlFE(y1sqz1, 1)), 2), y1sqz1), mulFE(sqrFE(w), w)); + // z3 = 8 * (y1 * z1)^3 + var z3 = shlFE(mulFE(sqrFE(y1z1), y1z1), 3); + + return newEC(b.curve, x3, y3, z3); +} + +// Simple NAF (Non-Adjacent Form) multiplication algorithm +function mulEC(a, k) { + if (isInfinity(a)) + return a; + if (sig(k) === 0) + return getInfinity(a); + + var e = k; + var h = mul(e, THREE); + + var neg = negEC(a); + var R = a; + + var i; + for (i = bitLength(h) - 2; i > 0; --i) { + R = twiceEC(R); + + var hBit = testBit(h, i); + var eBit = testBit(e, i); + + if (hBit !== eBit) { + R = addEC(R, hBit ? a : neg); + } + } + + return R; +} + +function mul2AndAddEC(a, k) { + var nbits = bitLength(k); + var R = a, + Q = getInfinity(a); + + for (var i = 0; i < nbits - 1; i++) { + if (testBit(k, i) === 1) + Q = addEC(Q, R); + + R = twiceEC(R); + } + + if (testBit(k, nbits - 1) === 1) + Q = addEC(Q, R); + + return Q; +} + +// Compute a*j + x*k (simultaneous multiplication) +function mulTwoEC(a, j, x, k) { + var i; + if (bitLength(j) > bitLength(k)) + i = bitLength(j) - 1; + else + i = bitLength(k) - 1; + + var R = getInfinity(a); + var both = addEC(a, x); + while (i >= 0) { + R = twiceEC(R); + if (testBit(j, i)) { + if (testBit(k, i)) { + R = addEC(R, both); + } + else { + R = addEC(R, a); + } + } + else { + if (testBit(k, i)) { + R = addEC(R, x); + } + } + --i; + } + + return R; +} + +// EC Curve +function newCurve(q, a, b) { + var curve = {}; + curve.q = q; + curve.r = new Barrett(q); + curve.a = newFE(curve, a); + curve.b = newFE(curve, b); + curve.infinity = newEC(curve); + return curve; +} // + +/* + * Converion tools (hex, binary) + * + */ // + +function atobi(d) { + var k = 8; + var a = new Uint8Array(d); + var r = nbi(a.length * 8 / DB); + r.t = 0; + r.s = 0; + var sh = 0; + for (var i = 0, n = a.length; i < n; i++) { + var x = a[i]; + if (sh === 0) + r[r.t++] = x; + else if (sh + k > DB) { + r[r.t - 1] |= (x & ((1 << (DB - sh)) - 1)) << sh; + r[r.t++] = (x >> (DB - sh)); + } + else + r[r.t - 1] |= x << sh; + sh += k; + if (sh >= DB) + sh -= DB; + } + return clamp(r); +} + +function bitoa(s, bitLength) { + var k = 8; + var km = (1 << k) - 1, d, m = false, r = [], i = s.t; + var p = DB - (i * DB) % k; + if (i-- > 0) { + if (p < DB && (d = s[i] >> p) > 0) { + m = true; + r.push(d); + } + while (i >= 0) { + if (p < k) { + d = (s[i] & ((1 << p) - 1)) << (k - p); + d |= s[--i] >> (p += DB - k); + } + else { + d = (s[i] >> (p -= k)) & km; + if (p <= 0) { + p += DB; + --i; + } + } + if (d > 0) + m = true; + if (m) + r.push(d); + } + } + var r8 = new Uint8Array(bitLength ? bitLength / 8 : r.length); + if (m) + r8.set(r.reverse()); + return r8.buffer; +} + + +function htobi(s) { + if (typeof s === 'number' || s instanceof Number) + return nbv(s); + s = s.replace(/[^\-A-Fa-f0-9]/g, ''); + if (!s) + s = '0'; + var k = 4; + var r = nbi(s.length / 7); + var i = s.length, mi = false, sh = 0; + while (--i >= 0) { + var c = s.charAt(i); + if (c === '-') { + mi = true; + continue; + } + var x = parseInt(s.charAt(i), 16); + mi = false; + if (sh === 0) + r[r.t++] = x; + else if (sh + k > DB) { + r[r.t - 1] |= (x & ((1 << (DB - sh)) - 1)) << sh; + r[r.t++] = (x >> (DB - sh)); + } + else + r[r.t - 1] |= x << sh; + sh += k; + if (sh >= DB) + sh -= DB; + } + if (mi) + subTo(ZERO, r, r); + return clamp(r); +} + +function bitoh(x) { + if (x.s < 0) + return "-" + bitoh(negTo(x, nbi(x.t))); + var k = 4; + var km = (1 << k) - 1, d, m = false, r = "", i = x.t; + var p = DB - (i * DB) % k; + if (i-- > 0) { + if (p < DB && (d = x[i] >> p) > 0) { + m = true; + r = d.toString(16); + } + while (i >= 0) { + if (p < k) { + d = (x[i] & ((1 << p) - 1)) << (k - p); + d |= x[--i] >> (p += DB - k); + } + else { + d = (x[i] >> (p -= k)) & km; + if (p <= 0) { + p += DB; + --i; + } + } + if (d > 0) + m = true; + if (m) + r += d.toString(16); + } + } + return "0x" + (m ? r : "0"); +} + +// biginteger to big-endian integer bytearray +function bitoi(s) { + var i = s.t, r = []; + r[0] = s.s; + var p = DB - (i * DB) % 8, d, k = 0; + if (i-- > 0) { + if (p < DB && (d = s[i] >> p) !== (s.s & DM) >> p) + r[k++] = d | (s.s << (DB - p)); + while (i >= 0) { + if (p < 8) { + d = (s[i] & ((1 << p) - 1)) << (8 - p); + d |= s[--i] >> (p += DB - 8); + } + else { + d = (s[i] >> (p -= 8)) & 0xff; + if (p <= 0) { + p += DB; + --i; + } + } + if ((d & 0x80) !== 0) + d |= -256; + if (k === 0 && (s.s & 0x80) !== (d & 0x80)) + ++k; + if (k > 0 || d !== s.s) + r[k++] = d; + } + } + return new Uint8Array(r).buffer; +} + +// big-endian integer bytearray to biginteger +function itobi(d) { + var k = 8, s = new Uint8Array(d), + r = nbi(s.length / 7); + r.t = 0; + r.s = 0; + var i = s.length, sh = 0; + while (--i >= 0) { + var x = s[i] & 0xff; + if (sh === 0) + r[r.t++] = x; + else if (sh + k > DB) { + r[r.t - 1] |= (x & ((1 << (DB - sh)) - 1)) << sh; + r[r.t++] = (x >> (DB - sh)); + } + else + r[r.t - 1] |= x << sh; + sh += k; + if (sh >= DB) + sh -= DB; + } + if ((s[0] & 0x80) !== 0) { + r.s = -1; + if (sh > 0) + r[r.t - 1] |= ((1 << (DB - sh)) - 1) << sh; + } + return clamp(r); +} + + +// Swap bytes in buffer +function swap(s) { + var src = new Uint8Array(s), + dst = new Uint8Array(src.length); + for (var i = 0, n = src.length; i < n; i++) + dst[n - i - 1] = src[i]; + return dst.buffer; +} + +// Calculate hash of data +function hash(d) { + if (this.hash) + d = this.hash.digest(d); + // Swap hash for SignalCom + if (this.procreator === 'SC' || + (this.procreator === 'VN' && this.hash.version === 2012)) + d = swap(d); + return d; +} + +// Check buffer +function buffer(d) { + if (d instanceof CryptoOperationData) + return d; + else if (d && d?.buffer instanceof CryptoOperationData) + return d.byteOffset === 0 && d.byteLength === d.buffer.byteLength ? + d.buffer : new Uint8Array(new Uint8Array(d, d.byteOffset, d.byteLength)).buffer; + else + throw new DataError('CryptoOperationData or CryptoOperationDataView required'); +} + +// Check double buffer +function to2(d) { + var b = buffer(d); + if (b.byteLength % 2 > 0) + throw new DataError('Buffer length must be even'); + var n = b.byteLength / 2; + return [atobi(new Uint8Array(b, 0, n)), atobi(new Uint8Array(b, n, n))]; +} + +function from2(x, y, bitLength) { + var a = bitoa(x, bitLength), + b = bitoa(y, bitLength), + d = new Uint8Array(a.byteLength + b.byteLength); + d.set(new Uint8Array(a)); + d.set(new Uint8Array(b), a.byteLength); + return d.buffer; +} + +function getSeed(length) { + GostRandom = GostRandom || root.GostRandom; + var randomSource = GostRandom ? new (GostRandom || root.GostRandom) : rootCrypto; + if (randomSource.getRandomValues) { + var d = new Uint8Array(Math.ceil(length / 8)); + randomSource.getRandomValues(d); + return d; + } else + throw new NotSupportedError('Random generator not found'); +} // + +/** + * Algorithm name GOST R 34.10

+ * + * The sign method returns sign data generated with the supplied privateKey.
+ * + * @memberOf GostSign + * @method sign + * @instance + * @param {(CryptoOperationData|TypedArray)} privateKey Private key + * @param {(CryptoOperationData|TypedArray)} data Data + * @returns {CryptoOperationData} Signature + */ +function sign(privateKey, data) // +{ + + // Stage 1 + var b = buffer(data); + var alpha = atobi(hash.call(this, b)); + + var q = this.q; + var x = mod(atobi(buffer(privateKey)), q); + + // Stage 2 + var e = mod(alpha, q); + if (isZero(e)) + e = ONE; + + var s = ZERO; + while (isZero(s)) { + var r = ZERO; + while (isZero(r)) { + + // Stage 3 + var k = mod(atobi(this.ukm || + getSeed(this.bitLength)), q); // pseudo random 0 < k < q + // Stage 4 + if (this.curve) { + // Gost R 34.10-2001 || Gost R 34.10-2012 + var P = this.P; + var C = mulEC(P, k); + r = mod(getX(C), q); + } else { + // Gost R 34.10-94 + var p = this.p, a = this.a; + r = mod(expMod(a, k, p), q); + } + } + // Stage 5 + s = mod(add(mul(r, x), mul(k, e)), q); + } + // Stage 6 + // console.log('s', bitoh(s)); + // console.log('r', bitoh(r)); + var zetta; + // Integer structure for SignalCom algorithm + if (this.procreator === 'SC') { + zetta = { + r: bitoh(r), + s: bitoh(s) + }; + } else { + zetta = from2(r, s, this.bitLength); + // Swap bytes for CryptoPro algorithm + if (this.procreator === 'CP' || this.procreator === 'VN') + zetta = swap(zetta); + } + return zetta; +} // + +/** + * Algorithm name GOST R 34.10

+ * + * The verify method returns signature verification for the supplied publicKey.
+ * + * @memberOf GostSign + * @method sign + * @instance + * @param {(CryptoOperationData|TypedArray)} publicKey Public key + * @param {(CryptoOperationData|TypedArray)} signature Signature + * @param {(CryptoOperationData|TypedArray)} data Data + * @returns {boolean} Signature verified = true + */ +function verify(publicKey, signature, data) // +{ + + // Stage 1 + var q = this.q; + var r, s; + // Ready int for SignalCom algorithm + if (this.procreator === 'SC') { + r = htobi(signature.r); + s = htobi(signature.s); + } else { + if (this.procreator === 'CP' || this.procreator === 'VN') + signature = swap(signature); + var zetta = to2(signature); + // Swap bytes for CryptoPro algorithm + s = zetta[1]; // first 32 octets contain the big-endian representation of s + r = zetta[0]; // and second 32 octets contain the big-endian representation of r + } + if (compare(r, q) >= 0 || compare(s, q) >= 0) + return false; + // Stage 2 + var b = buffer(data); + var alpha = atobi(hash.call(this, b)); + // Stage 3 + var e = mod(alpha, q); + if (isZero(e) === 0) + e = ONE; + // Stage 4 + var v = invMod(e, q); + // Stage 5 + var z1 = mod(mul(s, v), q); + var z2 = sub(q, mod(mul(r, v), q)); + // Stage 6 + if (this.curve) { + // Gost R 34.10-2001 || Gost R 34.10-2012 + var k2 = to2(publicKey), + curve = this.curve, + P = this.P, + x = newFE(curve, k2[0]), // first 32 octets contain the little-endian representation of x + y = newFE(curve, k2[1]), // and second 32 octets contain the little-endian representation of y. + Q = new newEC(curve, x, y); // This corresponds to the binary representation of (256||256) + var C = mulTwoEC(P, z1, Q, z2); + var R = mod(getX(C), q); + } else { + // Gost R 34.10-94 + var p = this.p, a = this.a; + var y = atobi(publicKey); + var R = mod(mod(mul(expMod(a, z1, p), expMod(y, z2, p)), p), q); + } + // Stage 7 + return (compare(R, r) === 0); +} // + +/** + * Algorithm name GOST R 34.10

+ * + * The generateKey method returns a new generated key pair using the specified + * AlgorithmIdentifier. + * + * @memberOf GostSign + * @method generateKey + * @instance + * @returns {Object} Object with two CryptoOperationData members: privateKey and publicKey + */ +function generateKey() // +{ + var curve = this.curve; + if (curve) { + + var Q = curve.infinity; + while (isInfinity(Q)) { + + // Generate random private key + var d = ZERO; + if (this.ukm) { + d = atobi(this.ukm); + } else { + while (isZero(d)) + d = mod(atobi(getSeed(this.bitLength)), this.q); // 0 < d < q + } + + // Calculate public key + Q = mulEC(this.P, d); + var x = getX(Q), y = getY(Q); + // console.log('d', bitoh(d)); + // console.log('x', bitoh(x)); + // console.log('y', bitoh(y)); + } + + // Return result + return { + privateKey: bitoa(d, this.bitLength), + publicKey: from2(x, y, this.bitLength) // This corresponds to the binary representation of (256||256) + }; + + } else + throw new NotSupportedError('Key generation for GOST R 34.10-94 not supported'); +} // + +/** + * Algorithm name GOST R 34.10 mode MASK

+ * + * The generateMaskKey method returns a new generated key mask using for wrapping. + * + * @memberOf GostSign + * @method generateMaskKey + * @instance + * @returns {Object} Object with two CryptoOperationData members: privateKey and publicKey + */ +function generateMaskKey() // +{ + var curve = this.curve; + if (curve) { + // Generate random private key + var d = ZERO; + while (isZero(d)) + d = mod(atobi(getSeed(this.bitLength)), this.q); // 0 < d < q + + // Return result + return bitoa(d, this.bitLength); + } else + throw new NotSupportedError('Key generation for GOST R 34.10-94 not supported'); +} // + +/** + * Algorithm name GOST R 34.10

+ * + * Unwrap private key from private key and ukm (mask) + * + * @memberOf GostSign + * @method unwrap + * @instance + * @param {(CryptoOperationData|TypedArray)} baseKey Unwrapping key + * @param {(CryptoOperationData|TypedArray)} data Wrapped key + * @returns {Object} CryptoOperationData unwrapped privateKey + */ +function unwrapKey(baseKey, data) // +{ + var curve = this.curve; + if (curve) { + var q = this.q; + var x = mod(atobi(buffer(data)), q); + var y = mod(atobi(buffer(baseKey)), q); + var z = this.procreator === 'VN' ? mod(mul(x, y), q) : mod(mul(x, invMod(y, q)), q); + return bitoa(z); + } else + throw new NotSupportedError('Key wrapping GOST R 34.10-94 not supported'); +} // + +/** + * Algorithm name GOST R 34.10

+ * + * Wrap private key with private key and ukm (mask) + * + * @memberOf GostSign + * @method unwrap + * @instance + * @param {(CryptoOperationData|TypedArray)} baseKey Wrapping key + * @param {(CryptoOperationData|TypedArray)} data Key + * @returns {Object} CryptoOperationData unwrapped privateKey + */ +function wrapKey(baseKey, data) // +{ + var curve = this.curve; + if (curve) { + var q = this.q; + var x = mod(atobi(buffer(data)), q); + var y = mod(atobi(buffer(baseKey)), q); + var z = this.procreator === 'VN' ? mod(mul(x, invMod(y, q)), q) : mod(mul(x, y), q); + return bitoa(z); + } else + throw new NotSupportedError('Key wrapping GOST R 34.10-94 not supported'); +} // + +/** + * Algorithm name GOST R 34.10

+ * + * @memberOf GostSign + * @method derive + * @instance + * @private + * @param {CryptoOperationData} baseKey Key for deriviation + * @returns {CryptoOperationData} + */ +function derive(baseKey) // +{ + + var k, ukm = atobi(this.ukm); + var q = this.q; + var x = mod(atobi(buffer(baseKey)), q); + + if (this.curve) { + // 1) Let K(x,y,UKM) = ((UKM*x)(mod q)) . (y.P) (512 bit), where + // x - sender’s private key (256 bit) + // x.P - sender’s public key (512 bit) + // y - recipient’s private key (256 bit) + // y.P - recipient’s public key (512 bit) + // UKM - non-zero integer, produced as in step 2 p. 6.1 [GOSTR341001] + // P - base point on the elliptic curve (two 256-bit coordinates) + // UKM*x - x multiplied by UKM as integers + // x.P - a multiple point + var K = mulEC(this.peer_Q, mod(mul(ukm, x), q)); + k = from2(getX(K), getY(K), // This corresponds to the binary representation of (256||256) + this.bitLength); + } else { + // 1) Let K(x,y) = a^(x*y) (mod p), where + // x - sender’s private key, a^x - sender’s public key + // y - recipient’s private key, a^y - recipient’s public key + // a, p - parameters + var p = this.p, a = this.a; + k = bitoa(expMod(this.peer_y, x, p)); + } + // 2) Calculate a 256-bit hash of K(x,y,UKM): + // KEK(x,y,UKM) = gostSign (K(x,y,UKM) + return hash.call(this, k); +} // + +/** + * Algorithm name GOST R 34.10

+ * + * The deriveBits method returns length bits on baseKey. + * + * @memberOf GostSign + * @method deriveBits + * @instance + * @param {(CryptoOperationData|TypedArray)} baseKey Key for deriviation + * @param {number} length output bit-length + * @returns {CryptoOperationData} result + */ +function deriveBits(baseKey, length) // +{ + if (length < 8 || length > this.bitLength || length % 8 > 0) + throw new DataError('Length must be no more than ' + this.bitLength + ' bits and multiple of 8'); + var n = length / 8, + b = derive.call(this, baseKey), + r = new Uint8Array(n); + + r.set(new Uint8Array(b, 0, n)); + return r.buffer; +} // + +/** + * Algorithm name GOST R 34.10

+ * + * The deriveKey method returns 256 bit Key encryption key on baseKey. + * + * This algorithm creates a key encryption key (KEK) using 64 bit UKM, + * the sender’s private key, and the recipient’s public key (or the + * reverse of the latter pair + * + * @memberOf GostSign + * @method deriveKey + * @instance + * @param {(CryptoOperationData|TypedArray)} baseKey Key for deriviation + * @returns {CryptoOperationData} result + */ +function deriveKey(baseKey) // +{ + var b = derive.call(this, baseKey), + r = new Uint8Array(32); + + r.set(new Uint8Array(b, 0, 32)); + return r.buffer; +} // + + +/** + * Gost R 34.10 universal object

+ * + * References: {@link http://tools.ietf.org/html/rfc6986} and {@link http://tools.ietf.org/html/rfc5831}

+ * + * Normalized algorithm identifier common parameters: + * + *
    + *
  • name Algorithm name 'GOST R 34.10'
  • + *
  • version Algorithm version + *
      + *
    • 1994 - Old-style GOST R 34.10-94 ExpMod algorithm with GOST R 34.11-94 hash
    • + *
    • 2001 - GOST R 34.10-2001 Eliptic curve algorithm with old GOST R 34.11-94 hash
    • + *
    • 2012 - GOST R 34.10-2012 Eliptic curve algorithm with GOST R 34.11-12 hash, default mode
    • + *
    + *
  • + *
  • length Length of hash and signature. Key length == hash length for EC algorithms and 2 * hash length for ExpMod algorithm + *
      + *
    • GOST R 34.10-256 - 256 bits digest, default mode
    • + *
    • GOST R 34.10-512 - 512 bits digest only for GOST R 34.11-2012 hash
    • + *
    + *
  • + *
  • mode Algorithm mode + *
      + *
    • SIGN Digital signature mode (default)
    • + *
    • DH Diffie-Hellman key generation and key agreement mode
    • + *
    + *
  • + *
  • sBox Paramset sBox for GOST 34.11-94. Used only if version = 1994 or 2001
  • + *
+ * + * Supported algorithms, modes and parameters: + * + *
    + *
  • Sign/Verify mode (SIGN)
  • + *
  • DeriveKey/DeriveBits mode (DH) + *
      + *
    • {@link CryptoOperationData} ukm User key material. Default - random generated value
    • + *
    • {@link CryptoOperationData} public The peer's EC public key data
    • + *
    + *
  • + *
  • GenerateKey mode (SIGN and DH) version = 1994 + *
      + *
    • namedParam Paramset for key generation algorithm. If specified no additianal parameters required
    • + *
    + * Additional parameters, if namedParam not specified + *
      + *
    • modulusLength Bit length of p (512 or 1024 bits). Default = 1024
    • + *
    • p {@link CryptoOperationData} Modulus, prime number, 2^(t-1) + *
    • q {@link CryptoOperationData} Order of cyclic group, prime number, 2^254 + *
    • a {@link CryptoOperationData} Generator, integer, 1 + *
    + *
  • + *
  • GenerateKey mode (SIGN and DH) version = 2001 or 2012 + *
      + *
    • namedCurve Paramset for key generation algorithm. If specified no additianal parameters required
    • + *
    + * Additional EC parameters, if namedCurve not specified + *
      + *
    • p {@link CryptoOperationData} Prime number - elliptic curve modulus
    • + *
    • a {@link CryptoOperationData} Coefficients a of the elliptic curve E
    • + *
    • b {@link CryptoOperationData} Coefficients b of the elliptic curve E
    • + *
    • q {@link CryptoOperationData} Prime number - order of cyclic group
    • + *
    • x {@link CryptoOperationData} Base point p x-coordinate
    • + *
    • y {@link CryptoOperationData} Base point p y-coordinate
    • + *
    + *
  • + *
+ * + * @class GostSign + * @param {AlgorithmIndentifier} algorithm + */ +function GostSign(algorithm) // +{ + algorithm = algorithm || {}; + this.name = (algorithm.name || 'GOST R 34.10') + '-' + + ((algorithm.version || 2012) % 100) + '-' + (algorithm.length || 256) + + (((algorithm.mode || 'SIGN') !== 'SIGN') ? '-' + algorithm.mode : '') + + (typeof algorithm.namedParam === 'string' ? '/' + algorithm.namedParam : '') + + (typeof algorithm.namedCurve === 'string' ? '/' + algorithm.namedCurve : '') + + (typeof algorithm.sBox === 'string' ? '/' + algorithm.sBox : ''); + + var version = algorithm.version || 2012; + + // Functions + switch (algorithm.mode || 'SIGN') { + case 'SIGN': + this.sign = sign; + this.verify = verify; + this.generateKey = generateKey; + break; + case 'DH': + this.deriveBits = deriveBits; + this.deriveKey = deriveKey; + this.generateKey = generateKey; + break; + case 'MASK': + this.wrapKey = wrapKey; + this.unwrapKey = unwrapKey; + this.generateKey = generateMaskKey; + break; + } + + // Define parameters + if (version === 1994) { + // Named or parameters algorithm + var param = algorithm.param; + if (!param) + param = GostParams[this.namedParam = (algorithm.namedParam || 'S-A').toUpperCase()]; + this.modulusLength = algorithm.modulusLength || param.modulusLength || 1024; + this.p = htobi(param.p); + this.q = htobi(param.q); + this.a = htobi(param.a); + // Public key for derive + if (algorithm['public']) + this.peer_y = atobi(algorithm['public']); + } else { + // Named or parameters algorithm + var param = algorithm.curve; + if (!param) + param = ECGostParams[this.namedCurve = (algorithm.namedCurve || 'S-256-A').toUpperCase()]; + var curve = this.curve = newCurve(htobi(param.p), htobi(param.a), htobi(param.b)); + this.P = newEC(curve, + newFE(curve, htobi(param.x)), + newFE(curve, htobi(param.y))); + this.q = htobi(param.q); + // Public key for derive + if (algorithm['public']) { + var k2 = to2(algorithm['public']); + this.peer_Q = new newEC(this.curve, // This corresponds to the binary representation of (256||256) + newFE(this.curve, k2[0]), // first 32 octets contain the little-endian representation of x + newFE(this.curve, k2[1])); // and second 32 octets contain the little-endian representation of y. + } + } + + // Check bit length + var hashLen, keyLen; + if (this.curve) { + keyLen = algorithm.length || bitLength(this.q); + if (keyLen > 508 && keyLen <= 512) + keyLen = 512; + else if (keyLen > 254 && keyLen <= 256) + keyLen = 256; + else + throw new NotSupportedError('Support keys only 256 or 512 bits length'); + hashLen = keyLen; + } else { + keyLen = algorithm.modulusLength || bitLength(this.p); + if (keyLen > 1016 && keyLen <= 1024) + keyLen = 1024; + else if (keyLen > 508 && keyLen <= 512) + keyLen = 512; + else + throw new NotSupportedError('Support keys only 512 or 1024 bits length'); + hashLen = 256; + } + this.bitLength = hashLen; + this.keyLength = keyLen; + + // Algorithm proceator for result conversion + this.procreator = algorithm.procreator; + + // Hash function definition + var hash = algorithm.hash; + if (hash) { + if (typeof hash === 'string' || hash instanceof String) + hash = {name: hash}; + if (algorithm.version === 1994 || algorithm.version === 2001) { + hash.version = 1994; + hash.length = 256; + hash.sBox = algorithm.sBox || hash.sBox; + } else { + hash.version = 2012; + hash.length = hashLen; + } + hash.procreator = hash.procreator || algorithm.procreator; + + if (!GostDigest) + GostDigest = root.GostDigest; + if (!GostDigest) + throw new NotSupportedError('Object GostDigest not found'); + + this.hash = new GostDigest(hash); + } + + // Pregenerated seed for key exchange algorithms + if (algorithm.ukm) // Now don't check size + this.ukm = algorithm.ukm; + +} // + +export default GostSign; diff --git a/plugins/srktoolbox/src/core/vendor/remove-exif.mjs b/plugins/srktoolbox/src/core/vendor/remove-exif.mjs new file mode 100644 index 00000000..6c5c9e53 --- /dev/null +++ b/plugins/srktoolbox/src/core/vendor/remove-exif.mjs @@ -0,0 +1,151 @@ +/* piexifjs +The MIT License (MIT) +Copyright (c) 2014, 2015 hMatoba(https://github.com/hMatoba) +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +import Utils from "../Utils.mjs"; + +// Param jpeg should be a binaryArray +export function removeEXIF(jpeg) { + // Convert binaryArray to char string + jpeg = Utils.byteArrayToChars(jpeg); + if (jpeg.slice(0, 2) != "\xff\xd8") { + throw ("Given data is not jpeg."); + } + + var segments = splitIntoSegments(jpeg); + if (segments[1].slice(0, 2) == "\xff\xe1" && + segments[1].slice(4, 10) == "Exif\x00\x00") { + segments = [segments[0]].concat(segments.slice(2)); + } else if (segments[2].slice(0, 2) == "\xff\xe1" && + segments[2].slice(4, 10) == "Exif\x00\x00") { + segments = segments.slice(0, 2).concat(segments.slice(3)); + } else { + throw ("Exif not found."); + } + + var new_data = segments.join(""); + + // Convert back to binaryArray + new_data = Utils.strToCharcode(new_data); + + return new_data; +}; + +function splitIntoSegments(data) { + if (data.slice(0, 2) != "\xff\xd8") { + throw ("Given data isn't JPEG."); + } + + var head = 2; + var segments = ["\xff\xd8"]; + while (true) { + if (data.slice(head, head + 2) == "\xff\xda") { + segments.push(data.slice(head)); + break; + } else { + var length = unpack(">H", data.slice(head + 2, head + 4))[0]; + var endPoint = head + length + 2; + segments.push(data.slice(head, endPoint)); + head = endPoint; + } + + if (head >= data.length) { + throw ("Wrong JPEG data."); + } + } + return segments; +} + +function unpack(mark, str) { + if (typeof(str) != "string") { + throw ("'unpack' error. Got invalid type argument."); + } + var l = 0; + for (var markPointer = 1; markPointer < mark.length; markPointer++) { + if (mark[markPointer].toLowerCase() == "b") { + l += 1; + } else if (mark[markPointer].toLowerCase() == "h") { + l += 2; + } else if (mark[markPointer].toLowerCase() == "l") { + l += 4; + } else { + throw ("'unpack' error. Got invalid mark."); + } + } + + if (l != str.length) { + throw ("'unpack' error. Mismatch between symbol and string length. " + l + ":" + str.length); + } + + var littleEndian; + if (mark[0] == "<") { + littleEndian = true; + } else if (mark[0] == ">") { + littleEndian = false; + } else { + throw ("'unpack' error."); + } + var unpacked = []; + var strPointer = 0; + var p = 1; + var val = null; + var c = null; + var length = null; + var sliced = ""; + + while (c = mark[p]) { + if (c.toLowerCase() == "b") { + length = 1; + sliced = str.slice(strPointer, strPointer + length); + val = sliced.charCodeAt(0); + if ((c == "b") && (val >= 0x80)) { + val -= 0x100; + } + } else if (c == "H") { + length = 2; + sliced = str.slice(strPointer, strPointer + length); + if (littleEndian) { + sliced = sliced.split("").reverse().join(""); + } + val = sliced.charCodeAt(0) * 0x100 + + sliced.charCodeAt(1); + } else if (c.toLowerCase() == "l") { + length = 4; + sliced = str.slice(strPointer, strPointer + length); + if (littleEndian) { + sliced = sliced.split("").reverse().join(""); + } + val = sliced.charCodeAt(0) * 0x1000000 + + sliced.charCodeAt(1) * 0x10000 + + sliced.charCodeAt(2) * 0x100 + + sliced.charCodeAt(3); + if ((c == "l") && (val >= 0x80000000)) { + val -= 0x100000000; + } + } else { + throw ("'unpack' error. " + c); + } + + unpacked.push(val); + strPointer += length; + p += 1; + } + + return unpacked; +} diff --git a/plugins/srktoolbox/src/core/vendor/tesseract/lang-data/eng.traineddata.gz b/plugins/srktoolbox/src/core/vendor/tesseract/lang-data/eng.traineddata.gz new file mode 100644 index 0000000000000000000000000000000000000000..e83c1267675ff3a6641b110002363782db7a1885 GIT binary patch literal 10923060 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

{f3LHw3i@B`>}&vp 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

#B|_z;Gj(jIE@aw zbvZ(0?8&v`Zk>YEI81OuIrvWkN1og}3UhEk^;5`WMP3Ae6J(A0>KUBG|8)Ki7I+__XIH9GYR4;F z>k|$B=WcPX{j+nxlH@M`5_p%SwMPYl=1kIK7`8n#X?NKX7XwnVKOu(35{P88?lkx;Pss{bE=t< zU0FPSS5!nlIC63L;_>^@N33Zm?j&{I)+sMGL0@4oH4*uzUwyY*1rfyjM3d%k!CF@P zHR3+<7O32pYM0r9K)ViPHi~9XqKH51KQhowgBPucu3lG>Q5+O}m}ciuq*2$&aLSTdIO8=>cMQMuk)eccQslfVeE&WO)c^gSPjW-co#G9dXo25E} z1Oh;kp>dIYkF{Rt^3@bW9DZ{!TuMlt&R)FHHcNUAjoU?*Te-IX=cdeCknt87-u%26 zYC0+P>3OkSIh&Up+!3#u79|yzp&sPFckIeYZsC#pQiC=FF`e(YaUV7YrS8Bhp!zXo zyiolT)G&2<)ItkF@RqiE!9d3ZC^1%$RcB=DK<6B(b(>%O9BY#byY!ca@YMgt&%B&V zS_v}sHW-xkJ&7HCB*;2V>i&k7YX|wu{t_VRa1sv4ak}lp7(3nYqS?8`h6_!>2tqS zxy;}fRG}Fcxx}yF`n}>XEm`taH;ukiAL_V(oxW*Z%NJx|gYd-a#1((>BR>Oz0Aoa; z0DuX)sQ=|?yptO33{dh{Q_n+i#I~GZqy!0v+8Wid#g~_*3367p|Mf0ccjU945ktd6 zDqj<1n`P-NfD^SYd(T_|{~7ahWj-HxK@y%+w32cE?m_^Tf_#PE{V=3IQ?D|9;l7H2 zdEKp^+(7rivskdPnKfnv75LO1Iv#im;(GTPRNhGxT4cPxdKPvu1r6zURJ)qo{IYZ1O@@_c(q#Oys? zg)Wwv`Z?E{w5Z@$5ODWWs{mx33AOM$V5#j96|Je9mNM23Iz$Yc)LYJfNIZ`i*7d&N zg2~0Aw9$=FJrq}kpZK)V7D-qyH4=ECTaH%ZEv2p4Y>r6OqoTDBOFn&YNVXBAVA{5> zT(v-(u+xg-uda#ov^Bo-LMUCqpulEN40eC^W@X1LQ4+^IQH$ZxWuGs>g`nR$vYn$} zyL86yWpx{D8f@R`X;*T>O$O8FUg0+Np$r< zx}{)sEi(IPUQq-QzEEp}6G}jULD`tIEniQ^MU84B6YeNqXDt5C!bb5iR09?W14F_t z_S&+K|7K`Xf!Vo;=K(hX-1MKcsoX3`S9)V|*(9$`g*%YapTHVXU!%a3#`RyR^TE>r zCMkMHHPBV`zq9%UV`|cCy7!z+3lP2bPt&8OX5)UT+U2G$wg1VV!~^wwQKQd-*cgYt z1~0H%snkT`x0dH=MA~%7Kp~Z2?z_GS09s0+gsXfr#)7-AV{bMFe@NKb7?;->%4rqV zdr-q25`?8g|Cfi; zPV>~{EHg*1Enk2T`c0^@Q=qn&5d($N?r0``HcM#@Elv?0apYSDpHbb>sbC!l z!`2*{gZ zk6NZTtqK6{56V(@q5kC|RM^vF+{m{onCiW&M@_4{umvp5yKjZxA2v}%V7)C?xK%Oed5DG6# z2s?x#KO~_-jkl&%7&Ra)SU#b9=1Q#N4R-Ppx{p2Q^@i=4BfslhbVX<+!gR63HAAGr=c`m!}W9Ips1FdsEv=R6(PcY>~OvD!b+xbZ5fc0$*Zp8_B#a)0$uvI27SF@iNUbk^PBH+Y%6s4+pRWS}0Y z9WE+ZE2AC<6Cyd`h}(J9fYnnbMlC|ujUkhuIsxe(R&{=-1RMpo=%d7XrQDcQf3Wmm z%op9>JGS7(7{v_3cg<9n#m~$^Ywr-~xywR8+II=gk@H9q!uMY6MjP%9gNd*ygQGFQ zzzrNRBptmll5XZ)AR-+Gy9^{F-czAe+B&4no4_X*7obCcl?`;Z%{Scw{0zRNe>{2y z+ExFI=S6vgvx>#>d3rImg@@g-ph`34tVzHWrbP-SLD14V9wsGpS@go1-6o@Y_=sWy z9ZqZ{ea2QZx=pBdhc5vSI@BT5t$D&0z&uoW^n74-suyods)Kz)w=gi*k3#! z%E0EW*@z(j%tBcxYYc=g);8@QQ?NOXchon|sKByYCvDrXNA&RvrXspz>vLwRFjx6< zfo>_{#+?gqQki0!OfoewiJUkm`hgl(WnW~Lixj!k`Kd>|3LN^2ovKpJxN{{Y5)5+H%b7yE=>cK{Y33=6+#Wf({_e11 zjwp_PjuImW5C1Iu4rADcHd8;M7{RllUYUzF!Gvg?d`#qYEsKNzqAvkjxb~cj(9?`W z3==o9c?}jVH~&PNWS8)Cn}<4(S$|zVNm9H_kf0nUSK<5L4R5J$nhrCI8CA6!{mVxN zx2}n7`f6E?h!dPpb)Axptm@jgc3dJVWhUToN)FbquHvx^Q=$3-X@?cGiR}e6Yyu`} zWL9`{TMSNE{QX#Y1;EM4#O>d0 zBA5$VX6BhYE1We2s{NX5x0Z20qx$Da0&zJgK9Mh0kA7-6Q$8x_V}* zbgWW&u|(&lw*j~P%H)9r`c^Y}MUaAIekr)YR=r7F@Jk7jZ9a~%U{eA?&)KUsaj37N zWXvswY!(%}OIZd)Y_0a)_+iMgvWR|gK$uOh(VXxhH8I>6l@DB38a=i#)I?78F4WwG8m6fw zR(Tq)L~$}JUx}LZ%}*R|C{y~+nE*_uLGRzAgr*&p1JxwXRCzJA)fg4X8QC7iDT9Jq z%#Gk$<0K=o8z&mn#7Ir2?<7uZy1ok#vRSCljCMx>A8cHhUV`WA@8a}V^Ggz^mffbv zXoF}~5>*}=$GQZt0oC(n#6=ir&i{{9_CfzC!je?$5m z_^uujFm(68zpX%2h>x`;gI|;>H;60zxZ*+mLdkwT@gO%r3K>Sw(+hxp6d8SH$cwnv z)Oqv1f6sz`nlEd`kKptaVx61pe5Rq#t%5Te0*1ZI+^e2AmMtK|c=fdE@s z;HUD6zhZ>7R12LzoBH9p;f!9O_27nVo3F=A${S81S2VL{6N!Ctdl}y&4TX-szUGk0 zl&Dz!&4>-*gycSx&UXwjM?IJ>Bg&|5<<_uQF9Xj-5m*-FE)Len0r8fx6fArT_A4AL zR}m;D3z+VG9u?U-bt~!BqqfJ+uXLGC)I^V5CHxc}_Nc^l%OgG9*KTjp2p-biK0zjo;MGe<8M@n-%|+gE(>96!$vciyRB6 zoWTYZ#;_ml6gPdQDKD@F$Z=%oW$Nv*7mRszvQP?m2Sxn=Z{~L|)C)SFzG% zBW0L|x|B2fhUb|byN*Tx7*>eY;fSz0rp@o4u{d)NrtRdx8zebFMcW%lb>~CDVj1tL z129LNvA-E7{?N<5s$LxhzEKC12;(YO@s@|oWQUq@eOev6*!q+sRphxA@@4{1*^Jws z+PH8A8M*W z`@o$RfE$U-OiFt*Yr`1b>YSL}FVPhE96`TX<+G&IFGlKS|H8@SE8Ew%!r^` z7N0zwfyDJYde>>x>AO{vZNgs%Z)l>T0qWn8X=!5=JO$DwZ@^mIyx&8eWCdr1`$qDYj{cAj* z;=>-r9+kZAI3dPsZE}#n!$QogL<6g`Cq6BnL(@R<;Sfgme5#d86qoY|{5vGM-FL;{ z8y4xa2nXq6m0kxd1-B7Rw4C0K7PH>E8> zEs~rh8HAY3q%hpC2||DZ;~kPBR)d>CE-+5klV1ia1*p=qdw^p;s0Pp+uh2zHEZV zU;suU+i5zEXWQ$MNsEz~$Py0@@ys$)uJ%ZL1HF^KB!JjzEmRjf3(og96My?KF+ZRc z=IAPwgcrvGE$LT|NbtibiWi1SStw55)mhNanBXUsKfz$}q&AfP8?_`Jchv4v$Unz8 z{+6N&BEtS+Q_F530pajj|NJQ)9(r4AiSC$&F>it9t)|R{)pN8q&*IfvoZY4IyIz>nr0p(mH*Ongf&^H>& zPqx+>J1cje^bJC8v?@_qQ1t8oGqG@d*MYRHpjKPjasKC6>qKMk`v`$oj3tVTC#Mps zdO4rRDK3HTo}=AFO9@uxb1TPfwA_@xJsw<@8s(V3m!DD@lYT>S9G?pAOyLk{5yR_+qK$QNm?icfKJW=L69Mm=)$_RlY0TQ5A`>!KLi3BifB$Kxcu$LF0h zmv4z2RLg>_L}B7#VzV|72pLM@F(iE)%0rKb)yd&`-}IMN#w1@&NJM}Kcm*eEwBl4( z0gy-`AN|%YAAdC&qQy9L;u{jmm@-hp{&aH0Wqf-oTGEeEI*^cp!;!}y8i_U_euc)! zc%gS;_O0hgY0WmYNmZt1G`memh~ls46$)m-1VSa2_zn~LG7dq?B96#MdW;7elcmEY z?or2hA$X;axu-x04=Fz-CC_ZoJAa4opih~xx!}C?64AZF^qyI>nr&|xCm6nx05In^ z5dj2?C+2?A)ymSv$8IWjSZr!y(oeA-u)8YCv4)euh#%tnC6hedFr#@e1p>RXbeh_S z{Zo&@Vy`bSZ0LFQVYzF&Fy@n}$6-A@^dBzE(mLg?D0| z_63i?uveQ|7_;2s5Xxbi~*fD_lw8kCz8CsONi^ce`@wSKO@JiVKg z2xrbv{H5vm7Zo>^O@sKy0v`*&On$?S`P(V(gweoFmIaX(9M0(V%}^0Epjpt3m$f*R zj;_U=7m~%1v0ELa#8Hxhg{Ab9H-0!EtYr1@pT;Qqu;!ZKnK$0O_O&NO93U>?gV#RF#4olY~(Qz@D~6jHb0HI zd+@hCv7h+G^wH)qXFiQ}y69Vlk>@y&wPTkhjQfIkqRYh)+gcRP_GH7Y`Grmtk7mKc zL?ti*`S&m6JKYpS;RbIFc5*rz1R=m2PDt>bJ|)ApdA}qI_P}2SKC=GyQ~s^n;T>6p zVoHVJ^NW?%fV}h-A#p7xBUs3;}a|zUpLH*NL?gzj5lOH3R3=V!@4Vq^LB|?V8;ht|a)HB!X$2892PrYkrwzCf==^ir4gjQ`^y} z;W`3)SxGv_Kj&&0ketV28P@|K#o#A!H|fZS>uyuGjB?;=a4EYAXV-H6L~fP5z$9Ny`)(;;^2CaYaNwS;$e zA{F1Z>WzP5HzC=X_Nc^DVHx`xSVH;TvIf(qw#$WJmt_(xyz2t+-Dak)@>~%nPk~%Z z$%PO@N2Yo7XHNQ^rj3lM=^rj%o3&I?h4P0BoR$CasMCatbN^LJV%>u3>4XmXQW4nk ziY#Bh$zZP*kT}PcaO9RyJl*E-#>Y&={VPtDdSUdE+20(VF=k)le$0lq;_4Mjlqvoq z(LZpS?WGH$h^1kfgWtv4rjwMF8G;4Rq0=e{JjA#jVdPmJgAw(_M%{yQUR}9QmM2wI z3#5#fPtrB9hnw<;^I^6K9Usd$0qYdL?5tyw+IBiVQlaofz{Xo3B`1>31=674kDWov zS&;I^$Xep*vw8Quq>q^x_!Vx5i{02(L1^rh{89=P3F1vUz z#fi1Bn6=4<@D}&hod1eJwc_0krx2<^;G4V2>BN-T4E3F5)IAZj!TvFc@pSD=-ezb4 zbiG{jL$=wUbUeZ2Pivr&4H-APqafz`nk;O?%{gk`ahn>V89nx)NT}B z8bRj(M&_lNRy2f7GUl4=E_rX$gb3@bk&X3xndxNpwH@;8otDXp`R!WN(d($j-3=rj zp40koORA6zJxU-YM*oipH{uOiypNCu2-;hCMLpfNC$|qd{-x9YQeeK$2aw}({5hXS zT)3Yl63nE>cfRa$QCZ=W-9uW*gF9dcgIYFIyXI8M{ zYB|ooE788s-b$7gyCY6-v=-rz4R1@&?&5lCGhH^4`<*TkdueXTN`Kpyr-Kx1FIV%7 z6#ZV|?JHQWIQt)W%r4n_Hz~Y3zl`506s7cM&s)h%kt~3n`Y0i8Wd|&<>NOYbOqu%| zmFOk@bVUvcUB=HwMV4fSlpMZ>dSC3F-@F~oUf_A8mq;`!Syuo`szhs<<^Otu~J zv(Wu#*w@b>jSC0p#K(?DQcbnD6v_$TFl>bKpA08Q)};0Pymjvxpkk#@!*z8>XKmBN z7QpjHJW##FZOKnh;H?*71z1B(-nk&x84PWJACl^Fi z>D~6>R-#@PQH|W~`eE52UU5WXUAW58xg1k4t`wK2gi@1y2(3^D!k%mRw!)Gh94@IQ z-eF>~;QbuP>sexN8IvW?^_PoJztcuQ;sB43Og)XGlD#ncUJelv=L_i~L803&} zLJb?NiT$?ZicUL+Ozgno&xfAXMXl^34X74U{M?Gjis{`OoncMV)U@`AC_~B#7cs4u z#0exVM0$jt1VkJUAv4T^S0W;69`!0WmTpqDS{&!A%MpuIG=*R`P_oD$H6JcE5LfEY z$4yq^aIBOWnzZpsq<{V!2aU7JfjZXbCVvS1aOlsL0p!RExw^lSnBh1BqaI^_`oIov zumROjAFSLx)#&wAL^c%`RZ?~3m;r4Wb8!Zc;}Ko5B?}H*8nPBb)bYzyDbr)&yQV{4 z*cxo#kmrTQ1FB67-;t;;BgznH^T0hxl8r2*phULpN2*3r7}B4e0ZBjl;a{EQYrJX4 z#HuBdwcCAxuGxX$6SZn}#)?i)I0IGPWVCrDWHMzQkbhj1!%>Hkm~pyecOMS~jspEF z(e$}cOfR`)#!Jc|ZzCSk`^jWkBf%N+HiSHdXZHa(5F>_&4wQ}D4wT_6YvhYuch7wO z{X0?#xt(n-W{s&Ux;+M-~qu27$_+@pvMD{m8Vim z4wS}>XA(LnbJj#eb7jyK`Dc(6kT+yWOD-7W6l%7M@56s8yuErqir;iK_-)SfBk4DE zRSoU^P+D7lez!l(eWTdx+w?-<>?*o+Md`+7j3VQIX+~s0uSI_|>^t%nxjBS1`%-*PQQ^Yv>*NOCUVr zzgx_2Okf5M_MTA_wFC!AYLlRdbcklTC-NCTGcz0MP2~v3kC&}XRvV0%`X4n7Z1bPo z+PLhO{&f(agLsg&Szv_(+MMp!#~#`WIpB0_G#9~PlpG;S&UUel8ENje)&RA;-q`Do z|HF5FEeVe}Z{1EQhAdEd0#`rkV3^*i^40Zmqg;L8*nFCZJ|%nlt*%Wz!0mAQ(QNU6 zOEN_1cJw|{sA9wiA}c9hz?g@;KFf)^!_WOA#-dBBtT6k7i!2$x@UUb? zdY6Vcp^Ur03*hfe{e}=Av>1znWhQpvY2k2I^D&Gaqjr+9N@Jx?ARiu2Eq>}o_;WhN z94WieGa3*Wg>eqd_dhjmaLn&&{B+az=(VGji}Ee{ty8k}<0xf0qe{V>XNT`4o@w>- z71ouf*>cmquh*-GW!KLtt>*m_GryrO z99^60oVjTN)S^cD14wAm@EylxK7eiyMvykvS4;m_Po*dz(q&D8UXN+17{+uLQ_rKL z{H)Z;E;5i8k>~71^aI9&E?pa;@OWbm|E}h5A-1#yKCW+f$i~h`{hInUdCJ`FB|Rc) zd2$mG+)jmrimQAKE&m_Z^hsUL&8c(_p_082?B^(F;bzX+bZFquCU+(M6^2z=Hea_V zEjTCc4U32PXgQfk@Wjbv90ri|%;jn>`CI=(I!OYiU>p>)L=`V(f{P#mv$VjY7y+Gp z7b?TTj_)9hSVZPF+d>i7i@K4^p;2mrb@yvDGVjFL5^<|UQ;OWgrmiq%S z@IN_*ZH{kDDD!-Moy4&_``ZfXy5WC~vz(j$uXZj^JDP&+DrxQ~ruw&~`*0;>+9(h4 zS8*YgJQEm^%T>Y5Exp zT3?V&d`eY8+dp8_*FS!rUHyRLIU6DGsraTn?9JZk4f!7lRM&3`iy+ifhWo~!nT~!t*4z&&%JM<}UEVn?6x>tS?V zgBr_G`|-wLxi6&vaoMA=uWCP%RVnnwY>l8^L8p2ro!ZxM7++vfiVDIf3cdRUx%p6n zVrySB!z~2qQ`WB~+~AlPE_qGETheMC&s4tRbol``+~lMvMcm1hUi@I2kDMw30(e1m z4cLDVt-C`QZ0^mS)(CtprqE}EG<9c$DBj81Z}oD^E$e)^qO_!E#NqtzJ2}#k2*Znj zIoSPAkh=Ux_I|YxeDp&_Vv2%7N$#~{W4yy}#7fC)k-Wsef58*~9{l*K z_JMWXs&DBKtIZn(AtDbq7mDMT9YMEO8qLwE2<>=66{cUQjgR zX6l9ElRDTGL@6&kk2q1lM)Y%JJ!k(4Raw7O&DN2!Pi#`awZKO8vwZw!NOZ}-89m5I zZ=d8E&B$gZ`jV#D?j2)Rl>54!I4AC&f9CL19|mvHh3`nM`#$NivsNwLCqCfwR2VMN z`Wp5j`t#Kx_`~;GvYVJ-f+NBFMZFcpo?m=MUgdPY>wb^tgXbVCsLiJe$Cj_W9Alch z%i`kiSlsUNJRiM%t-3h(27fzbJ3sKby}&SWcyRu;A`L@mMXBf7MQ>Nlw_Gv2*V_6u z-)^5d@HeX}=hd6JQ%83iN$ ztyfU~hb7aU+3F)0md_#JggvtkvCEsijeGx-G3W+T)9?6r>u{+1AN6HZ$yd*FG1J&U zOflE>lMiM!ayL450vj70m7x=1s_*k&G+Y+I*o+8{0EYVQ)>&8Uwwl5L-fe0Ix1p|P zzaWeYMQiuDOL%u>4R}2(c$H2I689PKzYu(YCw8RxZgQr=lDKD{bqGEGSepy9EKiXX z?$2{Fusu}PP`^aWD8Ob+h#~R5iVsn{!0(8`pDey<^)fC>7SnSD6QC1eHIQ26_Bw7a&oNv{33^dosD%lCFRHj45eO<3$n zQM$R>Uk*yA_hZ@PV)BY+^I~(%$lU0i?0ZH?=R9c`q++$i7iqPID*%WN4qk=964bOS z`7cM`{vB*yZUZzH2eM%NHqyx9ljvvoz{8uft&g~Bg7&0#t-Lq{zlLKg3GRo0^O%cG zU=9{TS149lbAM&O-E##sUdFTF2Yq0{!O(=JBqtMzk&u{nk-B~xP)e8F&X^w*Uoutw z8_@mu)vK`MOb7GBpB4_bb!nndn2rPGDyt<5uq}~2HpDj|YRK#BTs+`}A~0S+LDlem zcn$@zPFk3Br}ze`0Na+R#@-$hZf9sn6N*DJ-?url9)6aZEziy*X@}4Qf$DOc1?7 zSnN5NH&eL>fEj3iFHjDLwV9vePw$QI-+nwUIYhjRLYE^>-azl+j%S0TDX@=>M`TY7 zlkPoOjLlArQj}zkc!kWrrqBaLwkjXZ1`OPq!i%1%{mb!17~IyV-zN?vP<{MyRT}iC z1^(*w$6=~#x_y_Kj8J(so~zvZ#u$|BOzwjg6EDymTka*W(@$)bTvT81=ZYoD4kx$X z%Lskwc=Uk+wWfF?V|mENbzTs2%5ko@$ClAA!O2f~*+|AdD%U*G!WKpZ{oE(M(p?n`B#5*GM2{7`nw z1U4S&T}Q3~m``u>UYa!I8?JXVm?Vk)A4g{u&{o%UVW3c;l;Wj0rMN?JON+aE@fRr$ z#Wg^2cPWzM?yfkD1a!n$Qp8#x zd4h?Z>1;>)OaT(9+y27cvyOsbRC#6MM{xG5!3x*@0QhIkeWaH-O>xeqF9PY+SR`E~ zZ%CP>MId=q4LX4jALh7_qLXZ6!2fkinbqc{uDO~d%1%^^b_)6=Ds~zBU!VU@sT%?7 zDEckWu#gF60&HxKBPazkj1A2N^pRi7Q=TdI*g(OBO>9sb|%rPhBjlnMxfj zPa96%Sn-cAm_Pk$730w`!@+C>VseA;k8=$C&3yO?IGl-5(@he-JFxD@cXABWA`!sttd zOovB82vt!lbg=6KdzkG6@}84HSHx=rLt4)g^X5I}K2-yY3<{LO1TH7jFjjANlszgE z_094xgQ*g7*oRj2_kCz6O!P!sVP935QqwZs*nTI=H?&s171b*`hr?WcH=QUB{JvBm zT<<%0zIINk^D%GpFPph*DxBfwu_t|=5r=O4?B_vynM~^=da8l@a*-2Jm{>2}YJ2S{ zxOQ`BmcRbgz^3x`|J9>T{@9#-cikNb{K1~)g7HW-VZr?YFJZN=yJyT)1b@uxYkc3B zEZ3S*U3!g;1vSZ-!O`T%x35Ta>d0Run7c7hsvL>8^x2eBa?*TsaXMV?DL|WGwy&oQ z4)+;1@}cMqj;YM;F_xnOOF1!qv#F(d&-tk|qgxHfJ82(D?!e}M67`^n!NNdICH&Q5 z66-EEG#g?0tjX8m;dU5F7ua`BMYSS0`Nc`#a96^N4;@bb&?#Y-9H`*Zj2Q@EA1mzG z_6j4+Xl0d6&OrVkKC8z=s7_PJHCu?nMSaJBD8p0ueIJ#-1FkO8TP(=o+I*G#WM#|% zRuYn|vvN(u%}ZGP_gTxj&d_g~@M>|XPz_evVSWU6@4z8`1~<+vhB?S>dY!crA=uzp zm|qnAH3~5)(?)^^k=Ht*U4@w=!wJl|43Hufknud%nQG^MP#1ML^PmU5C=uHKeLW@| zP#3yF2epMMKY^gp+Q_e?RIjv|7o21hv+DW6g~f=e~@+hz4vB`n|ny!F(02QfkY-8kxn$A9_UJZ!Pca^+7L8-7eBlN6hqDu~lfxyZCOjS;Wrw?$=wZJDmvKjk^KfE+YU>i~a3Wi! z9-Sbv)rDA`CZHrcrUrf7qE*#=8Daehz5uMM(bEs;?uatp9iFYou#9;rZN2GSHSY6U z#&X7YFO}KbLZ!|e&lA8g{7l==`j&cvs1H^j6rpakaNBpFKWSU=im1Oi9;sRZkc_QU zPOcA+FO!%~Tr%BeozxhpS%dyPCkjx(H(hKS)kAp;TFYG{lfI7@Kv*0+8t!KGxJ(sN zj9z;nQEi-beag@K0<5ij<=F7IzM9Md-$AP#;vT3@tq0;!%5MKwz@srv!N&~n9qD_5 zGY<^NTb$t?~E zM2giB|8V#@%A&NNDx>Gy37a9@-i!Z0?0;nkRc$&`km`*pzXf!^)POj-ko#6tI6pA_ zzJch?$zv4g(24mgp|V`QJ;qwbY&jCpS@Zg0*ORx~ku^~+zY(?T+X?%_eO2h3(N*{Z z@9~Ckd3J?Z+WR5(!H9p@VuaGAx->03iY)7b2HihXoeb-o0vq(| zTuYH5AOisS2lGNZ{|$6uLp{QA^XT5t-GJ`Gj!Zw^$=6Z&kT}01YIoQhN{o3rILHAx z^}%0IQM!K*fk+X4yvL6Iqi8A>DRx_e2>~S>pWrP4DRmVQ0)CO2Pt+Vx?8mhC0}RMO zvn197-azg&jCcD^GjW!<;zDT&IoWu$@6#j9DRBi%U@q}vP!#k6=MO1+9k;5|PmWiKMZ zpC<<=L5sF8GqH+>XQY~U=Zvh(BsGlX|9KN_wW#RHMXN)L&HBxR?Bx_Hn{=gBe&A~; zu(@e5u;f8fHTz3w2NDaYxh>oOYUaIr$A*xk1&LoG!-A-#yAP)}5qi6qujHlx%#qDY zj2D%71*?D8a}5AvLU_KtjbpDc zF&+G8JrW$NwHaJI;L+5Vk`4xmSoo;*G!`R4gQ&AOqSZ=+;L3gMz+f|3F2_9+w z3BMk2b#sG-plmt*;r`hc2;B5sd~y(gJ-l=MT^CLf=Jv17ThG^*e_1E>U-g&hw$ECu zlNHPhG39ermRf-qBHQhAB{McE_+`BMMBimGhOq?j=!r)E0x?+_d;nLM62J6u)L~vq zLNXustMgxDp1ilffu=l1fneccE7?=Id#ZY#EQAzW9^riSlA?E|XKE(D!uHkZ7J{|~ zsI2sQQFkld5f6lnde6Fr6lFf{CexK^KzlFu zG0AdbJHWZLdTs384SFH=6xbp-&1x$#)xhVus<>L!?UE_T? z0}Zkrv#YsWU4jHj00~Y1Qtq#{oX=*TR<&Zwq{Te0s>O0@DK^$#0Ka;7mDvw-&|!tE zsqKi^WYIFh0Ub+`Va=R80XMl!P4Ch&M)uZk4rQ0^RpFs9zsh$ccR;L19L_K9c5h+4 zp1zNkYE-%O>fz(a62UlXgG-8F4m8Py*$ah3JS$zrJ62eM=742hyVI|zNVabf)Wq$C zDZpPE@@F4ZgYa)#yBIB;nRJ5T6$F}NmY9ezJ5HajZ~gBbRsNi_Y`L(&+E#3&=e({2e%8iIkM8cK zLjlZYGEVNqYDEaeG*qTgzUChEPK{I4cw}A&wW4@`^?6b+Xc6sYm_6uB>v#4eC8c#F zs!K%(WS@?;0q^?nqJuP2^GqP%-HXbA;z!beA-cnZF&U{6gNmHpsGDW3%gVcz(VGKg zM_c&v#63Bl=ZdYF>=QK}`^=CIe!x&NgFb_=KB0KulGWh z`?J6%=il{|>i4OQA7rylRjYpzC=%cO$B z>c%Ogj?*Yt87wRsEP`ZnNQ04K0V|{p5&-1>y;m}_+xcqt9s)}L zDuzR8&N=;f)rs>Le!4vj%zw4g?vi*~HN=oZ-vtgjBxZkrP9wX2IEmYE{)Zi_{AA*XU~HKH}d! zAOqR1U}kNT@i>pEtuz3i=l+~#>HHGdt+pEBJg{rXc|a z{Z3)ub#p3hS14-Zb)dmoWHS#G07EaDedyp#l)VT2M-;&^T}%pT$iBJH*W&Y?gEDLu zwzTdt?8;FgZ0Zpns*gYo?OAMS`=I93rY`44CS(}e=_su>uyfp4<>```2c`EE%R<&U zi~2PX5Nq2AD_ave-)0vr6)IgcraIwDXP}o>$`AR{M@%mxpCVdg9P=mHuf{k8-p_G^(x8KXb*OQ;mn$M8`fNEe#{sQnulNH^S3jAng zB1PePJ8LrbJnInosc0#}IBKD8bM&9{UB&+(NUJWD%B(8x=Q&)cH4XLMlo>+|@3@jm0prU^$$=d%#<}(?(I2 zg}+i;E#?TK@eDLS&14Ax2AYpbf6V+MlE7j(C{7}7U4?j{01qsw<5Xi7qo9c$3WeNT$@1Ne!WO?0;>*tr9kQAiTwGyVw>9iny)wCKfPv`0W6+x zpQ%YPE~?YpaR&#oVptAZRfA#Tm|-{Qgfw$*BYIAhVOX?tQX)<~#DS95Q)H&o$9%x$ zU6`ZqN7*Oa6YpFP8?%w=yo+?~2sJJl=8^ySWbkhKESTr%iSYadC$u9VM!icEdHi*th7YItXBev7+ za~_u}aKGD~R#8GnvZab)Zyx(L7hV1Wmd>3vmxy&;cN($9re55~LbcYO1mv9F_*K5Y zLB4&{D}5q%EBJZX0t?xh@-N4sVAem$1R~ZCZWcmEa`|l|00OCs4V(y(1yg^koR_6> zNXFR{W1w?7Im87;e59xK>@a|sVJghFkRz(EpX;p%=mMeAaXx*h?@GAifIk78UZmir zD{X{Qug)t6aJb?gv84Yn+yw@2gLA^_pM#)(mcHaIr0~EWo^i}hMZt1=Tsuv1yG{4< z;;YY8Ej5HyaAZP^43VLK2ptYp0#-(Xb$lbJ!L?2vWx^O#Ra{qNGA1ihlmh10u z%y;P;+$YHREm#MQd;uR9XCRfj_fODaU7-aVI?jGk&+r(0COH z{%<90#V(h)vbsh+`4R6CZ)`S6*R`$E9G^w`#H3B zRK+~o<|>xK&3mKXi=8kWqqJB`Gj^-8;K_zgEdZUqEdlH7po2&+I9qH?ESE}aR?|BD zYZGJvm-Wra>{nhOs8OHR+VX?Ql>=tpOHNueue)QNv51r+-@V|?x{^hzc9KC6r&7AN zDV!wZEdM!f!0g!#Udl`&FE@;Rc_c)y;BB}yzvL#6Jcvad{`}2`b$96sI*vu_NKKVzv)YKvw;XQ!+2o?PTUyYiFy36`mr6< z^5C~&3)UX07O7@FZPBJ_19sUdZc==1<1ftSx$`s5N{2IS>)%KqCgpt5JhU2!47UM6W#H4o#V!rjvSD|*JD zSdkEmI?PR8BP}eg>L1FoFtkf}^vf{QWnJXCF_CS&bu=xO%;UWMx;YK%&uDx-9rIFJ z3MdJHLklPdwRVK<#>!r21cjg7Z#gU6Q)-uo~_`qdh~lubHvB|8ef7Zx=DRFK22@-A<@40iR>+Elt1yn7PsxEfkUAfEs0vH?4TnOAM)qRD$Uo_^#6 zoJLOD7YGb4Gx|ui@r5N;#ijZ;^ic84tiBQ6-wku=;^RVtP-(R?7d|FOBEgux7exPk zmAGv^UgQY-it>IebV0lO^ruTwPr^Qsuo04k9nQ7+4Pipvvt@k_cv5IQ-=KULmyB$L zmq1c{!S3feZ@fVFJ+P$Y2ZFmvl^GOmh9R?ikCh_DlsZPyyK36}JH3AjGR#=RJ>6Gj zeNTSBUY<<&?0LKGS!l%PPeenk)Ho85U}?Ixs!1nF*Ce&k!4w^HZ#o7ox%FWa8p2 zJUz9X-KmgY(2cdkPvZq3Ye6%UsG z9_g0BQHPPWON;z7u*-kKHxPsE zNbwp%bhS*}1-V^eaX-v~Ux!?wUe7xGQK75OL^7@Bp}}z zpc_OHK)APnSWcs6Ks>_^=RW0~kh({a@#3{Bo78f}TeqLD7+tcdBIKlBW&0TuqvYnD z6g$iugO#q~8=nYGr|{YC{aWyE)JxBPmS_{b<*PoE6t7f8F^WG^+w&QH zP?2pSqP%mbb5xih~xmpbF#KyuvF zEXfn_CEaJdG#mXY3?!6&eidFQgd=&10Q^wvoyj z3M${!MpDLt_-0&E>^gq*U2z%k!J7xN`#6`vl6v;&m!DPCA2*!KjHL?vr0zl3sSm5u z9}9k%dld%mG^hywK_J`?IVZ`C!pK?^mLy82cqCG)G;`LVv@(}R0AOd=ZF?WzTVA>N!Bwu9vCIli3qS2AF> zoM#_E8x{2GXbQA4%_8f;cNdnGV|5Ecf92}@rXb4%3<`i2OZ2A7*UP`kRT6w2znC7r zk+oN{jk_>Yvh$B&qVZ{?7X(}K(5(7yo2j)H-pM}w+z&B}VoI<1X&a~Xz+^#;d^$pu zSE_hibkZ*{ZC-SzYq4{i7vXBXdaTve5OFu@eZh8x3_IxhK=t8@|HsQ@DFO)tb4~!e zz{Nh8%N-2#YicxH>_zMH7`d>W>5PconnP7v_s`X~0M-rZWr!d~SL4QUFyq$uXNc1L zNlQTO-T7eRJje9ljIpio<*CdI=WhN5>1JU!oMBgw3TKC5#_k+YTnhV-Cw5U4TI~5+ z@$r$EvJ;5^>|x;{#W%(Ng}=W2fOm>p7oA)Gpm0{a0C|PgO`BQ{6<6QwW7X^qvpx11 zAov6USKi|qh-Q*j28R(jtJWVAFlotK*sQh0{{0ldVMP}Q8qwCIFogh~kUR8r*I5!b zRzLD2O6^N8Jf~CM`*(l_^{eT5M9)-K%*SO>1jj7B!bf8V^;Kn_JaLNT-ztt~h9=k> zmnj$)rXppw<;603lK0756@c?*S7mb(gE8Ulk^bBQ?61ylKgb3r6=wkf6Pf=H6Kb;! zXb{jyLP9B)AEx|lO)E^qWb?`uswwy9%l@Xv^w-!M@D{1k)8g~h(IKa`YHKwPROAZo zI$)zO*2HUzbHzbuC)!{;pk4+)LtHCcz{h?$v+Ur10$CnuxbI#Q`c~TUkASEEroauF zj^EfMxJ$_NZruPRBT>UT(QgalNI>2z2B)1#H*}V_rtsQ3^^M{CA~gj=YkhGGsw)mT zRq0RT)_=@~jvMxNGzSaO@@s9Ib6gB1lkxq@Y+J+%f^<7;Eh)pK&9dAqSPo~+1E{J! zkyA`5HQ}GpC{NvcU|+76TJRxMm{wmh$9qCrv)t^GkufKG`>zf7%&Dn69_zv}G3Z%b zU!+e)_*{kds-c@T2#oMyy6jKh*yu^$>R(Fl?TPHn{BQr)?l;{X`k{B-ogbp!DYst- z+k{C;ilwn=x*R4U8_*Y7y8MJ;yty@<3_A@7X3?#A8T0IKt#}fMMXnPRr~emlS{?kp z#R$~`qmuZSL@=XopCSulb6P%GdAv)P$NSCxB@R>&zY%bE*p>LJrUXF}UES>%p4B_g zTU%~lWykL^gEXC6zX!(%^kA!Vk(>q_G~wco=`DAI2EMg2)8hCXOW{x!=C6@sja~Yz_2xBx7Cy0@N?WlAr9Z zL_@+;6eC$f@7ttU_nc|qLGb#_^GgkA?1^adp~QsWkv&x8?I{;coLdS!^At!)7H0ei zO`OA)fYDK{55OWAdmHYl$c?Nn0Q6_vtY?eH@J-Q@&70p|;*Tnl!0(|k+Qy!i*lUj@ zL9RrHd-z<|_y_BD4_U_O&Wf%Kuo05E~z7 zV2sqcQ_C*-{bU7pTL#CX(vZvEQF8;{+_?OEjdl&5yr9=)L%d?R!ITh?c%Cs(ApTNA z^3KE1N3w;zMA1Va{xF}e!H`YBu`BrK$mY6vm)aehB!h>vZw07&B2tD3-g?P~B_ReJ z1M_Bf+giv``F*+>VW@T!f_4tKTHXAp!pPYI?bF%VNiGCJ-Z$1Rjy!@I_nWC72@T`%sWxLgeZF0< z+mI)?I@yTGiFkv!YRHGc$)F|g_U(k>V}yy-p;ng6lkq@yD``VTtzh_s=p?1>*_xzB z5F#i(;Zmfm%<=qv+OT3{k&);;P+I04;#kXlj*BUMc*|0z5UQ@x@M{a9aB!3Rbftp= z*TdG!sLx7Ac?tcND;l}uy2T+rO%2?-jLSPkQDZ*?oPJQ>8^NhV7}TdCHcQ}o=F^CL z-X%v790=97GmkV@=P^;f%nQ?e6zmjxxfmtCy)crdA$HHJiMh34<&b-h;gLzYm2f(uNR+$|nSY z%wE@RKAy(`+WwPOB1!Z2cnSSZa4UAbC~O}(Yg+wlv)#qMTeU19#m$(EFF7Y|-kc;1 z=c8e=AqJ~h{;XE{i4@oNTRrP+bv1?eL|Vr3OI-G+fRBhXPl;EL-H^Gwq-73$5Ul%S zF%?9P^EyeMy5C-8?8u56X#yBl$B?T0>2lg*qL{2C?0U6De(jG}$+o$bT5oK=Xvyi> zWbA%O^l-p&-f?^`Xh*B=paGR>ob-IK08@26ZGG8=&LvZ6cE9-ldUcMR$E$uuf`3m+ zyeTdj=Z+=Uq#b4c3&_CL`Yc4Sp^(}?$b5p4RCS|hSJCQQFt`GIi*64sHqfe4=E{kT z`5bAhzLK|VM(gLXi(`xEW|OebeM%p%tduw9x#J(hAN`OQR)sKK`quxG(^C#79HF11 z`LiY%l8=CpX2iDm!f5#*VmN-YqS7_|QsT(Udrz=b{V&mjJgh^90ygkfXV#T1ZnqfX&* z2#Gc_a6f5jF7F{vQg=SJ0KX8NEJnFk8NPH0UUG=qECGMfuh1tFm@}OpH1*gN(iE+G z+B@;+GR+bjWTNg#z{{{@EXt^#GOn=c)k6lu!oG8BV5lQD9aPlS`PlCb5#gY;RCdtc zn-p>a&fKrqV3F>j9hKJ`nv{O`+2g_)ov4=8>IZLm5I5(oKKSlq*GlApA^$iY_}yzY zwjR`nbz_yT8$7yGncCta^Y%3DoT$Bh10)++O~_&F?XL)J!+Zl{Dg)o)`UC>^B!BQ< z#a(hX#~=Z{e6Aa(r%hD+i#sfAcm$TjIAj5OM7})VPN+HJF!-JnGOlm1$rRBs9Yj9k zV_RIea49ArXv9eIJ?T#m_&6FDmz_*|Ql<&qxu7&|V4&;(E#IeZ*IiO9C5C;BG6okg zAL%gM#K<*tnku+61%hI=o#uiK1H}ebb$SmCk5sN#qFURtsTAH-|NH1^Z4&_QUOb)u znhd^~ze;NS7pQ6B>M2v{T)<3op)d2j*}`0-C0AktrG)2aAUvZcPjv*unka|ax|Yp4 zgBP52MIUuXs}}Badn0TSJh2%A0{$oxBHrn)P8iKYvbOOu$P%K(SnpGj6*$fcVJD1X zbjkXm+B%e{7-olXh2H%h)4j=rJKyI&@S$PRR^#BY&g-?78_?XzIB9r$d~#(oH*a|B z=ITq;H3Tg*)l+|RE7`on7?9!)%9-`+eZh?ILStY|S zoK=L^FOwtu1xD59F6PY60TY@s*AD2gFf@q^!6{>ue;~HHMFsV4$k!-<`>)znqrlAe zBA~M;5#{H|i}x`k7|BtI?Z|z-`~@Gu`J^QnILhm;8d_q0^a2MfO08?$xbLCPqb4;o z@hpQ3EQFCqu7XA+WDK(f1TAM7`*|)Th#mGPb@&PtbW-KX@kIFLqG$=TX@upt>z``IjIK2md0H0I#`dna zSGKNl80pB|2>r(eN^I;kJ|?y9Rd=rtxXrrmZ<(I@*5gP zfDoQZKYSh5n~NzGDVweS#7r3n!^}}(XLb#*LRVJJH0zbA{G?e`NXjow!W7?Qq zomT?f5TU>~;(Qoww5S8I1`H{#U~W#yOGVlG_S*=NjHaSSVQ>>YGx#4Nds%rz>b$0m zU5T)V{@d5ZG*CO$M+Xv2`iay1%p&v@?ilSZ>pVr0zjB-Snx(N=vUc&5Un{%?P4d34 zSnBS}kPSUn$bd}}8sV$~u!DpTVh??eDu7R8jaL4)S>96|xVZr)uetE4mviOH@GiH= zo5g13Dmy2!UZEN=(CBx)IO*Tnvdo?W;Q-n>J@bT*i-{ncdLP$d?V|Z6NH;7Wbac*C zR#`bz%_~KiVViVoTmD6UJgLUGQ%hY;P?N~vSOcH<&Wcazfzg7vfvX!3WR%op@n50P zM^*2izVlHHq;{i?*H+M}I8-V(kl)8x@UkaF&KB;44oRB*Z+-Ci{cd(C`ZE%q8EejS z{RR^mQwQH2!;xdljKUL{zE1$~6UZaB$408a6RT(ED!+4MXZ`Xe+R$B+N4=DJF6W?%PhMq@9^4slc{8~1$ z7eBwBq>619gMi0eZu4>{9Fxz_&uxa~CU7sm-6}LnNn{c*!fB2;N1#xj*lhAh`1%{& z9Xbqc7e9CQdjaQB7wUh_)OFqLd}oK}Q$n{*bmWL_{ejeF0E( z%EeyTn^+uz3TT-=374I+0v`%|`?#USY}9V@CRd=kl6c)9f~MDHHy9@k;|n<-q>zPbR+5(o=vU30S|eWM;e(+#6bV>6$P{}S|J zD~5&!?jDJZeBPaT!jKFGE2?~he^Xc4>ECGkk}?I)eb^vOvZnp)`AbGo&Uj#BJOyui z;2-KZ{SdyzS`pS)Q7m&)qiC0}hL~d8!>TT=1`NG{xn>%t;-AV=oU-5lt~DFzl?lG& z5RPk9W$YGszrLo)GI+p~pu7rtvK{eI1M0-*If2p; z7?VsS^A6t}%BA|zdA+PM{tb0wN~WfPj^KCPOpM4iCFY{v1|#O&nu_#2g+r!!if{2F z)E$)q?dlV`h@TkrU*hintTriMO+pWAC%$Kgq08kD)g_7=f5S&j>bnoge#hXejXrGG zMc7I%5^uu&W!nooAaQV55)U(}2hpWhlTDWDoF?@R<12&zg=fCtWd7zFP^1?DB97C7 ze(58H>6QE~0cd1+r3Q3U_vJPnKG}KrAhM0%7T$zSs0-ot$}^7XsW6-bxD50k*u?%0 z-Va-WZ8#D%?qfwBBZd<3Z-2n8Wo4Ea1GkSe-t*0_xMj8MP1?O?oXIr!Q;sB?Y5{X1Fru9F#( zS;m#%+f8be4{42X5z=pGR*0}%O8n?Sku&B{Cs{i>cMJ)^h^3Lc@&HGZcG4;{o(Zy{ ziBQXL*ma_vB)RpI`97q=$XFS`j;!BT+42#|3(6nlQb+ns;R#wq(Q7P>(~PWWsh|I| z{*@I|`|yrAv<)liKSZsljsKvJaR$Ki{SdQU18^xKAmF5)r4&Kp`9i%;c}9ndB6J35 zK??EFrvCu>(ggd>_amYwmYeDI%^4ued7H`vzMVx}HP(*&h}l$rTNZ#0&CGOWI8wPU zzb$F2olThN8d~!a989>>R4QupKPRDQiBTneju6nBA38FT()u$a-dR;#s8?hUwL*d< z@hnw)ugdQlrNvVi+RJxgG22Y_z}_(ahP43pRj~42)%03=tMy5UL!J+2Iu+ zcXqfXvSWf&`SLH`v}Pv}6_=fHgN;1r(q~AF!9|`5##Xi4&bhP)pD|sQCuv(*q2N$P zwX=4!t3%#x(i3sjUJr~w3j}Q}7T5lx{Rbeed8ngT#=@>SpGkQSvbKejkk{Ooi*Gr~ z`x~mGzACA-o0HowS{Qkl@mcbZa!WB*N+lD;vzyISq3u9E#mG4(Ew>kjah|Wf_x*;5 zXYTf}_eY0Nb#**ZECG35E?hhI`2AmAWjuuNq5lg1^KfvLWP1*Lgh8puZbB2>@ES8L*xK=2Oj=fUNVg zhzW|3k=i_e@}DxcGb+1NrH#)_9m1Y1{3~qvCHb7U-rHyoEF*5Ch&y9wXXY{877xru`hScF~ zr~HKcdhNJh&=E=7VkursL8ECE>9p;7%7Xul?KN!6lXLcGjpriy!vQ1)0W%i? z&8L1YHu6#gpFCVfP76smszm*YAoXJQJ1euMP|GbaE66M>E$HmBeFY@)gZ(t_=Y>kn zF8k=}nqbX;6Ra7o2dOvV%kmj>7eBmoRhi_LptN+DOV!jpw~Pl2m~tXZ&(b3lK_>vF zY;)B4YN7n(V8X{k>tustH;G`)d=qy|E0&Ny_dgHQYK$vos{KvR83z3BH>eQZ&y9Ba z;1fU;$76dt%4NDd9L;u8g|^cYzd|1oPJC|c9p2yA-Zx197fkOPeG`ZEJbl7(Qt(Pd zbAB)Zqi~6RD{JY%6qRmBNL{-rKK4h?Rkb(n^I1j;n{vmeEJqLUG84UYcRhqEg5eC{ zqlM2Qd|x!uSvG`mkRv!>TefaG7D86`r66ECPp#1D!JFrGbXssnXEFb~vF=O6GzRp| zdGrd;B`Ibc|2pWz{d>2|n+?gvZmWzU>CSc9E5jl|4G7bfaS>Bh#?R9Q)*on4pPi16 zhA*{yCnh&`i`s~2nV;jUYrY%{N_f=SOl(*#NocZf3WM9r712K!V0PJd<ux0 zJufujm~LAj>@+FlnYnFe=M$ZvDbWo~X9mzaapK4_BEf*|8u&Lpy@PP%-|RRjKyqGp z!#`g^F{@;lOTd;_Os&XOBjiOx4T-0A+dFebs*7D%LqZ4AYo}kNiXo@FZHHg)3kQkJ zP6x5!DMzbl-Qx88Uv!vU?7QFY^;bsG#WX@LMK!E839Le2Rb@pwHQkw`x*JtE=w93s z+E`)Sw(xDy6M)>WWsnJ+YcxqEt}`effH)jQ&@J_L{(`4B>fSt)Nqyw-gond1=7DYE z?5%yUSvomq9fh-}&BI<;pUY;YN0QDqt#MJ>z2OVQh=0G}AoClkK|h-25EZ5>JP}j;bBD6?(#E{i~CS z{QuhO)hOO)n2kAQ94aHlQXO8OhO$tJ2sp@mCF6*V3qj4Z)IeDKOmriBI==nav>)^K zkh&kC{JB3;d%g;CFUBtU+z|WVHuP5bx8!&^=5qJqA-j{(P1uI-Q^q%S=@W^FTDuTC zM-N6p?UJ>4^#|o8-9l~wx_wLC<)3R==@FTxGuB&x4ZPZkifebOMVSgRRj*cCAw)j0 zHiwV?tX##{$11}b9gYF)@>gH_cVet|1~r=Z8jr!p+>=_*8vUqe0Fd7gxqA=@AqIH= zqH^>$6aKazkve_rT~M8JV?||8sylT-&dSAOJ)iwK;B&A(SzX}NVQ5Lj8*Y4W+xm9b zZ7=R~UE4VJ!mPQN3>vh{1^jRF?~v-BS5z{ksJA-&6=eVkA5rqZ%txi49Gr(egC72)ck9ZT zhgX0k44-7sJV3_G=&*n7lb*rIz+K^uEcvZXKi?1k5kf#y*h3}LH<;!FyrT$_Yv@AP zI`)KV!1^RgFYMO*cm2!)FnIwc@i7Ih2j05H$% zYC)R^*!T?Z`h25Jn15X$WK(ltO-wAxwC!uk5@v_eztZ*iki}4=ab(z2rD*$XAh<#c zZr4^%4k6f5LDYnZ@%vr~mW&CUDJzRx4O;9!XYPeqyAnGC48O@A89z9F4*oTowY-lL z+R>!HW)*b(uqM#CgdGh&{O51XuQ|Vk(h`pOx(Iy?<5etmEx(!tR5%Oddi$*}qbcyM zYj?s991B%xy>46i#honwD2U!&H0xQC=qL%HW!FKfLY1n+SP>z!uI6&c3nTElwEhfw@!U zWSu-*Lw}N?h}fxBO&_6e;C#E~OHce?#f!r}DSgik?u9|?zd#e83gKbHI!r4cyN*#e z%t><>es?Fqkbu))8PSP~m^zH6G<16SeCD4wwu5Uk!WB^?XmSxKLT2$aOO|B<&wa+c zE&&xFG~YW20hSHOnl{(mM#fG{MaoXjLbAU`?7Nys!J0^g26Jz*rJ(PpI)D1ZATo`U zU|~+1k4_}Y0!g|0nANuLUvR>ZtKZbyhhV+2a;`9U`NW{7?Or3$5i5l|9J9vl}`tm9JL2tT^lgsUB6 zIW75VK0CZx4^=t%BENbr@_q|CkyLTPux6hR#HH=5CGjxJlNDMR3r1$7=(_$SZ^%R@ zLRmCU+?;^;5weULI8VN|Wsr)F>Ft&fedxO=yMVYu?7hxV#9GRk^oGKqs!-l{gwy1k z#4#0)!@s^fS*p$MzvM&=C{51+qQZ!d1jBh(tt5ffe`h8h1AhPI(o2`mldj0;87IjJ zx2@1Tvbz>+|GM>Npx+9#^ceyC?V&7026_u&7jA!=2cDI{-pC^S!_#7T@(nKNwv%e$ zP8=9;YEe{AgUl7v{=- z69{KbroW#2`wB%v*_tds-{BGa>t{kAlXl^F3V<10kl4cY?1pFUTC+zDc~Xi6ui3X+ zwEcFZ*%#5TAoJh&9wvk0e*Afpea3?fvb1k(b>D*Y}p6?9xoZ*NN z(S+2gXuo-x{3%}12&XO3TSR;yYJlI?+CYt)Qz4RhpvXo-siYVY5;+d64DpnQz!3-`a4RM_0XX27)qo`P~pGa_KJl z6nl!88z94YJ*sRZL<8ZCmWD@mO5et}6%CKbV_cN9jZC{M1Yo)*M!9yDD9cojfd;ky zVRc~@XfUFA=h~~+>aR^Omr#AU2C&q3OI&N%#OBWj2$jY!l+vS5t(KAQIBE@PJP(Nw zL-YDPL1UBR%TfHsQKx6#UGEonN@d5dt%&Kw3*YZ{ADirbdvhnfV?ua|`z z3yp&Yzkip;H<`}|y)pw75na34yB;e6@O1yz30}X3Ll7O1kI!S+(pKCyvXWJJVVOwa zg)T$vXH;xfw)DxhV~>JqisB?M0bSdT{5<0AK4C8_g}t$^D6NNpBIkJW3V?a`jBMZ4 zy&bn!G=tjz9$A{+CeL(9c}Pu@QFTxqK)Pf1Z>5m7dX=x2C+9{NAaPCE$u zv@VyqSpck3S@eq7deL!ur+(IarP~pcrX-Tq(^9;gBC*udQY&MDMx%VJ?50j3($FTq ztf@o9chNXnt+ZBhczLC1*19&R3!FkFR_#iB=Ssu}iVJ{^SYqEz;#|z3PFLM)O(b^J z1!{|^V?)oQAIjEk-Fbs~0hs&Xe>_!Y{)5Ra$eu8=&9SM7qfn|1wjem7smCAt7Ntas}S0+PqU4s4oL|P z7u}g9v3GiW+DQf6a=weP*`*;+b9*JpbHXzn9~yer?o9=^{*&sF3mv{U(#UX2zhtXB z=OY#G5pg$~(%?(^6IndulG$5vSzuSD@?;z>)aycMcQzp+H|O={>PQD)qVq^@JEgkB zIN~pZRJ3%tyUf(bN-8Z`WYJRp#t2GE5pJ0d;qWdoPxI8rVQPI)-G|3rh@WKS%csm? zkZPrSrn$@dpp7=c{27`N;6zRfWRkKNCw(J=sD4wkGJ~L2D*fpLOBCn(w@-0&&Fusf ze)_^Gy$+54Y1&%Vs8-*EClZbIHmE7&nTOCsdwRUuD{Jr(Y>@y@6 z`d!jIMrr@-et0c#(i>`>%HVPFTr20Tt}2ESs! z=DewUT&8|jdk)Y16b)u-h;61oe9;aoWB&uv@TX$E%%|tjmZ7R$c>DP$b8)Uflhxe2 zGUq&HQeKbE5VN(&mLJAb6z3H4F3o$A&6Z7N3OKL4Mp)GM%++XW&FjG{{e@Wgm$>54 zGG3oal0wfxW^e(lS7d!3ZPd(P{Rq)tSO5`1593yEAN&eDueMr5&x?chZvU&Uk{L(4 z2i*Z0F)0Mp!R^pxr4p`oZ;v-7prf(d^DSozY=Qc}&|#A~T+++iM%twbT=fGD>3fid z7#ECN>kFjrLCvNwfq|i_8HzGMsT1Vbj36;hXKI(r%#<0lkMi` z4DPcv#vu;hietLr^Cqraq*p+juUFM5u*~VMg)%F$oDk^YSkk!)qQ%u!{*^YJGx(>6 z-b|8EqDC>2Q|TUJ(N-4fZZ zy}4xX?CnxU#@Ck2o4xnmA|v9;-ZOizi@Tox^E>}@oX0uN;e0&K^LW4JJ5#fWTxbD3 zMK@cO=p63!Trs=i^HL7cbr}Ih$26fdDD^+TRhUrwc0Aq};(2(&80RT@tY;y8ZlJhv z9vyBD*!lH0P@xb;%Zq+P@Yo8#5v0A7Of51&f0XLj7BFok<==Vv}Z^V+F;lbZ4C%2_6b{Dlx(Ufh_60nzBn6#%y zTY?wzIb^@?VgVyu4ML*`HOCf+=mikMJH{V1CGtdkHc;!eH$M@ z$63|4y7^IG>v5+%eCQh0s$q2^dwBl@A=K7xZHv;4ZX?#n^Uf6L=uRmcmvBC~@|24V z2aUe3#Ikz+TLH{R#JOrbm*#9{o=H5oM1O;3n|^G^UF;v@t7nN{Z7x+Uial;Z=puaJ zG!_?L;Dq74x`G=zYF`Rb=xcyTaR=R%KQjk>b!9FY9ScHnU2OdSa&92z{rMRsEYn4cwHUjwW5X}zK>d&y-_rG1^x7R*W zbhA;!eizuNg6r3+4WaITz?=UT;5vY`vkeH&DZgIcbd3_q3V4kNxnB;1C;X$Jl28`S z9hf_^{?*bQ$uOjN-53{tF#n$V%{aqO@0|X zb|ry@d!f|IG6#cZR*vRYva(T1g=3U2Ul$dhrThxT{kb_uA-7ac(w=#R6I*;Fq&2ts zV-`SwH3xnh?Go~53=O7j*HBuxhpzkbJ#uf!WE!O8laH-w>7iu*68fiL@XOLm*>11T z9x@uMzh!4VVkp}gsXO^!-9sC-DdtuHte`QnAYvKG^OC*y-@9!Z{+ArRAd%jGUy%CP z+om*MkU`oSnTgE(`$QywJvuBm<|zZMniSo_?BtE{*Y6|dOpVLuVr-Bk5Oo*<3A5<9 zTMb@}ukYHla|$B+TjBB= z0dvQeGbOzmcF8c^wJ#0G0XJ5;HK6muf3=m7544o~=t_g57wwRBH3JK%h(FucyXo@e z+KJdtb4TXLXsk4{}Dy-)F9-7Tu}(k{qeN1oDuL`@T6;GdEa< zf;;qIKI-N^s>o82`5XDPX#j%+b)b{)3ywJXl)2xbxT2V`FB|yht6{lJUy)@b2SKt7 zQ(={BpKw%?(3pV)#fD(DXRQ?gL7}LST{4{bya`QZzYlR_#kuz2zZj%N=9mR+6_5+8 z#(mHXpvH;4=lt;knY&`ujVC6F*R`11QzL;;Rc9E41Y=4b%$)pBX!LzVPY=|e-s{8C z+j8=%2lsHln;@#dMSS>w@M58IM7O3jZcUhE#228OPNpAT^@sRhG8yx^AWmbN`*U2K zAhGQr{paJ_SK=q(`1n7JSKDLPwvXO;oe(=e;nRza7x_hLFlB4l7q%x{U^O`n|1eQ} z31K1D0TIoZT?yVDR(NdB9XP)s{QSD>@K-2gwvK00Hv4B9_Q{MxkH9Wd}iv{Ec-t=Z|#Zwc=ewD8!!ML_XV#5g8L;+Z+hN z+u2ENqgAUBPlVB(uO}v!Z_>j%xA?OTT^92j(%-My1O4s-Jf`pj$%k zo?0cG7TdyBH}(6)UpNo>m;AWfQF6iq+lK>01Tz7Z16t{e}DWXE=VypZ~Na~YR&@!d9Nc{$J9k}C_w3o{GHZAWZ&K74=4_!xd!e;k^FS6isKeLg@?wdCOz z2u3a%wzx+rBQXQ9<`n@Ezlbd|`YOC)f6t*W#~rgRo|cf}&EM(dXN$h0*&}(W6Fp+} zMQSU0&*yv=WGqknYm_|&HbrdAfEO%i(&C_$F-U;Z1>JFcXl&xv3m1PA?daT=@nKV= z0QE__!?zIQc2ici=R19UN^_*pk(`WtGHlI~`*mR)HBC(5`Us;4NB#vsfYZ9V#Nn)9 z=Ys`tXgsR@ST=4`ZDFKnJMPjj7)Z(%p=SquJFYV+H6LG?t#9JZb|0s2EKkSY8|Nw9 zFg1wSarjJ8%EX2x1ErLBxwAi|TJs3YHf?JixjCDtlxiT8i)!VvMBueZNQ{{BCAX&U zOn{Spi$uvmv3>R}uq_cnimQ{&ihK=lk{X^?Yoacb+z(=iyMh1SNN#-EDXwj#1yXheO#>qwdQn!@2FKE!ov7NfPYy-H4Qo!-6UTz@81* z_pLjOatHw`-?R&PmVmy55@kgVy(7bRR8fAu&qSq85TtKX=Tf%v3`1_m(DDs~9fw*y zWSJ4qMuBt3?RJnie)wunN$=Cv=Iu%iRg-Q6d2wCpUCYWMz9dxW+qKe;9{0pNB~jdC zQ%l09KPTWdZOs*n{TJ!>hQnd~&H< zCsbhW>88N{QNy>_QWuQ-ZSzD}qsxLcUZg~E4t$shIyI7QFkXIJIWj|zxn$MuZP?fQ zl6Bf;-c&Desr=J>Hwof!e(#D?yD6^3J;7#&*iEAJ&@#Sz?C^SGIXU?ky@kXHN8-okBuBlg$Sxk{(z)Sp z|Lx}GqFMR*{LNy-sj#V8{BKCHgeex^8fh4-wCH~T?y>d{F0L-MN%vCHc%>O$)-Fg1 zIsBx4Z1D2oUEK}{3p3& zw9a5I=hV?${TY*1@{?+P%cy=YiE(AwK4|pHr+h}w*zHJ!NB&iKzk5@i&B9gU%gS`A zB*>5d){m_GTZmn9qdIykUXtUZ2Ozkg5E0}MTiYO|w6S?^Prd_+HOOu7hbNX(mk?u$fc!=5XjY%?eZVE;>AdTTqIB61#`a11m$v7{jDOm|Z!pLCDhJHwCxS(WGEU9Xz@)xI0pAp-gw*tH%wsw|5FEzFhMr~HZ2dYq z{OZ$0dX1Qf=rSO{4qvQAT$D*!427Ezq-JwvEV~z<7SQh5^B>x^VaNAcTT78>XX!fI z>!QiEPNSnnyikM@;FMVbyanDA_uaw53b2SUeE5O%>S5ScZ_pVjzo}Q!G8ayfjSQnm zQxZd+VCea+yq@Rlt4Z5B<>7MNwyB;^TBXCfxN%qhM4CV7uiG1}Ze^aWYGqzmMRo^0 zK6PGEjxBw<3cGGE8roviQ9n8>47$wKBEIxrcJ#Fy35%=`bW-KNF+p>!32jttRs&c| z?9c)@s>1T%M1gWR(j!t=fq`P296IYG+t$-;T__jt{Z%%%Crg7c$mLe z$|dIK!qZ;9Ujwei*oQp$xyPE8%lD4VR{d9;w2*wts33Q=A|o%E{w6(tz20UK{;UvOU4TLw!Td!K=@1)14)4_kC(E1cD4 zlcUwY)F$Em9#}#)LT=+$eD9(oUT=!O2ZE=KIUG$@GF6J0T{W{*60Ni$Ts(~BJ6xH5 zvv8FT2q?Sk^xT?)e|DG>l)G#8-~5jl#>;H2!cIZ|{bGqE^(HZCf#%?0?FOI933O{U zS;+8*ieqYoSDG!nmZ|ajc#;`v{=oIA8aGey-k;>7~hXIZc zG@t(Z{ue7Wq}y6OHyguI&n+cJaT>$nM(gAFpjK)+jOP7 zVkl#5%?F9roJs%by!%=QT9wc8->$}t)VzJlJg^hJ;E^ep}>T5MLl z^_vB~q|uPP`oIFU6L8DQ&HftfaiS}|O|d`ey-Z<$7nv^FJ0A${6(f>;LD$847C+e# z{p909*t=CUjaX8aa^2`JJ+ZkR$3rUjn`f)YJ~C-NwFlRUZhAK@AbdIU$|P^xg(a-! zEr1z^xIaZviCIo156&T!#FMI6muu+p%;hW`L_?3Z2^gD~N&Rs1se6(XM#ncCJ*PE6 zeTW-4D%`LtZ6tTlCo^+kbi4O|l1!)hAkYr{XaqYSXQ#I%J0-WSx;Co5;ztL70?06` z=)_Wni0zfYLoad}ChKu^%^yR9H>%WhyVJ-o`DkeC6hvyNFu{3Pd=?4Wf!E*%lqxF# zN!EdBcylAZmt-THseYjO9y1&0r$j4P*=m=JC)c*Z4nWSFffQj0{{6;$E7jF0{tKvN z{?L9!^<~D2#Wvv)TYcQ^lYk|Y`r}(qR+YeLdqCO>nVb3!gxx1@KYY0N_<=}hTlve6 zwdEhyDyx(AkFIE?@~R&h9(mL9Qqpr3x4Q5cGck^Nc{V(j?67)wZ6r=5rL4@G9pL-D8aC56&e9i(dSDTJr-iVN-*a5&SFE!%>h$&2Gqt{UQwQ zc{_ZPqG^8T;orN=gdttPK=UhtYtn!S3y)POFbbpCaiFq`p#JwAcn!*~S9e6{UX+zG zylg@-4o}*88WOSkWGxB^YM9K47DqBl7VX>ZPyC8=sF!kLgZgK~UvDd&8+8LEnFm`e z9&Ps<#oDCe6}_#aiRaT)T07#Ozx(=T+)C~i^~6~B5|L}o;#S{!2cLde2*uPdtJ8po;g1BTx{Nm zeCFYxZ#Tkn{Qb6K37#d1I_J%(SA4sdjfBl6S>giS$8F;!UShl{G#w)hZ^xxz+9Q|$ z&8*;}j)lw=g1k3)m$5iiOMSf{`x<|k6Iy;Pw*Wjg(Ya^_u9bU{H3-}cYPeFk2n^vu<hu4h<@ zAJotOu3P)w%30`0l~Z*hV<9}%f4gY6%sIwqVOSWQOaIszW!bLl!C}vC_QK~GrB^{! zYIx8I$m>;1`W_gp!V4{b&N`O@#TajXm>F0)-kC57A{u;qRSW+ih-hrK-kY{<_NQHA zWsKaDB=WX~zF6odVJN!IRsq?O%`T_=jNi$yE>UJ(FDDd(;W>>QkVKnU=>iduN)0Ui z!)iolp*=NuIp~e+dr~J_VKeZXY^O@0&7qS7Yi0LbN0hz&Q1L%g*SzV4y{c>rMjF@? zPMtTiDecb8=8#=XUZf~0;*F%1$y6z+i_dv*6MB+<7*<}TtSFEb=z4i^QXmw_fq*$3 zm54TON(-&%YrC|2IS3T3qQg433R9oVb5kjWs`8I;wh1!uNLF_j9Gu|{)`^|@N{31O z?TSAt`^KFwunJGLXww9*fIJdR#N2WeGMU33nt!o zjqNJ|o@Ol)X+Nr3@8a@|9_cv{Y{W)769e~LUEaa{tyFGZG{q@It^QY$*;}Os=F9v8 zqZp^)g$_v{&44sMsMN&6mc1}Clf6&T|N6p+Z-PZ>+a|4{D3KLEvRHUz{CeOHlB;b| zLb-K??3xy|EiuG_X0=xCyBtJ1txqdYv<-zn+w6djmE{g@$(ll=&fe$OGhS4z&BN^& zhc=G(rQY_-#~i_3^j&f_l-Chlv5}2$;e7%ULlC~qtIPJZZrCV&hG-IFYN9YmKSy&Z zYJ-WDOT_QmWOpfQSQnR|RV~|$_pVRSxX19w?aFOVK!?%{Ly9jmb}%eHz2bCumL7Hp zcO(0&|C0J{wyBH6u9Rl3KZIQ=1Btt4)t>IYJ^qhxE2!Ig{;L1};?qWA_z&a0PNoo? zyqvbO84wv*Ky?k-i7mhm_}dq80?UTV!&Z#Q^EoQ?)AWGnQ@NyU!P)lMce3Y%jB!s6 zzZz`?A=m_P1*``UMVt~5mCtYf64<+V!r|1u0A3bLLenF+Je7h3-!qFIMV;I~6VmLT z)u&{A=gXKqN^505!2@a2icYIjqgw}6MjoQfQMV;sbMtT{Hr)#H{$I+2+p?qvmfunv zKlZ2Tf+^Qp%q@ed{GUlu>wwG}t?Qodnr zK>40ta90pd!_D238LBob(^C`bDnYplhYORWMD5bM;?+-4h}xb)x#4v{vy>kUe&TM7 zglS|JNRp0GJ{#8!DZQcnULi-{qh3kA3d*_juf93eMHi zU^bVAEG1EC@;PGTl4#{^+B)G+;g|MYyMETDeA`^3oAFF%2NpY=l>-m*YH~+AyGR%~ zGzm2>M042N6XKOLy_l4lQ#kVm<9P@llxo|#8}Qc-5ApTXwXwxnZltJ2=04;-5jmJD7@`2BP}2AbRFHk)iOGK5!wv!}zN(|94A z)4WZ;(Q?-T1ZDs}(h)eN_cul{Z8=>_9lhZ7`2mM6uvjz>5MYhmf3{1r`+cFzZpy2@ zNu44o0XOaD;gY~C1cYtNKZ#~S;cvm2)~XJSF7wIz@F_z3kDl6HQOo}B1Jga*&sTiL z9(2{%KAsJ_IHf;_UBv9^wmAN|G7|UTIE-_7U11{R$>FpzRhT;c7FZYn<%(Sm;0Ap2 zW=604%ED|Vz4>!0sd_Qf?JwzlOQrTJf>c;;>E`IeDk43}U@4vOY#iTXrgQLqXvgywQ zO}-NC9PbN!;;>)IP%V=TKW06W@YrXITU&^%27JI_Re9xbCtm{cXG?oI76dGjELton za@&VqZ$%QvmVDa|$8Hk=Htt^M8hCt6(Kwg&8w;0{78Gg2sDh<-O!-^6^}mr^=5F9& zu5|!`FJHj(IO6ShAa~QMzA|Qs*enla#4@l*vS-}GnnMzV{ha@tdnVj@HCrW_FLRps zADuJMUYB8L=Q=sgT&Zimx2G0d;+xTZ$b{`HdYhtUSpnSCKA7^?U7hmd$}AOSQzf%XLx6hHp9J+c@Wt&xDmUj}>D_RNvY%{I=S$qhw%igR&x+2a zhz*YDDS;3hb>|nB&koU1DP9sd9#OnFka#kzBoO_g-jk93LDT{#bBvQ2pModjq&SFG z;Io0{#=C#ssh^~7oxahW4O9RPSRqxy6ez|F(YQ7fg->*)5&s0Qz*nkAT>NhQFKm>k_@&VSEsX-0pI}PX& z(+%G=NW&|a60B`M2nGWlyJ^z{3CgnaEOA>mh$nc?lkJRw>ER}I%V#GQz9gpl(7W4nebg4RbfZmW^(e+}!`Z;^DY6uO zV!8C$9Q_K(dzS{yLM#t}0H$$#nF1aos~;t3b7-FBe=E4<}I$#@bSKxlbirsU5I(wXZg`Z z^u)XCIwG5UWFYfU7;0Z7%viYadv=}s5CnGrUZr_R^O23bOY=xmUr+A+IG)lRdJh97 zVgPkDsiK0c9Iu1<-1BkCZlRm)f*y4V-P2Rsx5+y9)xQV@cRjtIC-k6Uir&Bu&=cQ; zE*H2&;QvXb8R}-jG(aaSjS)~Yi>5lMdPz5#Pnk_G!XRY-u}JuRf8)B%5}!0=*8TCd zJOnm95imQawnaZT#qg`1DyxZCnAB!|_>RtwzoUeITJk3}_wcBJ!Q0xdZ{7GLmV-|XKn6Q6s(Ejr#BaaH4-zQH~r!$3hnOWqG6 zA|-_$IAUzyR;4mPJqEh3=w4638+U2o_-d}Tx*zHsqurO}hHHd2{rda9ywjGDyh2Z7 zR_EG`nzBn5R5>vvr5Uq%mkB$S=7U=>Uhc8*EOwfiEQSLuvTWnO4ca}W z;YpjAFWcjV{KetskQ(DjqRwJTxQ2vV?@s3n!#w_$zxSG3^G-~9f^;Wy)dZ=~UDMCc z2v26(tv#L^y%~6O4}4WEkFsppdjgf48Bu+B={0U#^u|vdzm> zgnF~L$~rJJ>-7HJv||6L7bDPGILf->+5f~S>2=~$#mln2`nF(xE@+V_#mW<}6{d+D za_3}!m-w4Ks;;thA?2-!FTMB^6pDfD0=^#?=(vjHuHZJfF-sM#YCTFsPgZW0mF{bz zF7P*WD+wTg^21-$AAf?)e;P&v!(o@7hB3opO(F2!)6JOC>FB=M3LAo=&oza&GoSec zt`eI*vtv1cC~^ILQI{Id8QH@}cP#r=b9rGiuk|@K&5BX8a$tr6*i;mOlh1lp&*HXD zauTO3Vb>|%z9=EiyZz@s!efKGsvH-Hg6bRYfL1QxUa2z~*in%bGlr;A;WB;GGMoWZ zssIccr!`aabJ0kG0|>Iq?1&Jbfc(SASIX#oV^3E^gI+PDY-B70^!F#NcYt>rV=AXX z$6@3Bni3`O6Pa8MJNau;{_zHNoJ~Sb*d8RCgax{!%IZts^IlqH=*o|tnf2j^4O5pi z?}!$EpO&^iM({1li|zf*WJnc#5!QF<4{tZ@flfC*UTVTLLAKgKzwSnk>&%yyxnq$V zjI{}JeXvSw-w~xt(wty1Xt0hFhIR*uBvbh~qz#8nbFCf^JZU4s>ACk;>f<1e&$1#9 zyiJ=6YJ}A}SE~}dIb9dw-(WeWFJ9m};D6zMg9S&epUx(-tF4Z19{hscB}pZ8aWeTC z+$6D^<;m{Sy^uZZl2FBc-ne~Qxn`v8z7w!4BC!gk<>mb3ckci$`?7~COezV%nCGUH z(%eGD2Kq@8Kyu(19A)^oJs$z`x3r0nj-L_7B6W4?GoVDGd?bi^u+GOP25xMq_n7j zmk@hY*p;Z-IUD}dT-Mx7Z-M{q`RF9#s!;8x>iSN^^}5@>%YsqY!5kn17vq(A;^Ka$ zbg?WSPPPPyVrK6!m$J_f)cK0L_0tzuTfO{2drKYF^h{T$CF% za4h+?B=w4woK2>EsXkG+6tq;6lmhpwfoBTLo*&NIgWw;(=TuoMtt3D30`ExSZD)jb ztZI{})Umod{OL91SbQ2zb`9AOEM8el_w9CBvxRq{)%(H1dJZ1{`DKH4zkfx4p%`aA z{eZ2y(x3^|Y=74w%8t!x#~_n{a#YXh97^$l35c2853~p{E8m5LVQ!UffTM{vksI|q9Y(}w`PFm%c%lN=t_ETn>K^D{Tc3!7wx}rPH^4ICI3JL zKI+SB0Q|uDF`z6}F8p{8AT{Ziw+=WSgXqn!jyvcGf@}2$-3!y%*<#cW%DFW3rcE_& zA*w1%__}0nVB)TuZ1Ss!v%E{$6_3zOH@UG0{W-%$ggVu3L@%0F~yyR2Qg5Y+|@ zocAHifm_1oCsgj&;EuF?o39gpMcQl@RH=_6P{hZCSm@{>ax_gRbU$kXaT`z6A=F54 z{RQ(Ks4@jMs8x$gKa4j^ay!6=(7h;mz&kOsbgmwG8rN zb_1GhXT3bt~*$O z5GxYOgVtJw$KJVzdwQL^h6(AqDi3Jy+ge$Vsi;M>bVj;9I18GEjx+xg0dG;?X3}Pd zoEFWhl)0dR3Nd(-cuSu*>kF8aP^iTyQ7G@~kT~Qb<$e(ZMZ%&sE{DF6yZJ4<%{5nS z&Ob_r-SgJiXiW%rYe%c+^RCn;JKw8DOR0KOhX8`e&V@46lJwE0RX#c{HKPJJ;aiT? z1z!%qk%?ntqtIvH$#2nJprDI~KA&m)&>R60(o854geduOAxoQZjrncjYD9kc=?QFChD0&At11E;Zy9-V#*AElf56t0kzIMr;AYso+01dZq*4@i93+>3Ia+z1 z#z>TXUB{xuMzN*{aed2T4%~!B)`md#A4;#^`bscQUb{0$A27<(PN05n7%Itt9vFz2 z(ZJ;&894wqyBrRH0Daj+X(4rwJ^A{_|3z-T9&4h@6lECl5ONvv4&JN(+%#S@<@HAV zmZdkQd(LgM%DL6EbCOj<`BU-<5rS?X{O!!M8h}?#-RE6LZfTlPD%?;_OLA`kjhb$y z*O~S|@n3R1EHi|@GyesDIvo+`g3Mr^f}|3A99hKvz&i8Zk@f*^`*)hthf@{Vt~eDC z-!M{F1IrkdeeB+>jMH1bNnKF^^sRbg^*+3!j7X=z7T21U(Q5if^$tJ;QQaYP$hg0oH-Fr zIcTaWf3cSg4^fXO&D)?SV^T7FsVq4!+}8q3%raDan^fwSgA@-|&b*0!R{4{Sc%}CL zP>YrEr7*h6!9Mwg?9|1#k8U^Jz|q($_zWCBcMK2eEruImsLqP_u|=|YQt*qgcAO;V zG@2-bb4ZS@_=zO<9c}Jl*1v-9vQy})uLuf_z{CruB#a^(A(yYUZ+!oSXBI=`q4?~& zJowGX%+;ty5Bjwgi`l^%+$Vj2%HM@}=2xH?eub??_U#(qzpveTiA=UmWt;Ep8E0;} zsaGpdyG4?*JYZ9=j?yL8iMHhyKMW`(A)(M`9DAv?Wmqlqxb54Ug`5Tv!%y9<_bSA# zoZy3cH|BT*a+{B{IPlZq{0z{932JM)rLgSXVtlk5aP--f@Ci+r+?r_*{$Uv3GGC9~ zhd6iKKn3!nt!rlq43?@8t@j-byNW%HzkXbNuW?vE@M+m>_-kOO`y}Der^%34X>XA_ugqz# zd7nj7AN2~n_^}ETBZ~xd-rl{l3Z$8--9O;yU@!Xpao#BmH;}$o(i+srSc^x`l{M%( ztQ>XNAoUDY13j0HV(sg0S~qIjat--hG)x>8@Y+9`6{c3a&JV;YcCzA!w@3ffx|lI*p1%QJ6_5x;=St0kyY$m2>ABK-{9fe?z{8cK>|k z?TWLxI>O3y0?FMu9l`gqr#q?vSOzrg38L=o0%$KJ{@mle3P(=1W;z-=Bi$x<*8X{c<0fnW@_Z6<5nA0{tA(QKfUo{ccUOjX z(!4dPc=~4N?6+++fwnT%&z>BjF{n!IJjiMh~}NUS;_qGy|PF3hn$@s(cBrCHi+8wDORB z_t_Z>E2yj@(w^a?lqU5pDY|^KRYqW?2VHSb_YL}2#As?cwZJ+Hyb9`gZxXFc_ti04tcN&8o3C}c_dmeQB2L`^xX(;X)HybY8!5|yHG zkJg|x?o+j4hw2M)UrT~#U6^;HnsDZCPB*%RM9(v4hWd8!DA(>9s|x z8gt|R^T0 z*J&+u&Z;l)Tb~Qix6X4~{s+AR@qSEG|7|A%zj*nhqrj5;`1oiGyOcEu8FfO7>~D}_ zRb9jaaBd7~y;*%~MSq4dr45fBb26r(~ z)s^4lGd-5ukY@*mx4*$5+fdXwz6!_*={D7seX>%)_No%NPjLV_&fo$c!>cdP3Ywkv zb}vb`HN58Ph0?uFFWbXm=v!+m3Yp@XvOVUXxn>%Pzlhm$MDdl1e*s zpt;_MM&-bZE&Ru}%c~G?T>Qs$vbq+tucA+^b@XkWYS_x&iCo&uq;BpyTxv0NW$PKw zl*9$>w0agdsY2M+-Pl$eOKQoxfs@981mNW?{0HElWQib#Uy`5s2VFYz=51l(*nb|M z-s7;@QzeVCU4j~L^q46+neOsh^eP>8I zs*cLo7`W+fsIJjsyc$cZ&B4EZZ+vT}O1qYP->fT&=90s=lnPGGu@ALZHMx!3prtMg z2CAT+@M*ymC(t(rZI975nLO|U$rn76%T|>OcG>sshlNEBtHZCYW@o>(#xiwLgms1- zQk>UuH6Dw2g)8>_fY04he07+8lN@;`m#gU?T;Emw{$XN_4ep;J5BKj$%x|08NKN{J zJGf8&@txs!Gsd?@zb`z7SPd~sT;nHvFAa@kjQ_Pz5w1k%1C2*;bKnI!X*mQJaRe3D z54i5&sy#m?XVLAr9{{B_axl&#^KFkl6!^v-D!H7!RM&CP7jKuQ?63sdkDk?E(PUA6 zTi`SBe)KI&L9lh{Jj>=i8(jm(mc-~wtfLTA|G!}K#D}_vlqVvt%mx_`AKCXo?+a?F zb1FNr_1ER(#F#=Y_a6T&K;IG+GJUY=!=%q}<# z_uq&OT)xu18ct%@=~@~y!YIbKqu++KUDj6x9A{%|x7=WgK_gsA?l!@e=7$69@>;8o%$UaehVm+*v{q@S>orS3yZ_1$%vUxm8_-Cj71$+?>$^21| z_^iurAmnQ{A95VRCV8K9F1zyUK6de3?W%E1(d4+k2hVaWu1|!C!>(rEc+QxT$Me)> zS<|}{v-Y9l=309Qy8gsGy!e)@zIsfOOggJCn)3x8oX=$w#J*4B!aJ<2X+S&tO_Wi^ zY8Z4Bnz^R58O!r|S)-1`{4aa6Yq83nm@4OLWh^jzZHN7x4!k)aZ=GcMER-CYEhRR*S52C$p}2tE}#> zSSzRqgNkS7lIiKs|L|Jm7^pW?=e%+Y?T~`1&sDPN4-r(J$CrNaH=WZ4M4|9Tx7Q~t zaJ1uTl6-KN1INGX;l~mnPD6Bd9Rvi8_*1FuV21JAD}d~SfSYscS@^$H{2N9Tqwfr4 z8{9YKLvRfoXW*$hjGX-(y1JUbFInRU-UhE|dzE4Tz2!Vx?qs~)4}rh9IKGqkm}YC? zdn5>N!H}Sa$XRBK>Y~J1hMa$u-BDp)Wb`iatsFZx#p!k=^xAx^An(?jb=4T>sNm zQ4+Z8>YXtdu|*7}62jLOx)LQIqZpDGz^|h9GILd^o7K7bTl3Axh{5sviGKb-vb!rU*}Lwt**?4O;^MF! zu@g8c`jYliz@Yx)J8QX+NM25Z>K|n(R)=ilR3;1oZKVzQ1b$aON(VFkPic6b@l?Oo z8$}|kL^;G&->?sGxwlUoREsZChbZNqr*@FXI)}Ep=6dVg>fQNFC};RV)D+{KzoW?e z#rzg559oyFq*5J<>A6P$xU{zdb5tO--U24Ai~N0#C(uUaee~EhEO_xg%e4S(u^?FypIn&nl~2x{O@cUvP!V+wIXkOq@!- zd{D3{jNe?I@Vugp82%KuJsQ+1v4m_wDB#r;Jc7m*O1r{gAYKwmdRig(s4}8AM;%zx z-`=zr=DXt^!z>AVx5HHDF3B<2dn66>(2xLO)T*W>GnE*eV@hri(2<8i- z0)5%)n1vrotiNs|ap4Nxn}zra%52XQuO#Bc>e|W*zHp|q|2&P9>4=aV7(KfNv25Zy zZE<9n=dA2~G$jHjB4J!>6l=oAzT`JY#ENG)Qu-rEa4}#u>oEx@xDCj}P=nbT9Q00# z+tX)2>!z!0fCryW`OJfe?2menW-)|mebxg5ThJKIVn?@fK zjvn>)+_d!J^RLwPfF?E_G<#iM)-%1+P=g;s#%(3_T91FhwC+fT8|FvgIKE})0r&W* z)!1u`yVk3L6U(i{uAhCMZ|l~9+wC`egIQOJlG1)reB_y+D3-@X^iYU>%bHYp2RQyV zBHF2Xg#7^So{@9h#F@BF!q2={jApA-k0JL00J~XoEIl90c8MIz@99|~w$XA#S9;WW ztfD;8Q0DTCYED~wb_H{D8b7&6des6X$Xx&WMF?2RJfm+>0O-@>RSIdffZRL3v8#Qh z@Le*+5UcDnQ9qztN~EZ0f9tk-TWPFpe6YX$FiW*Bp`~ZV8={PT`Dxn+O+yddAoVqLxmNfPkkb$5=@@VIlS-@5001x%sn$T~AGI0$GK2_>1AY zf&aMK543RH!?4a*?ly}qwOC>Y$}H2NeiHR8S|n5Bl{T-{#~dK7Al(Kx2!*u{eymce zhCib-t8t<}xMabI%tn8793^+ZT@CEeb;JuJW$={e?5V$hE*mw~)mhl&S^O*riPkex z2k0bc=V#lC_CKEI?Bi(pJue@bo*2`$Pfp8uO}AI~UVjNyfm#SVCuORx z9Qe&S-F55GHL6Ma&r-s)?bDCGwR(@kcDL$=%Ia1J?}?xLdS1q$v3qf&#qBnFre4^j zMLST^(w$5nA8bdS1TZ~X zaLda^CN~T@IoX-jZM%ROmH2Ssysgl*S45owg4xT?)kdRqWCKMcv+ySzdk{WUH;iXA zC3~y&9A4?gcOfilig)+UthjxquWtCx+(k5hLe;%zjAY4ZD16U8=sg_4afi!(!v%mf6epd8*#=RlQYroy~v9Fcs%2mDi>C^GP zyF16y>m|YXN|uT-7zwT>^*zfENMYK|eeywDYiVOt5YY_0o=Co=zj4*Wt^J&{&haN* zbWVws?_5tbIgHNn*s!s>^WS5r|J6q0w?sWOeo^X$lhu)p2>ggb&1f*_n}!LUq(eGh z*49(*q}>0x(dHlo%FjrIzwMiT^1ifsEd1l^vUiVBb;H9vXa=2=4HI8-<17Q=la-B^ zBX?tWYE9fyM>7a;61q+q-5Am&=VgHPM6Zh{ZWdpe^;7t4Kp*S`42nz5$}ACGjVjUU zXO*X8u$IuuT0O92Z1U8lPjBU=S{OZ;qVn>Tazr|f`Ioj8&FejCAHUi^B2(-GEwH0x zLbL=x(aSGRaV}C1(ECwL3oMltXGjBI+XQ9)u3sdBxd<3# z>-LP1LqnMvFgKrP6%3Rg4tTN~3-FFK^OZfLB40Aj`p08a6h7@imp;UEHDA_x`Q@?6 z)%^AqD0cDYF&(CmDC_Bu_v9n(6S>)0Hw6$Q&-5NRMj7L3R&MFVvkl^ES-;=Ar|3b? znpVziS;%c_miOodKi!v$*I-4%U#ro1+rf-8`KFTH;-9X_U9Aqid5VMwMKgrXS_wt5 z*yFI?g^%55Ko=>ci@*Aosc8MdNuy#n;CAaI?pkEQDF6m85@I*Y=)YQ%^ao~DtP2N?n6G>Lo!b47P&L&)JB9X z?$i7|-1{8_dq_h%S9lsNf$Be9@vwiCB#1D&GN>?pfs~A&H0lWt4Zla{#bfh+T&4=~ z{rKRXs#bkA=ckL8;|$e^>RtcdahmicT~!nPd7^nIb7PMW44yB)yKeqL<_{T!XTb!c z1?khqKd&2DCZ?Mhsb|`%jJHkev2)e*lwuxJGi6Zpoo@Q1W{OY@L}V!ysifh?LV36uFSJjPtqH^ z4=BA{@jo-+q(6ipb-7jauVK}{afmqb_a;LA$SICv~%Q~!b!17>pM^t7ZVLu>CvE%rER$iX+zm}TusQr zmS0pp9|N>swOMHP^EC>6Up8p2Ze6ea;>5`VA_)BfRQA^>nO8d@5 z%@t!8<^Ka*L8HDZvRyGBD6=FKW%Os{l}{4{nosxxe_Wpa@i-Bfk0kb!VC@SJjM;4Y zWIW{Yicg+d^M?m~0H0s;vBGE5uU>xsSKAcg>e=bf1AmEScDfVzOPu2ao&S5qUlK>B zo0eYjC!zrzR|0%g^j2T`N~phscKgyz@&HHH>0r8Pa_BC{nP9qT#lo)heNMKaWI@+Z ztCQ_%-MjbtV9UkJsQ-ZfX|;Pit*suqwzrD z7T^#2k3LxR!c@^Z#sK`Mie6$2;CYxvY=C?@gxH{k{U?M-)=DFO{&!z-vNllm^Dha3 zQ6!Yj-bV;zvIJVTk02<@K+|7J2o<%}hyGGdI4HLd{d+(?@GqP!+r?Hv|DSht6gb&} zlFUn84NlfxVms6~*iwH8dc$!`CHCuQ8VU{#F0?jR*5?C%rVx%JKV{N9Yp#R-SUB(} z--Fj>){Vp7qeKj&4u<^%P^Ml@BWg7?!7#W?s|VELGT46@tw3fxL3oL4F#+m7GH~c2 z10->rmi`flVwww3?CBsXI9u*u=&YcP|?7$8Nk1) zrC@h6^lk;-_xT(!nh+O*l;^+F_#c#jyXd7)FV8aO@A)f50&t>OX1{L;XiB z!}$J#iMZ~AkECdr7}tN`g`HvlLByhjxRN8rQ7(#5OGKDbF1kl62MiTiSlE9;h&~NJqq~JT z{5eRB=KBx9cOQa3zl~d{@FBds--&vdkJ5~6rsbFIP5*g zq)rN+M?exV*%VJ=QUbG>3}B;AV6zhq6#QD2q(}WnCefjOHNs!cc>76tPX3O23ma;B zJf4P<5>G8+fv2Gc_N#&m4V9juz6)xTEzCE^{6&Hd3L0iv4%oVPmJkaFbGJ)IIjPgQu+R~k?%j<9XlI? z7F-(WyV}xdUC=e)IoNujGOzk#>%pO`eV3|xR-E@-^9)t@EbIjS*Z0(BZeFpXfA5~2 z%(Ruu_to#}PEL7z`76MmNqHpq73BY*{CCpEbbtAbdw&<+80#<3U0D}b7ZVU}Kje-o ziw#iK^qofB*i$~eG&Vq4U2}RmgZdTpm)z`6@cv@xuWQo-rZRdrD`nGxznhS{UaP6d zWeL=ORyY`z>pzthUG@794)tEV)Kyz_$#Z3JsH=M==iigLxuk{jU)bE(u&diLYie`d zeAfnc*1Zmwxz`lz`yjhj-kt(e<(Zkp;!pS&mzKu(MReG@mU7GgqES895B4jgdY&)r zSIFP^LO$@9DEa;qLBA`<8O_W{)B6I7(b%V$wS=Qovv9#_mVy1J__T#>ZchfxuN!RN zxNO0><^7)aW5u?X<^9k|G3iB(f*30`? zfB6%?)xshPUm78`e&Ce4pzEtUD?dsVA4Gk`j5xl zNzgx-Jeky|RnH3|PsU#msSQEO?W@mdF^zmWyEQ|t0mtvA?TNa0OfeH~tylml_ZsfmkXLlp#KdZ4X^>}8|%0%d&IkPyi-`;-AVq4}q3;i>f zyUXNfSVd@2he6)MDu91{Of3}#{Heu&59hNceN9$yT!+QFwKI#J?zU9B+OlLyx3$Yv zI+r9}GtawLfla9^>5^+zIz_sZE*TF40)N?I1FhVy?>4T|1Wjl4HZ`O1jY~A9=uBAH zl$k~*s~iinZm!li&uD*UtGT3aI+MKIR&}{<@J#zM+x)&dPvx;E zlYBfgWf{|$mVC@&b*|pwm$|`gDRh@hGTG1xh3<6Nept%VzL>wOG^P|pT=K^IBW>v z`%lR9OtxFs2Kp6ovyYkZJdmNs! z?geQj_N5JMcjl~>rnhPsz+$%1#&lb3d0TgcG8=LiuqVpp$;|x6bKPdZg2#)tCkc|{ z0gV#ae`cG2f7`lb<0-eHsqF>Ec={B3r7hl~J6+a$r7a-@`ky_V5X$){ghGGk;RLzt z*U&#+0sPNozpqimRkLU2v}pq3HfDbS`%h%%(siHJY812$^&bWBPj6aoF#-RwmckBG z+Wb~mLr$kHt)!r_f$g--TA2&IGt-J4jhRe0YX|hTTpB^0QRa3@;WZRNcK?xZmK<8{4fKT1##r(Qe@{1x=6 z7taBI1z8h+4*Dy5+^30Fq}o?%(b^5QhM z%EcaSKA2|AaJfF%eZY?T&zTO}uDVm5AD(ep&)4nm*pR`PI~~xU*;e%#^d~-E_t}M$ zLgatoeW8Lr{o>hWfMjj_*@*WA3bMz2E_+Raf&yIBmL5PI`+Ub+9WMvSEzjp(h5g6$ zeC|;3xq#3~3zi&Oc5c?p$qT-+F6*_=e4yZO)&+I;v}yA{vn|+d<@_(3(u#BHGV{6} z8E@pA56-J}=2!3Pa=5CU%Qo(+u5-6H9@w<2qPO!H>_0Ad=Z6=2YKN{}^K_r#`%gw< zuB|_#k+sCntNJX%Q645pKXT$;So^e~6bTuq5?z*(M(cRN>sPa>a&VKp1+1nJ7jk67o*?;$!B+pK_JpHAQgdHDfdG3m@gl5x|>%6${wFx3Z7DFWW-?M@T$zjVEz(cDu~ zbI8-uT7S8O^{m;+GMZ;I;QE7OQppxy*ngx#wGRfE zB+$VA11ZBaG?s`X;tY<%P5?hAM+VOqV=#eC_89?g=g30t1IHP-Km(F3*$?gjU zX`XuM9ZEEt%o7|tLWm|)d9VZZpEBCP68K{CRzM7+BwNstBPHOX2afs)#*d#t{}f>w zNL+;Rork;)NkoDt*MCSI*MF3{Kx{fD5h*FTXu4V=Q__=R{{g%Y_8*#M?FfFCBb?IQ*b{upHn=o{b`0KBTvi{CNEbUGiDYd7>`G`*HmD z?wy-2@;md!Z~wRx>;R}OVsP9FDl33WFEzI(iLSpR!$=KWWkmd1Cc;QBZ`}Jg6X%x* ze)BD8;(O0+$iEIq0qj2{K?;VdijMH;;>Qw}RI}#lRNS0v@6rd@w zj-#Yk6D1Py#Bf&diW-vQyN{P}9MVXVH;CWhjee!$=1!nP{f86|6G!Cx0}1;BMKCn0 z4~(OH5+kjV;c!Hk79r3bOWjMdbX4mK(Ha`P2~ zGf{>Yn)}n8Nf_)u>5C*79*r+b*NGA1=Kw1u9)&}a;9p9P;I%3e(1e~u=h5-x`j6=L z{Yt?1pV9tOhM}OpG&w0U-x2=cT-(fLeGeARm}i?=+_$3W(Og@~p3C(+@5`|aiIe|VPlQZMdH*0%V zdJ2l}+uu;L_i{t-1G@_U?5f z(X(k|ePZsNlWRy35iye&8M4G8ajblibg`5W#)bfY!0=$;FZCDFnN*ZcK7QESa zd4uxis*fT6o?jn>{)Iii+!X!D zoLp0tHWm8UnaB9X$fLlTHBRziXjJ&`CXSO#vZXj09itbJdgxC{>Gbt3lY{s)YTJuE{YA@rAol@o+!)=Q zm20g^PL0mZN_PPNXmeDcGku)=!TC|)&WYpXISWCk z6zo^PKZ<$Q_hx?*b|B7Q0{wC5uV(Z(sZU{WmZIqNO)djVQ0zRe|5VJoaG(fmaH@9> z9%!kkv{YYgIWTmd?^hRKzuMc?(sJ!ubM2w_63>;^YdweB3p`CF*LwDBe7HGherJ^> z_2KyrbFVqr_rZ)Td4Kx2pc(VC!kZ?J3(8&Th|Y=iS3&mURUmEML z+-N(E{Qs2FiTwYZbO!nVGN}sslTXH5am*klwHg*j{RjTdOP^*m7)6v;UyJ(Bdi}2F z_Zu0_R9V5obRo_)LygV(#30op7xqUUG**31~=3~?<=hz@cx}WyEZOs z-f>@NRc7k4dRBhHJi({1RxiJ1@S!K~)yFhX97j(qW~1w4$3^5mPb}&Q_nB_JKY3AS ztk3l7%=L>(V+r8jv50w=fc`o)=MN|$fxnvf$AG_5yV{Jw{zI&mV+5dSjeunEjC*pm zL{_OL@0oL`|12*)=Q1_5Cl?;y?Xhjv&~lq+q(~Sw6t8gI16}}3|?vYpr;wI z$^HTKZ`u*sS!GKtJa3YpF^BmSbs6M6CV$zC-wI-C!~JDTp2wqW!^7^$d77Eiqw<+< zxyQ1oGn$xgnNYo`G+LxwAJ(;qQ2~En;2$Hv{wx9hF+$*fMy(DPlD~-W#4xE?xkhse zY-c6Y8NCT3aKGs$V?3FNE2fxX|G_6LIBj8^A21IuIMu;69ZPoZIn_}&c&vKao^zf3 zo@3pITrE{s`hb7iiZfSgkM$fny8J`vzq@+b+MLktN_%Euhgn|BDuN5U(jmvs_-%Z6 zEfqF?$uoEs;5|8(MBU~rpXqMapxcl|0J@B&St4bd>7=n#g^|hepBmLM7`8D15+{F| z(4kd_T|h|8i_X=8LHRJe*l}N#E3y?942` zTsPRWaam^l<$h1+u|pLt8CUvD$AQ23N^RnC;Gfi#mU6tl+WA6`->eN8na(z|Jk1h1 zwFt~d8XJ0l(XSGvX?n%|MYF~FG`;Pf9LB8Q$RjR#$V+U(WRyG3vgU43pHZ~+4KiFPu zZd{mhd{=ee%Q^SX+LXJ1Z8Ha@Cg(n$3z*Eze=K)R5|ykicq~^d(We@%v)Qd?eW@$i zXxM7l*S3{0nzpk2ZF*Lh`0~mAQbP#20eTxkIe$Ya*&Yx4XVn z>NHuZ35ZP2E|XQN6~NzYv8xqy;(>X2CB_Fr%|ov>udpmkGhg31Sk$#3ZN6uxC#QS& z=91RNK0{B_v6cIq_Qv-#9WUPBv@o$}NA0dx^Yaro6)tprmccT~g~jENZ7Yh)x6ITt z@6UhUtV_}}C(9~Wm$}T{w$^2G8JgUsiA;K#{t9>wGzn$yE3U*a?1d!v*)0MER+`|h zTP0ACfDXuw@uwmn+x4d-fIrnvosMeL2T;GrE}P!DMG?dS`uyVU1R6ew1 z@A3*;ntZ6Jer1O}ZT_L14GX&)HkTY~Y*^USd~9V))83WPzolv6O6cF5pTBUEb74oL z-QimAT-I4JFH;n_aH=Pj{GhxlVN+J>oL$+FIVRK8Z=U>dnx9 zoArbl_~S1po|v>HUV)b-oQPZ%ub|c?xFN~S&>!$P?+=Ll*8=~JEebjGul`6OH@%gc zS$r}qH0ZZWY|Gr%H2I!q?Zwc4?_B$WPUye5fb%Z|-p$8~5qH#Z{>vA3HQJo6P0Neh zdu@&GW6cLQ^j7wFwqLkvs&lzJkDlo+AG&g_ulvKwvOT}A-(3m(ZTrj)mer(Zd}e0N zVYngb#3V97ft!Fo2AGuaZlpS1fxQ&}hX}|G`ajG8{y5;GHTnR2?VOjF{%UK0gmI+j zRe$CWI4^TSzptNkA@J`{Nt4@_*d9J_Pn&F;YnytZVe=Esix*D2up9UnE&N&EZs1=8 z{C5NY`uv48D;9QLt#O{(1jo-bG@j~i-CHx%0{hS9THxK&-P3c&X&Dd7Z-X#nF-$kc#|`mIVW@MjJu>U}R0+S+t0t*tp3;YQzN%$`C_r;O~tAW2S>L*%_FU~+3d~gQS%ZxAk z5Da0Ujj#Gh7&<*T`wAfeI~T!A`+XsO;`)6F6>adD(gYZi<$v#$ka5n?BLAPA1OD@i z!d4F47xu>Tiy;g5mjM4W&K=PI`bB4XcR|e|&tPl)<=R>g^0uc9R_!cl9!#0pRQcNc z=G_caX#JbF|CqrB5cVGd`JxE;ufj1viExz&TTNgRfm()X2n_52L4qSK*na?F|Ix$0 zBMW4*EJ8pK0veK{1HB{waTP7~ku4VEsvycg;)@`WQ!e+P{u!WI9u{}y-m!0(jwO4tR$Ug=TY@bB8ZcXxbLy+yOri<>eqJ z*MEZe{v)`#|BUP>{MjZb3BfLcdJi~~y+Isy0ze90M_Ntr#NoK5F)}q8zceO77l=7= z$(ZR`a*fy1$|9nIXk>02uC8tcb{SM{fFZE zkBA%jK;AeqzQc6KbGbx!CeD*W&p87Wu?$X#G{Mjl_yqI5G|$mJtX~-iC>J`7H|2P5pjfDouqx1rTM-HIR!ubKC591#Em#!H z#P}S3`S9es&kZ790fzJ4$J>9r6VCr9xP>@Rbp9Ifhy6!GvJ~t;2@$aWNPQBrQU8H- zLdH9+j(L*|gob4u=|OrxQ)9XbY$qJ1MuRgRG2NMf;STA(z(qm~Y?tOpb>Oj-_#)VS z1bqJy@cl>N?LQGl*Qk6MaX2MnfV0@ucL&i9h=!BdVjT44& z>$L|9XHH1VDe0e4G;?gK(X(T~iTXz&veQIi)1W=TY1l{^adA5}<{Gzw8g zDW&6t^aLu3RE>lEN(srJe&vHP1lO^&;$c$IUn^E4f3-l3{MCd`KvG)hFO3Xb|8jUf z4g1f>xvfDDKCqP#qqxxE8XD@$QCuu28}fJxGY0q8G{b(?(sit` zq`#=>;-A}dp4bQY%TnM!*;Mr;6FqrOpu;>y94(IuT%7JBj1G+okD546s0vd>E5rST zK~t$HI>sLlxyPWS!?}J%g!^L2$?+r}PGC=_#FJPw@K1!qA#qHFW9s;L9QHajqrp+X zqA9Rzu-+w&q*d&^Zg;K&^`G7%2kbw6buD{p^0$c{KxqM??7j|k0j>4sPMRn<0RqJRMC;K z<0x}69TgNa4)z~q5coPXGf7Fr`jDxqfH4I5WJ)6N76WfcAtdk@B7ck$W6&R?618vu zAR%45-9Qr*6JEJJmnG=rc^BS-{UQ~E` z*L&JmcswPZKFC(Uy&E5H&YutaN!)ygIo~|N=RvzlzC7KBo>8C-e+2fEm8$4_W5-28 z|BRS%k=FZ-Q6aHDs?5yNDB!P5O$9{$Ymxs`iEEMnQ;CTf^nWrw5$+UWS`7o3q=l!g zil`)`0c^&!R5|QFx?kvbJYQsF^uK`pXS70y5iEs%E5tlTfMub;o4wI?Vua@HyrO7>}VcrwIA=P zuRhR}AKG1O&vafe%WKVw;KJ^7d96tyo3U3AQyUW|Te1L;w#S6slQSEi1N|-I)jDeo zF+Gzm)iE(5j~f=KV53X$wb_657&RPo-qUe z4}gD}%hYttQuvPBwd2aM%;lHPRbCl5R@35csk(L%`JeIBBL5FPY0!Vy+I+w68hfUr z!z{P+{l^ab&#wh4d$eNwlAq&%A@}5H30>M^pXqv$T9>kzn9dSwbj)IrQcJwAV^kvY zN&J1C8oV(+g|C4mpTgVJY84J{Z^P6Sp?s18#EI$2lm_?{(-Vyv(uC1dBt}hEIYv)S zs(}3`ZfaS_3D|!Yoa*Qu=&4?|;9O__U}txWt3Kn}MN`k9yWZ@nO#=SAlRRlNIe*_- zHS?cww3&luS?;?Z_LCI$zWa;Th^dstfLcPIw%COHQ?r=}y;iMD&SD~1Myq48L`sGM z^O1#-$r|7f*6mb|B$^K#ha`cw@+qp6)Z*glsT6}TxZiXp+axn#p;L&ZCbk?44URux zaGcgY8eDeilcv+j%Pr+Y=LS!2TxQvMePFQc*xMB?E3RHN9lzSqk~`Fzbo^S!F7r^y z%;P(&ca`PeJ8M(X0#{oGn`$X~Y$sqc3%JHtpPZfh7+62`so93vte(*`+cic#rQXVH zWsEGP-3o5eG14`FVlr9q{#G^E&ZG+7*8`G(z+b}q144g|gifVOF-GG@GudS_t6D)5 zOU*3oKk;wRb2Mll2r&=+y{SHVrOgcd>)T6gxz`6gHOE@2TUxL7*^Uo(va5&tG1-*OFy0ayjjQSOHaBg!10Z%^!?Q? z1Fd(JmNJZi)v*l2XyQ#<0e!Lf#1oVn_r;h5L=q5rr^dg`QU3?<8jw(_)E}Z4y&ol- z^YV1-7DW)TG(FD-nE2K_)PKxFZys7vu`ta%w12Rqs~|1+`hL&C?uJcZ`_s4ZxaU~2 z2X1%<+jjw!K>z0Xu%G00HQF4m)WT)mb+$Tpd((l+?bf=sKg0e5y-&GKj=EEwM@wA> z$JVln^$e5F>Pbvsc1F%R`$=sEU5nRM5_s>%%v z6KKscL;pbQXJ$6h7n1^iQs9dP0e?)u`D4I4DSkEbPt>nQ{tUG`3K96vUd8pF%#Zvf z@s4?!#V39Jqy?~F%}SFOEUA4Q_)ji*wHEq6+WLFwe|))TKlDGI&-vHxzBZV@ax?5F zJ%wjC!w%8cc=}jtO(pC<$DsEW;N8=c>$&3b9RHwv(%#=!HNOP>ZNE1=IsYUF^cR05 zAmf3*@Gy=6CJKQ+>?Q)>4@qg1TD33mhxEr8ogrfOD%gDtd9x4uOEj?mob>UN+UMDx zbNl)Q7R;OVa7TdO#DZ7TrgjDd#J0SeHmyeyQ0Up8_C%i|Ajh-cUeY&B0sO5i8%pfm zLl>7{Xn_6~8&7vP)S&afx_f#GVE;K@yBX|vw6-4Kux`@cHRSfMEX>)5~P5e8dD{paCT~oo6YnkU&vVx zy90=cL9fo5dMbd34SjXiw9{b$g?8Y7E+inQ0r;Q0H(>XLfsmCu3(`6-pId&RzF^j+ z>*oqjcNT0q1bi=c*KRIB-u9VARXYooA4y4iu;$H-%+cO>p5JmM9h&zIMu zg9;2C-m3`_#R4ht{}k|~HJtAainxw~VYlOtFw*7L%VYB&`Oftp%XrVjNVNbYr_hF2g$ez&3EM)x5{zDDnuV{dTSpXB_bDME<(MoOclgiw?c7Z@D~ zXpIY`0to?abx0|2dn5};K{|&SEr47c2o5jsNNP@C6yJYHzW>19qvWofB!J_WIFhLU zV1&2(+@}BBLgejz)&;!3fCPKcI6+CHsbnGU3;Rj3khRCf&X|{+z}lU$@_DK8Y^7sj z(A?AnhYK)0HNjct1SAri_0I6P1R}vP-x(X1fN31}WyM1O=zHf(gy%O!(Tf6=LXkj8 zL`kDy{~@9%j!IGq=>xlu2q(vIgeeexEFwNkY?xo`PfFvc^+L)w0`?!FDJ?Q~#*&%@ zlRYn1UQ`ort<0Y&&#@)tod?XdB`v#HI8k0SVdk=i!te(H9R<$V8M$MV9S>y1#>&SM z&|fMaLqy5v1ghj?#8Hwc@O+AdQGQ@P0F}P5|BMyN#!*qEbPO&VLn%pW3@(EH)EG>J z`jrS08zy{ah+%)6_s4mEil){}DPJ-?D7;H*N~0ePUD9pHv9k|`7S$Sd*Hlhc?5H*E z8LFSG*l9N(^t8+f-CteR+}ix$gGF5*<`g(*%qaTv(VQoM|76sEfd5md|ET0+#ZhwT zKSme@`%mClq0(O!?e(X_$0C1PH5S*xAyuj|m=>Pm4ZOAdd>{gUEy2ApfVWN@uJ>@4 z0r(TVKTQ#&idJ>e4u+1jEbewVS=NzR*ylJ=^P%9}VnRh?q(YyaAO$NDNYq!#8I!*!6*A zMDRjp1XU`d02x(<%)t<3vg(4<$uhdsNgn5cYO6l=J~)1<){*(Zir(()wa(0vh7Qi( zbF{?MP}B;z60&~p`iGnICs$V4lH=yH^7-a4p9k%fd_}qsJ<(2vKMMQLEE4t~dJ^yt zjTuKn{}AAx$@@PA{bO$UKgIh$#rr=A{bBz>OhTuvil`)+6hr-Ie6AY&F16#iA|0c9 zDro<6&0DPOFU|Yk9_p`kY|LHpdH1yj=f>QIPg`0q6wYe#{K@0#E7}Zry|1BYbA3bU zf!)yG&Nwf!@(gnrQP@Mt?FL^uwuX#R!2Xj;Mu*0ZiMFfvk1OG7*nIhz` zgucih`oVq$871JT6mb3|?~f%Qe*#ND{tT85{6)G_EbIAPHKSiId-nO=tE?>SKbKtf zb?tdYpZ8Q=Y--Qn`OlVy3r(|j5B$^9*O$AwVc_%Y7aPo*8|q)*wIe^Mrp7+oalss9 zHz~#!b_W9bjgPGnMB8J0$H%6^{u6Xhcq*<;izcR1W7VW@v}ig@tOlDX*iTlIcog(s z4ZNZM>aX#S=l$blQZ4j1j1M%b^}zobvr+A6GcJC<(x|IzXPxhKuywud7Uw_Dn0n75 z|MClGQ=tFpzH;P$q%R5h|F&XnzIanj#?RTK<{&t3rtoMWV(fZ>DlJ-m5AX*Jx@VFW zC)1*UzXmN9_@U2}{=4N2CHWm|p}j z$H4WUYy)e?LV`7~!~XL~aM}5f;rVNpQ|HePoY}a{a_+*FfzC~D@2a1F^<3HJ{_}mg zL;KflzHn2fIiz66$vABF_pUarCrp}$&8BY(9Y4gEu4|8b^s{iiYA zQLB9*qt`qI)hj25SLETd)A z8hQ)Mz>nGytfHVlBRmXAYK4cv;gp1Y5*+^`QW{dLmQcx@KLz|nA*%vtu`}IbTcx0d zjq~#Mu2J~Oum8Qde*MZc`So*y4I4|+a)JNeW3B7!Td!T*d)(9B=kW|SAodM5Y~EX4 zb*+BK-c2j=x~^tADpHGtDC@w*9hhDU;2*x&GsFcN{HsNh7zG!u~_i zdKUH*4ZW2Ghd!7_yoDlh&L2a37aT50Fs)!UM`|@G(nw%G!3eb2_r_2WjfOk(%ZpoFNzT+R1hfn+cOS@senxIc|!2T1wH3|Bo z{sX*e*dMs(0YilS1QK}@y#F|yA))^`Ng|zY8Gm@3B%Yp^c@OMAiY2y(Q2$x7`El5P zN?zSOwL8Ekw)M-+(`prd!2kFYJqkbI-&4{vO;Oc1P`k3WK+$=5V8w;10$az>xu(;d z4K=&351{^&+d9yL`cKI~E$lzx)82fk8TyB9O>#0?O<>5@B!>nL@jQ(DDc&FF{c+wO z=lc)N_a7XiVE=*L#0V(FiHVsJYY3qGhuFSCsLZefg0T$)vE?W-edL5UMae^v6}aKL!2479RP--A>eh00nAvT!5qgBjWpy z2<@!O;MWAA5cMBGX;7fg^wnTK+eZ)?)Ag{z(?u;kceb5ILg57vTB_1>OMwl0eM+y;R zBZU|q5i}CWV;-JK}CRNPQY=J>?&vYBuKk6c2e$G zB0DTAHauu75f!52`cDw*KWO|C>_4Pm6dol6^i=}?u|jMd@Rp9@{HZaVKQ)Fkq(mc0 z^8P$Ya-_eEVx-Vt7G5od{`8U>gVD&~!9_I&ONEIH$*D2toj0jMifrcP7jgir%a_*| z0{^acIR(JK=+C7&(}4e^UzV!w1^$ztVpNk*{}Cwp{zHaF31I&r{gt>Z^8g<+~Om`KETtD6b?6;Cu9+#en=*niOMQ49^gB~w+?z#o%Ece6{43^xA39@Bwe zTgma0YE1_(WvGH@*v)${0~Xbk@2#fJ;UPJx zj4C%PFwzA5!RsR(JP)BtfpQ}F8v0KJ-eCQa#c=+zXwF|0&HJke-e1gn3x>&UBD`ey z%jPjMG;68~nNdw(TGjdNr8)-iV)lV8R_aMrefChlJ<>9Hes=d&z@oj|TbiwtY(;%* zN-o=H*b4jBtOT^?G?WHcS|?d^>qzHqZf#4~|5TXAqg#HBQPZG#qP156yY7wa=BcEHUW^`I= z#&ZW&S@loRMQ;ze?T*yRD_-wDZ+E6b|J~NYSw)^Tp3C;!S%sc8*Du@6DLD<>D=Mu) z)|?EMwX#7Orciom7!_nU_|Z{eShQl|I67(^79AYxBU2`0QNht;Wnkx*91l3cKg#P* z@V@wMh*o{?m}dBKpWwJsHXh7{PD@5SuLWEqoBsTIOsD@P?R>k7b+H>Gou7AE0i8Sk zd7!4!G^=pnouTep^Q`3qZx40alTz~Q->4|Fimld+*=z?3o`TTvOFJmq&iajyss{ei zKI5ZOfqyhHUYU$5$3=tX26idNM2ke6zX;>~u@U}Cd?dZ|af?4W9#gBqnxlM7t5)kv zWl@h+sCD{wcJXr^8keixvH0oEcsJl{ziob@vkdxQ|3eS*zy8M_;J@>YinUg8iq-ry z>?bL#{Qm5tu%Afok6JHK`9_QHk4nZ>NbD_MF#$TWPv*c5Pw* zJKd%}^B@i*1eln2byp&=8fjg!&M=%d+^_{)F zB)lXD&Yvdc=tbi(KbmkF*i0;x7Bm_hHQG>G%JnN&dj9Od>C_dh>B5zPQ?pv?D(kPF zEt@sa*fnrz;7H2ATU}QmUwyse)s7u&Q2fQ z=$x1LYi)pU;LzWjf0aBdC2;86U`47u#e99>T*apP^;Ip`&ed%8l=gVQf%{8<*ZT%~ zQuc1Iy3l#HCS^r-S8pcUkvd~~dtIi>ofl#BePPo*ZBAaKCpPxb8W!CWbyIhqxQ6kCHs1y z|3uV(`qt$Ff6q&Z9?yoowN-rseTOy_*ik=8eIV>8>?f%Y1Z@~PckPUSXi!q|KzEJ5 zLTE0z(zEBduTXmL?_YXjErCmEeNr}q;R1Rq@)r=R(D)M^UxjnNt8VfhChtEE$4LtK zj}r=L>PeXzGCVb6jgL^OSd#iso3A9WWXa~oj|NC4mi+$s)MEkSi7j6qpSD>c0p1@z z@gZVQ$sfb~%E4;1a%~vbPf`@VuAy@~%2O2Lvg-r&^_vtDbICx@-s9lsOTMZ-_#yOv z^QE_eKLz}k0)L9$ngsnRd==MEkUz%zk6!+;|3ISt177|<0x&~kWNIHFjzfP!C=Hwl z{6)gR$*}*7l}w!R`?RUY#)>CC`eoX*%@ZWK1z*j4;zPjNH|-^V43?N{-&CwzJ3(Tq z{C!4#X_%O;c+F%g4H4(;{;F#C2G0A?hyKDP8L!!w9RdC!ug!e!CV%hx!~LBRyZP^? z*bNTM2VtO4ITq6ZZ=q@&89!DWBUJfEyf{u0oiNY$ zq4x+$mU*6H*&lr*I`a}mUa5~*Z+bQZk$u&~mimgHwZ4*(x7J_6dHcX|KE82`4^9Q? zeWx?fUniap{RvVm6XL^o03B{`C~lJ7%NfJ*QLM&SwI_(~*JG6`6;h7gm0 zDnN?W6Ojy{Nl(y>4-swB`$R&TAw{@~AW`q3MiBWEvb#O1zpLq{S-){U99VC`3?eTI z`Kd+_<3E?|R^D}y_@1Xb`H?>nzn}PY<6!N(@ux8Ht;%~OAwI5RKmA7jyNJZ4~Qc=8*K#n`4aH8M#w)dPZ8g*MEK48 zw$q6I112T!kEq6Q6(WgK)EEK0Y80T5WRw&o^%D3qsAu6Efj6O)l8CThq4TpSG)@Vf zi74`RE1qM7oX40^{$JaF?&wdFgb+1srH@di#W6Yx&`4o)^f-ZxrAS&ePAFql6deO- ziU#x%$gI&)Ivi33I0lah0rLT<3?>0ZxRNHNDlnhm*#ZRfjd~m+cm~G`(Rv2E59E#Y z0J|-}(O)Fx{KrXAKZyb~!j3Xd%DQM$rbr6;DwvsS>^r!+L2 zkC>-4l!XNI^OS~UN$@<46_6Al>^~G(pJ4xiYZ$m4t!XOWUpa>NAM>sJv0K-F3Q;+M z(yGC}b<_mCRtFdzrcd4?CPgZn-r^EdbhJ%pDGQ>4W2`z$Wl(r26EJHEMyzCm5rIMo;W>;EFRBH6XMKw3kC%PcJ z0+3LdSulZJhaf@=?7>b10YB&!QxOE(7Dp4~;rK^9nqO|wB5pxO@yl6xC*M)Tcz=xd zNBsvQwWRDZE!Tk_TaW2#11ta3aJs85cY`^+wvNuL^*^ZcG0)c8c^K3(B5 z;RJ0q0)IgHcq0M!glNfl_}Q2^@b(hZf=7+Ucz^6J{YUg4_zl#r7>s;O4Ol88A6t#- z^c!jYbMIKD1t@t8TLTUWqlw4h z2ig+R_;?Z=77|ey*DaO2zjr+!P3%q_z5Hp^uQV8azgn%5q?~cns`68Y~ELwFq)6@HNfGS=VR4e>Q{YcxFA|YQph+JL}47gVaN2J-uGf zs!9p{(?$(TF*Nm%Q9}W8-Xf)!)Oc`g4#y=yf7pAVzqk8*i~cj*fe3tUv9)bDiyVy`Qx)xl7yY+<EZX-mDuMytt1yyI z#J0DAN2UeXmQuI?fj@)vam3+%g^j-c>IjPXM`~OMyR~sNUYT3ZtY+`hRrjM7UId|7JbOd*4LVeQxeQ7~g+J za&&(fClnA|KM{gAQQ$8O49(g&o?#LKOR|nnNVX>hmh3x|Im@0H*!<-=DlYx zo=?eu?7Ng`%_!eo%~*TBasK&ac}Qt*U5?u)FlcS>KX#oQ6Bv|~1-)ru68l9r z@D~d3eH(c1#G8ngJ9*3U|2luTEd~DIuvNq{RRsK{f%?=j3?U56&DuOJIY1IvwC}?S zvjW7x|HG+i3W<3y;LK2ox#4d;3lc*BzwBAS1WOWk|2`v+2^BMSubEgPRGe7%_X;Bs zDoJvD)vY54VS@RK8jS?_3--MPuZ;k_lhEP@{@;E58SW>7oBGLE)K7%uI1%h864f{y zoq0S|-~Y$!lTyi+WH&{TRFY&jZMGH@l7uE(wAuG%ZkFts?7Ok15{k+;Op!gtQX$J= zF!nKKnEl@0e1G$p`}aNfKF)o=&--=W=lO#5-#05dq5J6S+fi6EtBeHVZJ_ee&(>5vYStg=1ILeKBZCj4 zV?kTQ7WiNQGmpec?)1wJ0miA#4wnx!FiWDn(ln2XD4TBI&rhAX9v$-Wdalc6i-}^Y zX}@oHh5LRU>_A2Ju#HpD;oPEEW@L;tNFVOINvgH?LTfEVBDv1g|hpMxY1 zJf@dsMQ4*~*KR?^IF@k0M?3Q)vW6auVedqLl7HESNN6G8v?f%=L+^Iv`CIvA9@jYE z=FeFeQzmls@Ey3&k_C599s)Ms`pD+XBzeVSvqmTGzC5IzEcdqirXN?uOID!ykKl*v zn}d0gq$@w%_B?ccHNO~VRTk6Swcd=^qE+e*!1Xswz?Zs9aG|W-33uN&Bz36h{<|4N z++0WOc8WW(=iRV^{ z%AaSuE8k$kF9e-#GR;xB23ouv)Jj<3@&II8=b!lLMfL2OWkng^_a%P!nwE)e+1+xw zgwcijG1Rx+%%t-1|0nvOu;h zDN^N;sUG$Q#}j**0lxI+9&F#RDMh_9=(M1|G4FenWC@@x`eu4YT3pB`N#~EVu4ivV z5J_?S(+*i2Ju%$oATLGGNq;!!-0B9X&2rm>?@9`=(OH$}`-8sb4pklBCVqWtjFc|M z@u$WQ5&$txzCgXrzkS-4&R@I`)-mXXuoxYA*C-i$bD#mEdgKMCSWD;Vwdwi$vKCtM zU6R)~&n)dG&%OhmXMcxn%3qchVOE;09IuiF4fud0s@!7GmvGRL^XF+{<#p|`mrEC8 zjdCg49>1}w!)Q0JQu$5!ZeDfKAI_C5b!?o_JhRsWJ@{1ehGG<`U7mTxGoNlUO=LPG z0~0XZ710vYe)m~-qnun@MTK4U>8*(K7kJdkf5x9K#7u3RJ~_5OM)RsUKXUcQx<%4- zIgqt$`emi4l))zdYT7=AGkvpF-)z3BmD0pM*JZDTXm@j?g3&MUXl#CT+bwu1(k5lf z^0b2F)$dLJBqL8s{#`Ks@@Wt@=>H$XS>N@+cT3aE-BcqJ_pj1iN749iZn5ggPf;#s z%SN4#kpCi&9Xo$^Q)2&By8-9pti=ySDL<&aaQY(O zfIBJsn{&g8qOxrN1W$ia0gk5Ysmr^b)DLW17Nu|8?|LlcV?7h`S_| zhkJ;8ZTi>ak3kuNKYF51{9xTEe>MC5cwCTGrnqIhOHPvHxxeoIM}pMey!)dYWLPSK z`lvB>F&L_5g@1&1V=CT|m9HL5*8j1)<8;zs(%vK`_x}647ZOjU^Q=0l-q8{F!bK{N zV}I^dO4hCvz7UxuK6Yz2uvDd-0sp!ZfwUGjcz)92x|S%zD@j_ZhmcG`qUSdm1v11p z9(r&Hq;0n=GKiL~J|?YKy%IQ%IIhiJRdZ zFNPI8K9VybI-tD8|MOU5M5Mx6=gTV$_zIao2-O#4N9_|6y_!G#U&^gs*RpzSNsL5Bky9Y=qG!5Xe<;#eAPTc6GFw58NF2u;0K} z>{VpmJ6@}|C=n&ZjM5T3yLHlY2b|@oPs73`SfvdDVP11e2OVLJf)vqtt`Qc#!)pYI z->kV3oux3=?6nf`)ARVHHi*3fCxo*+I^1dFzJXiZ_d6N?KNURn!s)|IA|q@R0~K?~ zE0o{*{*s(u6i-Ad3B81%7)AunxRXT*kSJ%U%s8vsq%0UyG;tXB>UaN%V6dXzx1K>* zVTx_rP`hYPLGM3Uyq5P^9yVu85H#WVbJTN^A=*{Bh4O$SuP0Y?m5qC_^9E$U%e3}e zT5aheCsgDrjHEnohGo~La8fv)`FZ%XIUB`<#U7O2+!-LY$pXE(=VZm~wr@IofK8=i8Z98n?M*jb^C;;`mN2YetU{7&N z9&EhU(Zyyg z7QT~N6CBy1Gp{y>Cbw|p!#vsgm9xlq+MWl>%)8b__Vntc#`y;6(&k+X(?m4qU4r03 z`PadV<_bV0U8xm-L;>&J_|P+)2&3$fee+IL(o8)m%`I0k|NOwzp_}vMi-Nv~v6$yk zq6Vp3hbA%lgm@fP8Tn zXs}rsluP|DIVAXKPq40bt`DQecQEYy!(1Qt0YZeSyY^gmN=4FQIIf0XB`WZ8Uax$= zO^J-rf60f)_)T69m@sx|^(wJEUU@V2r>5+W%!C=_r-$G%ax;gSr`3(dyZsEIVb8~( z!RI?F5QbdxCu7||5F5NAj9#zons>laP%_Z0hr%6&r;)XTJ7&&2B;;(j54Bib$SQ&J zT1bTiQ&|XqpTda<2n*u%;P6iz_=2Tiv6QMHafh8MV|(w;X9ZdL6Z23wQKCs$w}F_RZg zWY8Cl&3Q0Mn~Mr5`+|k6LhV+rSN?wJ16HCQL7rOgnI5Ih8aCl_fAl}Y-b3$j>Ggkex?$v*WXQy~BnBy6LG*oC?9FqqR&^x$`#26 zV7cA)sd=QoUExgYbn@6cEyDzkpz(ZTlAApKQDIMr;+ET~7i;}}M&Zs}sv&-irv!nI z)I1c*3du@r(`2NiF#csBcg=Ag*GChbv!?E_wS7STTlpj(jjmVAo&3k!4|VdZ55V_b z17-i{RzG|HXA-3-y@H-vtO`@mCCe`4UCyez8U57L9*$@{i8D_B*IYs_5ipayP%qw$LCYB-|!>i$#{5cAeAY{HOoZ`9Vt1JTWZm zU-%tXC849r*p8Uwdj_hAyWc4AsDu0oQ;VHWy~f@AvuaT8HZ;VF!% zuEe%dC-(lpP<(cFL!|R?LXWJSw$j6Eg@;Da`Um_KSvsQMwBIO-ce4++OcP>paT7^b zJg?_JXmi+im31a0;v@w$Ys3OVWbzERE?7DX5i`NFOiow)p!4)|N1Vbf*r^$=PKa7} zJe1dmAsn)xGCVBHu7Z&Z>h1>W;-%~G8JFX8H#8KQ6(puS>{Aj^0}Zk%n!5dOq`$Tw z!qs#xe!64>P^k`4~V9JR4XJ5*r+Q{etU(LJW;1m;G7(*Bc0;=~|O6M+co@7!hZb#;2w@d4I z{_XYwjcLB)oz_djXN(JVpJ&{A=`9zB5#BBUk1^$xHOb_YSqHrypj(G~@2d@M$r{D} z)lQgj=thPH>G4(pZ|Jj{vVSTWvDSowjRMY4m+W+rX$14jX;Q$GyG*RCcJ@@UQWDDzS{dq)1$DvFV4I0;bZ5?Fzf(TOLB3J zDVmJ^jMnDqW6(5P9Dq+Rd_FjZ+iyn|1=x;-l?^cYarHlN6f{c)f)JkK_;wE6=5CAfeLOn?^UGb`}06e22^@qX{R0-)8+#@J91t_7F>0OJo;{##d&3+lOfITURYA zsMo}@e=6CVsA@`Po(?3F7G9vye>e?CHXldGLk_nR$6{nsOy0*RR?c=B?TTsR@?~`f z5lmM^>filIYb}Sgwqr$qQyk1poUSZ+n?Bz+NoJYG8ypN)NC^9HE755D9fs!S3h(tl zvZ0O2F_e+(B0uP#LZSRGv6z*W^@=;szLm0>l^%ai_~CR1U?Ot+-!b7~K?kDWiDG@> zSGpuZZoN(>B2WHt2dJu3r{|$R`Rz;I(9S4Y8^W~?Fo90CjP^OLGe+!*Q20aE{`m!T zmJg_G?gR3wTgY($5GUisurl7H7Zg5(zConqQNsi=X3iYzz zl~r3?(p(TDU-B8aQQUo z@6!%jKmY8WH;fZiX++!aq%fbDR&rl$mTaNFoqm)_F4czA?hiC$3^*D=>{q>LZSp^0 za~_))2&s{9)Wae22Ol;^>)!cMN3sBV?CfJXvbM6MrEgm`o(70%WIvnQ!WU$v7^Dm& zI5+jih0Ny7>VC;@y~q{+OrW7dj|Xb;Sm+Gj*auMjBI(YmUR=KfNWR;h6j5yYvnJ*Z zqPuQXBuYX;Vc2$3TiDWVrkl-sDfLV6Bjok+gJ9v^lf-0+(nhdOD`piQ>w~+j@4kVP zFae|DzE)K!HaOCMs4QtW#;q!w-PG>vIzwveacaf5++GwK^ACelJOVc6^?uC?YZZYw@#9J%y9uvi+}l)X=_mEPa3L7q+gG<*bMn3@;y+O;x+T zDqOwA;&D&MFmU8zCu?ha9}eW&g2UCtc+rch0--Fgtei%Iv*A8GjSg8EZ+1+j9Ig1t7D zJ_C8IK<*GZo{_9<<;~@Ji{Bxbr(aTpPEbYu$)8*hDn`{7H~JgS-{iMT8NG>H;An9^ zNQDLnOiI10x!l~^JDqnDPfGokCrw;>%km*f zLoB7{8hO{;+xm%qt| zxfxnnz{SjQ;K0@g>QEE1`NRpU#I zF!NwhnL8&mcJHab-)vn^ww1q~-B7T8U#E5L%>Asff-R%CUGr(=mwT#Wcjj34t?iZffE|B`g09fL)i!vLY zqxv(!v!aw2Z#=fAwkw0QL?3Y7)L3aY2a1s$_xoxzOSLM?Y&2;i1?Q9mpgV~ATFKg@ z90$g;8}1RGQj!8y6CWr5gnAdq1!=^-1n!=^$Ry=*h-XpF(;IK$C>!1g&N^njC?uCo zOa7V09)M&VgjKjAeYdT3)bt21y7*k$yY{HIcX?M?^nz)>p2FCOuTgtmK9$<{}7J2R4KbT;p!Y~?IH9+%(IN?o<|DMsK__fE6IwS{UKC4LxrLl++mfqHCd z@cg-dqeRb}Tew-!8N?!nF5?`oLAG;(vkgpYs)2AeXDy$W=1car2WTe;N-3VZE130< zIIVMaXC(<=xS8A&J`r5fFuJFPBOrer@!=@6&+^%wnD4lRr0|*UptI8!)mqSXmN2_r zFF|jD>456zfaRsWHQ~f^_?hKLa3(g2J6|ajM#ymHbx9LW;vQg0xnS|W zlOr^5oAJwEZ#2bgOb-S{8}Q9xuNx{n z1MI4P0K!E8FShy)Ch(|Mk=tD|wXOME#00t`VpRu;wF)=$8-ZJk0~ym#+RTLHK%7_5 zcums2WgB}G4$La0;Y7muu)pIAYg_B~qMq4}1BF%25JmGdM$(ZYoCx^CK_OO!DP)!g zYS^;y$~rW39N;zy6)`YvJHt~(v%)^EMC;agXRw@+U42An?$@H4Om0{G z9gai-bhVY2FPX8G&aHC>V{`N+xFm5hV&}(_VS71rYd}@T^Bh2LxZoF4y_HGMOFH`H z5#W8n=P(n_^c()dUlX<7_l_nP3sFqyQiY_Sobowr5v{UnNqcB3ptgvMqT##6lVHx% z-nkIYJzS!>J%8!hA{WupuqvL0Xl3-uroAus9YR=!0}0#Dsl#y19rfa2MA%uOmPP;XA+VEk zdmx#a_p2}92YkZtI)~gXieEdS#O|Y}q2|&-q6_4`m>E?ayatb8iteOY(=ef_pq^sh z%!u3+A7P`?EiezMrRKRuIOFS^x(AnXCe`nmkV8}uCj7m9-gCYNT|Ypg*P&OqYvuLV z^2dnL2+P(`H%Xl%|}^1pQguNfp4Z7 z`sWv)lP^(0+wnDc@NkV!8FInYWFTd|eJJ));=vx!nZ#qb7({_PCgVWTD38eai?Er% z6cmpQ{83l(LZUvln>wXb+WfR+tOoU4QWFQh^%4%US4NM~zvS7!7#)ndv9<=+3CL?# zsE6%TJ}f*yJJ2#mw$_(ka)DDG^BgV+ZqPXE7Gp1!qIL8|wlKL#;`Es|Tr&4G>l*_S z|0%|R?V=QjFdhLk_KvS(k zK+A#PeK@!Vuhh6IaQoq}=g(ts6`%WE5-T1Xyf1CuYrwiIs~k$>sxS-<4gppBT9)Dt zU#)+79(`<9?qB=D^gmFHULTLU&3O?zODORMEt9?~J<}9^2)lN_a(okV?BBB?b}5b| z?|AC{vq>Moh$GH|Wd+-O9&LWB|aPK)0n=U@#=aZaFe7E>so)-J*X5U4!Fxmw_Y`mqf zan?>Z#{gwGTE7Fc#tL>MZZFh7D;)z)$L96fT3W_~bqxEje(9QPhe@O#P+Et6Yu@Li zuJ@|KpD_82*eK$H>IDzfSBu5ZXTIZK<$VdA1?-zg?LC$nd}@}7hEC0WE>APWNPXoY z!QAA#{XLZC;cH1z(J{T?W;G4N6UYqjZQVRW9%~H0558&u47l)8=+_<^(*H86C!;bR zZ0-Pv)BGKfJfq&79tRm50RPO9#ejOTuCDhVsE&!768l1!bZ83a zIMIM#M}V-F@d95kjbKnMQc&~kso0{j(Vp8HGlai<1U2*ed$h%pZ>LcBmL*G?W*QLw zM1licbW`TMo(Xt}F=HW$X_alC)G~gn6RNy`efPg;3&_sleYPKeuv_ZBu>udd3NigA zrTs9~TStFYCS=zCdIX7*-BY0^^MLe6%521^Laws5U{WytO4o(n&jvcLFAj8l@c%)u z&WYfH4mEB%q112j@kz|IWYINv@;oS(4z{EGo3L_hisYqX6N_4tGwTBKH;icDvpxoWT^z`XcP>i`%^EE_n2h``T5p2zYyLU8zUbX@%To=;V zF;>rW3SJEIM(tp{LA_5?$$8p-9~(Ir12c_6o*nH#iUJjkn{aP4Nc~|;lE>k9adfe; z4No*3qcM!g9TIJ>xdbGTzG4qd$M#0ob;~&mz}0gmflf0>iX?duGP%n_Th^Uv({T8l zT^tAR87V!Icaw!z_kckZpAr!UWIa8-QYcG8)=g@KIJxzA#qZJF?X`S zB2{@b!}p=_WB-@n*AAt6L$S_)W(xVzqvq-G?5PhWwk+#9TIIDl;M4{|1(cYrNv#xr zp}`UF7XYZ9CvvBU5g|N)X87D{VqjVjJOVem5CfP!b}e8s?2Mzea{HdCJ&h*hl%NAj zg)bT4QR0f6_BESzM;3-)0{ONY6sVkFqotpUK&PqT1qw{X;6+)GZp}4=p5_~$UztkP zG+!*N&yWh42;(H?&^+iDOPs$2mm&Wg8OTDt!q)`hE<7Cr!d~+xq=DvAVX{bAo&Oi+6Cc?D;$~UG`N!(Ak$)}ubGVyC+glA#k5o6yu;f|MGK;K^^hroVa&RMbk!kfh@0$s_iLGWaxFYB=cC z8At$J48@VL(iyD}U-y~4{o79dzS8N*b*Nu~xK*Ur@28Idp4?a}LNkZ3LHVbhyppwM zSon}j(&f%SUhvi*gBNT`XpRH=xqpCO`vZqEKU4X(Y3UC?YDS+^%Q?;cc@%2CskI#v zmp7NWdcDaNOqv*&CJq$tzn5H~J&1+2KSxZcKkN}G0?ur~V+nW(Hpzfj_VkvkMa9;) zBoT3o1+wVsAS3>~ie<^J*hK7->1@?7;@hdfHlS`jAkGYKf&IIUC`f)b)Wk#7>w0r| zK?pbc8YHTD*Fnz%;HI^9XW0!xVb3T}lF$`r65B%m?A}^i08&tG!SYk$66F|d7ti9> z6?!58B@P1vqYE*>hUxtJ6{|3xXAM&J1X=d ztLL)+7Y5pV2_DYM7(i{K#;-DJrYvl(RF?ug8(}KLZ*g=^ZPIVy2+H$YbMrM8-smGe zj!~~Qgmd6LJNK9;y{FJefQtjyq~>K_uO25DQoLztdRFqWkemt)e*|j02YrU0<&sFl z07{65mZKpbARyOmnN95U)5J)tb0(O&xDBxu(yDW=(Fuu0hJ3GpnJoudl!xm5r$+dEY^tepeJ_ZYSRbf(oxd zN)!@x3<+Jr;_kybRyY5CTM|%G_N-$e@@Nb?B9wBSTi}NRHM2J(Snh8^0`Qp`;1Szm{n za$<%1+8WM=-#4~|)QxMAe~R<`5HH#|<<&ZCHp&XLX@Zn;rw;DDXGa6+^`pLX44G%& zm0#~FH2Hoi`|Nc{{D(K=!{GtqeT&09z=AaI%1!3xu2TJWDo>s} z-fS15$&C@&_EiaPD@rO zrW_MJ4m_4xgTrn@Og9NbiIFUqwopduEn4|3d^R8jYWjvm zJ^PX#p<2Id0x|U4b;(e*qVO2Ovx`0Zi=B^i*>2aU<;rdp0aT$%OmsQs&34@(TG}}D z=nN;>@4|%1wJ8Z)8H@Z-#eDCgd$A<9C zZ8~bcMU24LeuA{#9`hY{3VG#u8|hC@@>_%$w+i&#Jjf}BehrLt5X=C0^C};3l&jp? z@@jHA_L)ml8@)@!^+ZrC4O2V}Tu?gl2&}U3zRW_%gt-;E)~{ruGS&zu!IUcUIq`B&FWs6P3`@tOug_KXN%jeUiF=X}0e;8dyE3m3z`HTU+d#L&_d z;O}gX@GZd#r<qy;XFfC;R}4IGe9vSMV=3AT z7UN`t%uacBcJKNE%JEMB3|8P3(aNE2$Zmx3^#`g%!uo&TJ@?QuT*Le(Bno{C!X1Vd z#^A(&y@RpOAj)O+QYX(!AJvr6jY8ZnS6NfajiDw<3ku4)I9Ryv z*&)wO6{vwRw8~Gk%1qK(0BgAZ%wL~O#jh-#F&VyS4?OYDy;nXAqb1az^NYu=>Vgzf z@!-VSLn?DMak$rD)g?;(Q1e*~56JmR_Th`00&X)@)Y-;>+xtkGRo*2wYpN&dW6api zt5ZRZ+x4D(w4m^mXJNWNj^C0m2VKGhK?Xbfr8NPH6MgHlek4{y-4D{40 zBnjNia>5#p;{=EwRrZ>3=WG8UqQz~>F=5}qI&+-F2&`u6) zG$A&Omn)@pSzq}RPh7;+Khqv4nD-~@mzd3w)hGg4M@N9YtnPVynI3H&P8H(>+JS`c zxN_@Q&zpL-JdgwHBk21(el_^eVW@cuO=QqKw!P))m8C!Chk{3_}#nog4moZxAGRh{5ljRa+@gAS|)EL>UaGx zzjzp$+9t=>)^}=;v9w^OW70(@pRLEzT8|FCv$&OeY)Dr9_7SV88|>I|mwFwOlVaD6 zoX-@`l$ectH@-b+>n?KDGtF=?fJig)fVbo{s)AQ!zRgULEi<*nqvswAxq*m$X4v z{fm0&Q{`}l-uTxD8g1^3ltK=|OCvzImnl6*jJNuiCwBI{4PxLg^6gaS4l=W0e=@Ma z3cT$LS)9Z@*I9p?`(FjvRrJZ5r)3P}tWT>}PVCImw-yQskv8-ay)r+W&yanu3l#js zpc(%}je`yl=ShWlra+KCQuB-b)7`A;{hw)O3P5dAg8)26Zb>t+Dsk~!me3lTVzuRjPh zB&EgPgc`e!MEE-a7hbJaRv4*Ttij)pZL}0Vrg+8xiCNqaco-WEUDjyoY39#ef^uOX zKAk-aMJIyQo#|JPvk{7;&b`l*xUFl-n+QFf-PE00>A4@xGIK+so)VB_-T3DiGxz~5 zV;>N4kpz|9w%%k{p{I|ka97SP+tAc>JHW*$%04c>4I)4x2SE}zuMDR<+c$<+(JFBb z`ls9B2TWkib&j%Nfu2msc~EZpySX-JzD%1@kj)28m~T?<@T1}NI?V9;93>}6>S=zQ zhg0E)PdKjrUU=8g*ZhjVX`_cvau3!JGMnHeYEby4?+~}mie!C>#Go`ZzMQlwnqlvw zW4zUJDIB8A7|^Np37rJjQTPsw#RpO9_T8J_FR)=rCmi!D*j6COTQ~mpr;_ zRw$8%`5eX5qceEBeBf&3JO@Uoa1kVpggqFEr*n6jE>Ya-Ul@L(p63$CZz2A9#WiKz z*=#gZWBO~Km)v~%!Z473l%+>>)*Q|QHP+KCt=~=%Vb(d1zXVyI8$|ETidOZ=NNjg_ zv_eZ?*i_SL2dyTBcIcH_yvl?((ZrzSr>uIFyrrt=`|#3*ZcyViVi0gDSc7|;3+#;8 z3WeZvZx7rm0=y#`c4r^uYVK2xd;eGV{56a7V6W-zJyth|%b|5dg zG{~WV!5b^kcqxM1aOv4}RofKLfqCwh*pjCUGOt`Q(O>ZsK|fbyH~A3na7?>&4661| zZW5~Yn%U1FZ?~1VJ}mOjrr#z{^FG7LHS6C|&5K(_;K;b>5;E-yl)g6zr#th&>(0Wn zrj9>rN{M~5HOLr>&-3$m2{%5Im-N-~%8jgzx`$&Vj47~#k^6f*?`~o3zzfS|x^gY% z;){QkhR|#uZR5q<>Sph`9Snr-d2CnCmv1|9=v~Os@ z?czLA6+w#-7UH*wdo*-ij(O+5<^#cY*P~#l*ybAR)ko*}c15R>l zE*cs`f4c@FgaWrhu!g{|x|UB@f9T$Z-k66?tk&y&ZarvgR9 zUj2<0saDNBR=;N*DX|5ky2@Rzf=*qS*{EP}G01hl%2tmYeErle2ziN*UV40=#=`^0 zW4zigD@|YaJ?3c(9gy)0_lUcrc1Zqbaob)-&G?&xK;7}zn8X`&3ziC3`2!B}D!g;I zga#|%{rzBdog)2YPm5KN@GkXyt-Nd3E}y)M-iC`^C7mkMu;6bx9Q9+n$O$+^U%rzr z$Y|9|+#zDm_S?YI^m|voZ|!&)97A8oCl+7#axNA!=w_LAdu=mGP5oHmM1usbiPpVo zt$k_a#FVD}`6ebYLhdOJ`)3;RiXx8-L!+pLh^C9ucW}gnhS?|$Jx?aBSfgn?1|-)({n1}!85HIe0SU{_tslu<0&3zx4MDO0 z*l0(oCcD=Lim73{TD; z!IPp4rg&Erw;bvE@XO13Bz=^H_`)y|rr{GanKqrSYc?LNz@}wnLCZzCuEaHmrF&o& z9&?ZBvCLG;z=w_fF7_$Ja8E3cSPugULx^F!#Bn#F&yei;7Wn22C#6@jiZ^5IX>cYj4UvpqB)KEEwn8bfZHZCJ~7MZ@MF^siCOl3F+ zBLY=8G!6q{G|&8Go+XE_AXsVVOg`Z}SXukPd5~}y`1B)EXq1Ewj%zQ&97;nSmN(eb z)#qr{k`K6+04>YMWyzsaYnN>Vz763XRWiskI{+2EiGu3r-Dva=h%2ymKQB`a;0G}u z`+rcNv?psef+L?`u9vQNc!#13-m}V(NjWE@>6`luTl+;7xhITSW*=#3_gVbUKtoxR z)!VpED*YT3$8}pbxgT5a`a-N)@wD2QMGu$69HF7eNxi~`h5-jSlfoXVUgVC|d9A%m zHj6e+Ltn|k>PJ_v5Jnz#hVMc7s2>8ExzJu#Mg9!&2nBfpO#BHHdrMi>=I92|sFEW=o4Uz9CT384 zBt(mOw|s(~>nRXgh4--CuH7;mY`q}H#!b~;aeW&F3dlPDIC;+ZT#mq79`W*Ft)6doopiv9uzf0Gh5y$c`ZKatzP+rCB4 z_`m-=_Q}Vm2-5x3D{ocolV?z2xnOSe{w@R#e6fD?v`2awF82W1JwgZeF2a}xTPs(B zxHE-KzVivUJ|d`1zQ=X(&yr8xuh;ErxUa}Yo2|loczv@|Zc;!5^Gmoaf{dBf{_>Ec z@%+_I>y1wx981?U1Ja@U)%g|>_-%b+35mmZB>M=;xq7bKtijpiRe$}`Dx3b}@-`Rl zk*@M?q1yEyM?P&k@rNwe>3LS$%>F89ra?~P7dJdJ#UU)y@o+uP;6D)kuU-Coz&F8S z;K`uC=DEC3^KwE>5q!;{#f^NKJpB!N3=dwGX7zygmTlU$k-sDP2_JU#-D{XZKD}Yt zO{Rj+Smfe7msK1;`7?`mi|;^;;eS{{H}ef$rrUZauKDi0iMGslXX*ua-@F-Rcqh2z zxrYXK9I^AQWdNlx-Ewvg$*dU$%8*|{b7~i}lwNf(e{|fY!7HpbC-uC?XQ^wZQzEY= zZC>?o)%o))()R6~e*J!DKkZt_(U{#9IWM}yGH`Htnh68*h9}pppPj1-hJ{M5dOEzf ze+`Ed8l+e2UB6Z@uFk1ddU5U?v}edpY?#marx({nnI?BWzrb2mB&(_%N@3pQUJNr3 zyXFd}dX@6x;T%-PfHxjyBQSL94DkbNhT_Rz4q^)tZz=xV135vC$2)`L=L%-bBP+h* zVd+C<87wXq^dH$S`A<7&>fLJ}E-&SuW0^H(P*YBS>|0Wuerm$hRXXV3Bx3vWc1&rL z44>zpEC&Cu{Ke}m^kf#Il;J>clJbw>xbaHf#??d2WW+lzcn!?L`pY5cfaaUTXVJV&BA)%yU7PRB^%!(++1|+HDC-53AO=!9u`C zf(){+sHd3~Y2JmESn$VaeCg%tw!URY3%LN$a)lIiC8MZ#vwmNH1aNgwR+X6~?x3)g zRpc~gmRtGh;S9QKy(>6yk;bA(j{`f&yrzUlDDy^TiOKugy7^pX*{QDF+xy19fMSX* z%8N=|H(tL0&koH)LPO`YEV%{^rE^y(CcG1a5M|BSFLwN!$6&cVTYNkU|5}N({T)}< zP=7xz`KuP7R)g%L7uhje8kdw^r-#_;*7X>+G^YWsXO zlm{zmVwWsWvRNbPU%^m23}qEs zGSk_Iu$XhrN5&8j{s}qR|Cx^PN8H$IY`<}-JL}3bStte?dJ1bY zdx+>NUAruIAJeevF4OgAiq`UP`&0vNL;d_}6?>*&r}xkfe?P=~$C*8CC|B7&eAR2! zA;7-#E~DAlwT-8toudS{{MtzKxjg zBh3k#CH%A-&~gemLV^@oco9fyH)xhDm2Hx?;lh6d=6nU$i+TD3G&BtP?=SgA3h3KS z6TvngTC;J8xwTV2X!PjS`m6OZ+zsS+hQTreC_Fvak)BuWvyp^QzVW8P2m3R!su zJ=x;>#?Zkgx9xX(A2o(jMzjqxKEq}8DDoV*_7zCjobf|Kwo#JcR$z}Y>HGo59T!^l zukpyff^xi~+|y)EOQR)*>3aqr-@zEE9vnw>28|<1mJRHwFskn|9BWt|=(l%TqQ=!kRe=Wqpl7}*1vR=DZ15t^JXt-I|2r(<-cAds>vG$T~5 zWokG=mRB&IT~fYj<@AH!-pFW7NX78HCO&pFLb+yN`1ibt1mZg_x)rw2pfPKSJZ|(a z(`m9*Go9<0=XhYT;CWpgX3hJ|H8@2(ZS+HuPc1Y_JQEGwBJK9e%~2KlggZ;Ze7E@V7l(DVv#f*Td(*)4Lw#@h2S`9~l=4uclQTrPtbtBNcqdYxJkh^Kn7g^|9oI zX@~i(j|u_&tgM@GizMOJ4;MxmGd0#nb26)}F`l{cR6gRZ)lO;ySBM?IEXSy^1z9a~ z7^xXg%q~cY-E{MGp15Z{iyrv4O1JDnX#*d4qsR55)y8R$uAtG3Q8SkA?CR+f+*~QH zHWKU^c(sNcAXCFef?}`nLwe`cdfgIsRph01#lgSf1-V@blnus&u=oF@T zq*mhgoL{e3t%g)Ix1POg zS&8)qG;+=^!^&$K=OjN+Q}wniWe)F;+qTbYuO@{b{>2hCK8_FE7Ts*IVr6t*T(*hd z`E)1)ks%cPkb_TvY$H=be|0n3I z<)!~@G#-HT%Rkjr9Dfrp{URUOZg|Z#S+xO)G__HV@M0b0SM3PdrX+Aj7v`~s9XZva zWH(*n)nqF{YP7F*bsFf~9>j?;_tMz6cTl$hV+vV3?^#Owx9u*z;X3aVqO5zQSoKX^ zutB1^Rvz)T!&Ue1xX?tL$EJi*%vMNaD~~`}cfIV+l4<9dlPU=*Tr*UP|gcytQ4E z^tU15Vu;x_QM7Z6x(`w#?RxeC2Er| z3ciB6H;d=gxUs9|G2N8F^NRjy4ax75scGU-QfFY>aGsKCpYA_R&iSD`Mfx4Cry*o& zxYl<4iS64ugJ-)FGRk$LG{i)XC29Y6aNyRu?#gyA9bv&9frOAVRK7I>+}o|%r5 zoW=BV%F;QQV)>EBI&I$Ag;R`rmq1@Ig@HLufmc1LT7&2RH5N|Kf5mPuanWN5_GgRl z_tex;zx;Py>MRwfHn^2erBj7hR%&SIIsIe$$FB}T-QnMYu zio&a~Vg)NcflFgkax{1|n(J2gNjy3(+Y~Bo zoexi^al?zDXm*b9oMB6K76HS_<{$2Zo#kZ1p&zRU;UkONJ5=RB{{-lL)6!8Wij5vw zt~g)lj@TZATslV}(*Zxj(;Q*K5E{wBcjM-OFx&D_5xT43zt}2Q^VfYOwXm)DGSQ757j z@RQ_j7={Ec#b5+DsDR?%rTR*hiLi_RHXeC3ghR+-Zvd$?Wq+GdZQ1v7_kai72}fX; z=PVSbS70}b5I2L-Tw1_rx|K|U){KKyE%J~G;Q$OgM>5d+`BF$+|9QlTIF4-C^Jn-@ z>d@s(Lwaw^i;d5SIP1w_GDSdV^IMk?4MQ+Hxq&EhcJ3w88HtRzW@A9-*as0e|D)6x zvP|WU*|&7c%M3@_f8%0BS9b z_mMG|8s>V*jhijKA-~R{;J4lNdtmvY*DbXvbe(Z@T=!0+qbz^vzUff4!}k(bZmHBU zbbC^+q$~=?(9q03NNMOr$VQ$w$a%OSW;cD0cXhl*hC^`D(QdHXUmrPpW|JmLx5c*T zwGu!HyQO@={Pj#KU_Xv`r79fgh_8n{}srkHJl7ot;Tj_`y3$W zozcKdv9GUJAIeTY)#UtFr7U!>rL?uaz8igtp7$j|3Q2$=bO z(WqQ3)2zOAnlSE!Zt)#-O1P{x_=^zmjAi-%L0=s2GEo9zrTzwOHiR3pwqj59omN2B5xw2;Fwyf2I~Y zO2WpTsu+7rD7S)4(Liol;J{yr8ao5U-|6Ar^WKR8Ien@_ zZH>rdVg_lTH51X5v*Wpl|4=xGB)a>sA`^7)k50Rz%N`_Tg3yy>zu zT~!(|ICiWJyE)Gc;NQTH{7?R7|9d-9>Fl)Z$ss=oa5eYSSS1{i7P*u2TB5!FCA~+e zDdn_b&;=v#Uf<`Q!prAcnIv0|+=yDe-yOGw&;#59jHpAz(qxXpV9``rd7Uy;4Ho~4 zRK5=tf-tcLP0h=G`tc@36A=SrBg2-?FQ-DvrcApHk-V+hm|3sXjW(MoVlDm?3$H9b zd~L6_MZ>LI4{o+1KhtlDEf(BMKG2%?dp8ROhlGt7BYB5l{u>W?Dj@1*pWW|M@9_3H z;x=Z$?Hn(7nM+uv@#@Q(w4g7L5*PKy*L6+M$k^>vp?}mXSSLwp?CF>NS9%Gx7o1ah z>SmMIls>L-g@M&`pBs!v4>1GJ$Q6A0Yus;OtNY8mDEqfEp@ z5p%Bn!UtVe%5X*SV`7!&ce4rs<}(x7k_DG3;YTgL<3;3)5sNFuh-7h#U%2p)8Sen5 zdzb))oghw99*#Hbi?9tU) z*MR<|1!L^3HCYeZ$;qF^0t;meU^7_SqN_43#Su$27TI5~{8H}9IeX50>@_PoKoj|x z?6_i-um`*V!ldD3L~MO{50SZt!4e%v$X!`Ff_M(0m{)ihcVhweniWf>3474ZBopu1 zqTMq#06D02u;R$pISP?`U&Y7HqU9PJ!XzPkpw8@7O3MzN ztxzMxnkL+Cq|}e`vd{d%PVnfYx4ZxklT0LAULcm!Ccv1e?zAlw6+m!j6O26;@-}R% z^3dKq?e$?jLNt@d<&Ii(xKa5Uv2{7F^v?P*G5Q6 z)^>0(Db*55v+3Xz<&%C#>MhE#qNIELohHXhuK6=+2=OpOtz~Ddm;i?mceHAntGfS} zlblVt=0BU*O)2+NEDKEAbMTKwVIDhwZrFE2X+wl8gAJpvfqXzgQWC3P!b%B{!3cY5 ztv43~rdq7sFr2@}smeE51iP8B^2i>Vfc!+<{Hte2>(E3e{pBsW!~D22Plq*U9|ft* z{yP^CS{wpXF(J`4@eq2*68DCg;TJ6#2_TAMug?8+&T`Nq$(Be$hX6 zOUjLb?~b07r7)CAs}G`Z<$C+!rny`J*cZ#Q)KacRF|>oZFC#_Iw@LHzu6+U;@VTZYa-M)JD}YJy)1f6-z2Lc@Gu-|ua> z885;;UF#`}y5+g!z=Rrn--NUaD>wezt2dpP>$4kHYVx`UVbtQoB4u2s$mMC%`sq$5 z+vwj+tt0SO3LkFjlW4C$tTVJM-uu7Ydr>xqWFTYMG9Ri&{%;oNmAhvUA4vv`hc&xN zqPRzST3#p;tNwaB-Q-&m((#sEn57d?7-q+R0IX?tUh(@mgozD6M_jxa3#zcCJvRlw z*$J9k=FJU&{_w*)r1MPAli26+oqwOIAt>-|=U&(>aK2fm1Pj)2uicT??I@W9|$w4(ivEEo;Vfb<~+o_Yxdr(8O#ogWu+Bj6cVhp(%RAcN` zRGW0y#AUNInG8UJ10~S3_JBLq_%8V-aOgMo1@f^R!^eb!;CmLzUMbRaf_$0|v^=RK znR`1nXkLR7PPV6;=P0rWBHzMWu%Z8n?Z;zEE>D|KvZH?teZr6HErPvUY(kKn#K>QB z;%}B{{4z5P{ODrY%(_Si4oPBfmfEc4i5RbHLE5biOJL>1fcOj*+< z`nj*I)?Ka_qG#jFm8NPBI)N5T^yt)9czV8!m11f(laT85=Lk{yeop&^Gin^Kk1WFJ zHolI7DVZ3}EPq{0y&5g<=xws}Nb$qq0OGP0Q{P%PuAN3cR1{mn_60C6rXcXZ9*lFlG2ruN$Dna!jr=42O|G4jO>ah>j0$+rCy_bRX^^yA$d?$2o#>OkB-t3rl1|D_-F zc5gLrfFA#eTtK_1tgG3oFM_Rn>TK0Cg{mK9qSan7sbf!Q3&tvxD&1v{jJPb!U;B&G zd<}hSa(mP+916QE*l65pqv!Jnqc>3U?gpK^aM%P4!Tr;Ic~I!s!nJS4jX=mv#?ex= zW|^&iw8Z>;rQY{nT2(ImbCOM z-t9WJ{y+-v(m|y1vUiE!F$iNsd&nZV(Sbps4||Y<(-g`nD2~VauG_)y+ZLEZ7%3jc zA(KVmDkoiL>d1*AKDHnt#;?WBmX7gr1shnbaiaJS1Ila46KXOj1;DSgwKAO}kjVmA zXA%JR{g`*RsfagCEhdd6d+lYGZ(0$rqkc5Z%>CTCE}*nAYwP|SC*Q~~oWY&;i(m)P zh-|zhx(N$jrnE#j;seC_0T2A<%QE~`HXyUPE3OtO>As$9Nw<@>0u#rA0m$Glw zFI0EkBJ}7o=WKXDDehN(K{6mWoBz*5NGxTCZ_I(v!1TMKxe365GZM4k|9Vxb8Cos2qm0tG3AFhOPN5)n9>0Cuk=x%Pk%LL0 zY@TI1c+r&lQ|8v*F+0f*R(BznR~)k?&~B6nfu%io=}9-E8M*r&Gso(1E42nx3Vgdb zr6Pz_L{oCsn|uyL`K~n1~mSnd;ALP!rQJ53k2 z8%bHs`kdRHvU()j|3i(nUqAN>kIZ6z1{(@io`L};V>>Zi%PV5l!!`IRuCBzH;T2N_ zgrLO^5c$ip&O!shv&*C`34J#>`wIZE=H0h8MZ^2_jZriG?Vr2p8IXF-+s9RGX5TzDHd zRq8tDNxGJ1a*RJ^wmEhptA#P94Y59_TG~#5- zyK&==!Nm@&i%fh-KT9Sw!b>j1tS||_L z*Zzf>pOHm&TH6it?eq?A%4dBQDq8|W;2-H#(TF5J20OCMgW2UMPt_JSyFatuDi^=$c0{H(UNPb)U3q8}?;E(8u7oKBD@5_6%Yqf=wWj!%RU zMqNOPCLN%H?YTbKpPU-Z^21r5c)9Bw!k8mwEUYY0=GgSE>yQA89A+X`1+UllR<>iD?K z(D6CkA-?9D$gPjz<>GREpZMhF&~8^O(|qFS$L%TZ7x7Wct=!Q);}ZB{p~y1bnKF~K z!pJGSva!LdToZ$V#*nm+Sy3xLm-XuiXAe#{D0YASvDDSsdtv}>F{vpCySe^4NDGd6 zx9o+dy}H4wc%SUc{=pcj9I=`5So|Zvl=ZDfRp|d0Im_8KYx3HJhVPKy_aca`{yFqQ z*EZNn5*yIUw4Z)9ppl`gpxXU!8~4%`%X`FGkCfBsV|5RsO;|CV$fz;RWpfG&(af@Q zyBWi{_;LC~-@BrpXa}>>28Ib^D9J^m>X0H{QK? z*p%(BEW`{3tciblPX(X|B3#>mB<-^fpLS3fw8FY*CQ(LhvFXYgigris)a3kjShx7T zZ#nzmpjw1*{Jk~|R`w^*j)dr2iXaU7cAH`}@cYwq0`gfA^1&Jp9tvGDznvtp8TVdK zcY3kQZ{y3AW*@EMwRVOn&PsY|w7yq3pmgiGhM;7_k-ec-*DG%duYJd95J#~2Okq-jfOR*Tq{nKkNygg(~Bqj*7X{~ zs?FdHRvRH;8gr{w_uEV6VvYW772U00geOxq_|O|V`c28*uT8>{qthgok;mRQz^@n2 zHO_AyS(n?~slY#SpPqEzSa}%mrq&UE9}TPq2eFgRsWjpkrK0e;n<8)DZF;mJ*V))K z)!PSQ%@BAqgNp8ry?pC{)3nIdC`}G3MVxu^nN;a_u@jKfV6jmR6?}oM4u0~NIDQ;b zt>-)M6MnFGg{+kJOmTw-gfQh0##K@1XO=YaN}MRa^yxq$8OXp(IeszpHQLLzo)-1U zC>Id|mDx`7iNJ0~$9CV73*SWxgXLyR%4@?rCb`~PEa7b1|K4-MSw&cVW08Z=k3>Q5 zUC0mDfZU9!DC>$C*afzv8;&IZMdw`GCh|qyhHksaRM+?|aYp-i2COVhZo~ad1kPt& z1mC>}YE)h@j>~Cuw=w8-^vXrx>jvOr-_-qKuUi|Be(hx zg_xC_Rht4Uq0J$Y>hFDhi4v>b+mP^|+dWAh;cqtx;hh_iR9jc8&a$_F;6D8R*-gFn zC`1wslX&`Dm1l+@$pCSsM>lNM4A^naYp_-sn_V*K(9^J^b!aL*npX$md$n7~cT zK2i%hNI;s%t1>i+wJX~|USKb(7{DO?SyN^Hl%12Cqv|F zp#}cQKmd)W3Q;^m5h%bogH^ z4@@<6+S@MSW!#3;9f#))SVjJ4T|86s5%o|E&iU2}c*()ui+8&JnN?arM}-bPp&q@NQ1%u9lvE%M#j9+Lby3R?I}G=h5MkE!PfX?%9EobH;5)MXF6`}$O11S7j5j}+&k|CxBK8Jr^!mo)#1Q!%*k)>E8O});EN6{@To)2T9W3KS~BI=3L0_F)LaaVG}QbQAq>9^v~%H5m+H=0&h zj;g(BJ3sInbzP4gZ#(uMf%652Q$K8daOYd((JPZX;cPz<_E-s(;;Bd+GlL5c+YcKi z%s^dpg;6u0Tt4utk7>USP+}1Feh?)O%Xj?TkNm3&%a7V!Mb%i+m4s(79S(iH%lAx& zi|m?(VFwpb#N*6r9d0ZYErWO`FSdAIl<)$ZgPkBVTZo zq7)8zkHt(8D%Q_y#24^`3Rh~JnC9=%%gF_p*uF5z471-}=j(=gh&# z7{t}>5?2ylsPj77!#vJQASUy83D_3{^Ovsf6(HUZ zXg&BSopdm+;ZBi7*(MW+s6Z`(kSJbR0l9&QZ4Fz8ZeIVW6oW*id3nUL2sfu=#0@10 zShGL`6h-oCr-Jh2EV6})-(g|jv1DGRB!o%$jCZ5=@N1OH-#LkM*jA~lj4B3q@6WH9Tnp&WqOAkbCItPBMmY&TDB3{EV*%6DsZG`m zT(-Qye}T(mHVt)Yh->k}KcLee#mDJ3X?sES)vj*SV#3Ow0zlpFOgNAbKC%5`R+R{w6|su0&6Gv_U|nWO z>_K7+m~0rV3y0{3))TH`1i*_I#8=5qLJMGYzshNBrS`cDM&%jnCXcQkmv1Gndsid2 zd%%;tsE;qk-Uf<8{;n?15zz^IeULoZhg^3hfYk(|l>gXGPSMeh2lEzG|30HvnV#E` zCtW?sUIB*Mp_a;Lj;e}qFFcaskvq={Xq*#+u+9&fTI!QB;?`Qus$@Y?-xtBFC2NVq zMcMU!!uZ=jp;-#|YbBjMmb?H?+G7x(^~3!4`WSu2e#<_NT$3YIbx3boaMokwZyxG(Pi@h8zE*2b2S4{lWhTIrxbEJ|;NMZZkp=K7@K`i4hZaiy4X-wd*L*dM3w=VMt4fV?Y z?m!Dre7gHBpng9J>AXlm{J+$6Y$b+tD``t4Cp27H7L%~+B)aTnGv5%#`!aD;s2jt% z)6n=WI#AS#T;j*0tBCcMnJz1fEMU67EwGRdSx_lnV%5u(!^)7+3#`?&mf~!6oaTdO z!p=Cp#(K$cCHSw9ScoY6Lo!5^F*T&H8ugYqdK~r;nVVLVfOmX#iPy+#*x*g3-^lrZ z=!}~pKGpxu|BBY?^OF7ToeR6f(9#9L+4wBHBGkd#n$|8|{@b!R5@(cD6j!MOs~aZF zDtE91ddYqG9=1iMMsf+#l`ehNppZ%LEqn*6e0mPp-5L{wmqur4wgT?;EXcN4_vrr` zK}SPL;ZO9Hl9>+-h)n4eM3zaoPxtmB-qXO%E;v9S0mVMVb^Ws_tNeJaovj+=f0T!@Rh}$+)8G84 z02!%MjUP8F-P;`GO2{%fo|R`Dg#`WwkuOq1I=}mZ*C6rIqPH_;7sD`9OnD{Eu(9Oo zw3^bIeUOUuW5CL)tF|wBOR+maZBgH1wUpnvbZ;b3tS^Ftci$qel`oOInrn$63Yl=L zK1Y2W^DivOZ)0uP>e6j@({0t-u&IKG%M_un3k~NxK!QtVw*IM~)k<81Sw7C8s=gqwjNDmwdO*f-H(z0Gq2428Rn?vWMy$nVNRejAT_&`%)L zaaeH4IqkK`fDphL<11XWD>p8LRfo^74@T>}P|`Z8PAi1j6{o z=j&17`S8KogKfxXa^y3H4YaS=c3tR(3LH6$rvvpZck+L%NrmEDkwPfdUKwn7u|s7O zodFm33#Ql?=Qh`#usGXWRdkL{-Di4duYbPf+~6MO`)pIEWdheUI&dlQ(zjL@J`13e z?rL==JhxDD7Z(@c(f#j-)EU?II4E3WpwH#jxhWs%0kn9Tw>Yu`XK1Ifa}uoR6k!mX zU49}j_<7TV2o@oO2E>i=J7TWm4FbMhae7-nchpx1I2IbZq309^WM^xC#}MN#V25b9 zl8(=ITFRS%l}StgOS5w~d)-6j_DH^w+T~c3f4M*X_-lJq(>Fj;de4Sx-(zEk9gm`{j=~3gUADZPo`_!frvY^ag~I0(UH>@1+`g zr?ZO8rYR?(Z;~l=XrgvK%94u9bvFr`If#VOg9k@qzL(8`nJOLNH=YO0b`O#*yB8_d zp%#EYGtAC(Vvsj9V2b!Jtc02Cm)Pt7mR001Q|9Ly5k@p)iM;?Gw2LjQ-OVt?$0)4k zuQA_yI)*KWjy5Q61e+G=@|oI>+M@R8`0aGtT^qJ_B9*HPa*aqPt?X_zp#Cr%TR>wn zfplo_@VJZLZV{3XCAakgO-ZnF_gx?^;{td<%SYQ9>g?Ef!Vhu>uiu5kXTT*st}a>;5 zM91v~@1cMpZic3H-+{OWmHzqsd&mj{utKb}(~ZH@w0-c5PS$BmUs|1zYtEn`zN^?W zwsNELmb&MFlIGj86hl_kVPsOSo0GvcS`d*njadM1^jyY93q_h(T*9B*ySYu36fx64 zJeQO!KiPU}@Mm7}Pmv#YmdZUhqo0oXgh+y<9jr+)8IdWTZ2Z|?_aD96hz83B0mp*p z)QZs$ZvBkH>(@gxk)&pvINW%NLpYz#LJf;-0DgRixo82jlpAV6vLUyQyktIC*Kr%X z0wv@G{%0DNJ0_;BB*L}6bEw_FK1#RQep#&>)zLL7gbZaZxc}`KZ-Lu;Q9lXe6`KMB zss?NX zARI*Xb~+P}EO=#XD9uhbg|1!_=3$;Oj&bz<=%Smy_js+A?*TaKx4#J@RaC;30+0L! zy;%04v;dLZveAp5ebF+qdzutTWPk1!sA&amu>J(!Sxu07&if&K?gek=iG6x^f7hCM z7wf8wts%GzzjBf`ujF_MI}5dXZfRK-KL;!2x89IzogK7T>7XfCaS`f_zQsxTQ)F3* zkf(DBDKS8XFgXc-cYnK$q{OLYqbcwnS%klt#RNAP@^UzgoM-H1kK*4YLqqWSY;z+c zqm8D|OPJQ80U{@1(v#g|N&Q_3x^w6v9t%ewvc}GE)ZZ6wTb3y`>~45ew4C)bz2u43Fnj6GDg$6SqS>eqv;u+{ z>{HoQ3z^FVDQ@XWjiCobw?Ppw6pgTRW-uH&c@O&v3wsdeO;K>3=fO>5hU8g7mjawh*eu7QPazDz4kpBfu=|Gt84ESXOn64%L!YJBn?P9-G+r4~rczG@l z6&yNc_;>9O)Al4RP^YkEC1a~_O<@B-+Qw^kU-q4ItrJNv{$6Ag`gT{`h(p^R<&=Yk z*PNczM%_^zvgG(>Zr4@1&SHL2Ws*ci)FInfDLor5sMVTz7lq<3k0k z@sYTg;%#To-wJz?R5Tnu&n6r?{pf7Qh#43d{Q*t%Sz*Av{C({O1IYc~c1X%yXCuJj zm!h)K!p7*vAgAf%O8)uXBdu!>*&nH3CxX0O4pO)Y**rexZTS zY*>GNDJ_BtXmV2T2+?1xn+%hohe)1T@D1%asWR5ryQE;bh*>DR(9KHi^!xg5+`lhN*-9i2s)iqle8!(z2UUL|U3cCh>bDmQjBh&>Mm`bn7VK|0 z_;ECS+Sl#RnZLtBKMqQ0Y;!FSpYajTI!4L+V?aUIJqtQg{Lf{SqND1m>+45DN)2C3 zDkavc@)o~DA?1Ap{kkYve#M4EXvjxS<|BbciST?$4C;*`qi5^jxc}8hwqCqLl*Gis zrKnUGh)Tq>!Iy*V9bF^xe9+Q=v*@} zTFY~8L|%=L{zeeJ9;MTUdyEz+?eV>3{!y<_EmNYlG^0%fE=ey=KTC;kfPhV zm@OhM^SdD2MBQ3ZM7I1JQD1iIXauO@tF&GZMF?q~!Ft!L?;bW-<_D}8AjFbo?Qy)Z ztQPhau?juJ__4u7Q9FgIQB~0OB3mfI{|I=SA<)5_s7rV~WJg#ej}Ms({lP^9eEG^d?wQQf}iO-HzD#a&Q07`t{EnvObWxM<)X}0F`w5hcTK?`bR(en!`*9hKE@gr zDPA%j3HFB+_+63mKU0LN=vi{Gk7p7ve~9f9pZLEQToQ;uv$L}J2Dz@wsA_~gF*isp zeQI)z>;*H`gFA?YBhbGZ`YT>+4a0nZ141d(!JvJ*O0HQ)Hht@dMy6?W*$u4fi zEW+=VYD-V%Rw>zstDu0{Uoy`STS0wpSK)|-zi@}fqQO+c&k7(RDy ztT=jGMQBQQUf)1BG-&S)4;0bqUo~h(A#;x@4aYUSB^R?lnuZDkg z3(%orpP@uCBNNq*@F zikMC@T;}qkjzJgP6E&WPQwE;$p4{_R;EF%6Ndk(Z$L-E_%v4BqldoG}kAbUw+e#J^ zZreiJ*3EKIll2K%@I2LmLr5_wbh6@M`++B;3#d`mDayDd?t4vgLtsn}tlFa+179M+ z{v*x6@kZpD4BP*%&PK1<<4EW0cXjL~2dgo853*;qm(~WSV3VG2w+2#%B-WWF4Xm9@ zX`^Zs>Sn)(H$_Jo;sZA3tSHDGP(N1ucZvuY9*mBSA^>QALOGHv_ z-pZ_zdSR=qmANL^M5`4!!A}!BuGB}tmvEn66~6=2e-R$SN*5rqtIOVsNmHbsl)zhV zF(NI3FTS5$ui5~T-uJB)@ztJQe(`IfCeuz)?_YmDEWerD_e$vgR0MHgVyCH_ul5HE z-MOM<;*cOP`S6^=#Zw+<-XDp{SNnJ(*-onJm5v9RhoSzrcHH$K(lR%XDI-YE1U~7@ zxhj#b5c=|RpOpOAu>40a%fwei-%MlaOlB8%7{8C?!s_~Ge^o7b0#p;ZyySY&;WZDr z+GX%DojT9gM(3wc5-bF2t9#&ME8RH z&TIe0lB*={K*A{(@hKN!L(BWGDux2p6OEA_cpqRS{?)^R_NM7%IZ&`=WtSryyx^@!IpUQz_ zuPa(_yZ z#rKF^XEDgvUUl6;QifF_)n>veX!QsGf#cg1L^Q${F>^bi&aO;k+ZyM{H_Xt<4cp~c z|8`p^y_@xZ=$eaazs}cyeh6V{p5an=*^}-Q)}45ca{T@aM+L6G0Ch&JIHTKZyu{?nnkGV!XU?CdAE!FPLVthW4U{ntE|MciSL#mh@p0fluw$$!b3^f2@_`y zj49b@ZP!tj-^m?0p|Qq@&8D_9N_9GABqqDq&&k2o)8Nup!B6bD^gg2R*JJ7aU%lZ; zHGoBuJBA#lE2TJf0($X~#s^s?WG215K}0uzf+U8)OaDRI92FHF1_hkyQHBnwkqZ-F zjx;C8=#0iavFN!tkx-jGS@0lmZXZWQgmpX9oFTyQ;T8C9ecN<#t0C4Pp=3eCsptjh zD*{c&4r-O>`1Ga6t&#m@HUN-6H(m!UJ%*45smOh4w)wXt;_u#-^_p|rySOz?u@KYL zc-_SLIiP@+fVlD^FNwO3ANm{CEaq5$*A=?X+@Jj!YL<6!dB&~$aC+C4Oir?mJlo6wUF1l~Qz>#PXtIb1c`Z}=N|-G;=LYR=XX z-(>n$3%x)#J=Bvif`AXBU!UTs*~6cUoRa}%E1gwH(Ow*b%>la-^lO63h#%3CH>lj^x+N5Qct_rvKLooIi^K{rf+$`7L|h-E8S;u%*e1 z%VA}BPX;+}=S8Xb3CB~^%TaH0)Y0{K53oa>Iw?A7umvk70Cl|PHB)f%1jDH=MT-H^ z6mfH@H)!n8FdkW)4saJh{IC0soS?TS_hkg7jorQGe3q5_G2i8i_i2e%M#$I3j#vpK zFB*_M4!e}T-RAqshmVHA*(-M+q^GNG_YYL9xQ|g~RlOR#XPDy(c7RS)wJy1lKAniZOtTF@VH)#LLtR9krW-a&Rj3dNE_i)E#_?6c3sN@~NE?YKj* zWGHlHkOU{@DnfGi(}-*DNt?&Jwg!%6-F8#Yb#P$r8t59Zsf*JG^A0XHSV!0X7Pjr0 z1}kvsEl6SgB5nI879oE(Uy~}OXekcsgs~Sfxz`>v=|N^tlpUW^5J&?52ezqH@}t(R zj?#xzcICS$qJXm@)tSJGl%k6Sw-P$)q@-6rJI)P6?dPNn?WY66A|g}*8diOq0|}<~ zCq;c*{4Hmi7Bz+Gv)GACuDHZd>Yj4QM4Ip%j3uWiN;2+d?t8-7=k6m)79C6q<8Az= zcPh=+6`~qG&Vi`|C3260+mNfGh|?Bm@RD*2O56H;V%>aHUR9<__X3FyUKC%Pe_!2- z{C+I6Y_Ur_ezVu?Z#rimM~i=&vx&1}@mdZWj>4%&!_f1TlBOOp_ z%e&gS+~jq~63*meB$$XH{xT~`&`)x$S@ENgG;rETT-CXbaHog+d!K#0*@OGybF$wo zoJI?3k}fBCc4vi*+PNJgqPSzd6^?&#D*I)3m$m04f6bX~cJUM_8@WpH(2N0ojmQ6$Ne(+ zIop(`nRrO@P%!>9x4s9=9P@85`c_HXWmV0UItIP?ev(k+1sp*z_VL?J>Kpm&S;K@t zH|q#pMuIGq>L!Jd7Hp-Z?Hjg^j3KdUoWuqhDrkH=GT%WzDQCVQ@^7)z-ml?JtP|h< zO&-hdH32abJrv z!j!mP8=W!67i2g1MRd`BxISo7#AnQbkHWqcnR-2IIpJ&He%?TW%)GVqjmfz8XNEx3X~^z8vb3|&LN}<1^q-TmatB*TAxCXd>62*=Py&Uv%xl(X{!(~O{8?< zzeU)64$t0Iws%d@^zo&W?ybn1jJHDRXN9WL?(VG-)>Vz9Wrc%(84oFesMYEr#2A;! zD*7T9yIfI8Rh*m9w(*u>T#(UY3bPoW^coQ>UjbHuj`UALCsjMxl2ydfu(Go{G5#Cn zvReqGo#GU|35HVdUwKY5uR!v?A&0xiK}CIIc$}nn+R|wC$NtA_SW}pjoHbJx-@=sn zzAk*G%z`!c0*Hf>Rx2l{LlBv-w@3d!Qt_?!8AI34w*Q$i2W8x;|rv$6|r@XG43&_`~6k>~k9cdj{O1 z>;B~zV`0=6Tg6h-^p)WSC3FF{~nK{4^gm{>ah+6W-wj2&KP)OPH7i zbz2c?BBeYY+Nz;e#fJ%WevNmM&Gwb=^GN!WxKDT*7I%9vVbbwX;9Hox+nG|OLE+8~ zK-#Je$-fiwcJ&b7M5^T$PQ1Z#ZzA}8*$P6qhn$C+f#O)kZ1pWAo#UmhUSLq40jnWw z%elN8d#4`tCEf@xL*69nI#z%Evd-S={$jvZ2$4U|GkPUG9Ow2*8q%v6pQ2>Ee-65s zi*kV<9IX5@m{g2}bI;-lG=4O{7rMYq6h$nKvl>4NMv9D0A+EZwpI*bHhJQ#IBXVSJ&uzQkIkc0^Bq_ zsUI(hH(8-n+fXW|L=ha-Tt~kOBFGD9T)4e|*1DOPHc$9{?x9Is6mQSUyTC=%TVndK z^(Cb8`<~e)HDa@F>t&CPWjzIA^$aO=OJhRfr<$QPU32|On>4lTUs%QSOTng|HqPaB z0&KFm3ld=qy_+sOG-_Ay>OL5~f~70nXtCDDpW+jf+YpB6Xboc@GPNJ@(H!tB!~wWAlwH5qn#k{NNDp)FLp1$HDdENL@Y`YVt^)wZ5iQw>G#l`HGF&0 z7Z&03r~^%eqqx2-)mi4A{c@jb;z9VoX^}yTgP?Z;azXa}9QZ+x-@14CGRq8D{Oadz zf1DX*-i)u!1lP4oC~nB#G|5%0bDw zG?$UzfWh#s;|*XcEuBBBUvntzs|RCtEytOP_2Ox_3ycTkKwmo7+3uLvxhL$pE@?zH z=j=3n8IdBdR&7)4zx&Fi3x`$@`PrS6sEf{4ackUF+*f-{dHVA8$Kn#73!POrdL^hq zcp{}=qhBLsr{=bA(UHdp-S;1G7*CiR8;qR!K&gnh&u=RCEm<4xm|u&!{$kok-^w;7 zA0j<8e(+1X?9|d)ih?&v1*z#c=KRL#pXeKMgFs9>(Yf=vCPv**m3J$a;hlPQv*8w0 z+IQ?d6$n#Y=I^k7Dbr%XGa7$|Y#2$Iwz9Lg4;;6Tg3STJb3IG4||5SS)H_X2m84$?DKi5xL`epn1Gib}3Z2Ue{59 zV)F9+XZ;^#>nG+VEnaz0UvXPax#cuwG7_+XgNJHFoG_0*KrV)V0Gm`qV7{KAQq{Pk z;BMJW$+DfD{XYP4K#so_t;YK1%{dPKd6fU;NgZz^^`8;JzsQ04NuHw^{T=z~{iXi> zW%AFRfc}fWbM9BMCoaAV^Pgw#O3tsgt$7Lh2kkt168bqcAH)7mi;kUx@rHSnpAkxC^-})R`z!RWhW)T8p8o(xyC=KR8|Uek={j?q=F{UepBK07KUV%T!ODN&I#cl8{}S>qApZjLFR=WPG8-l6LSp_SW#RUaye@oS zkHPDimi>^fOVPS!Vq*WLcc}l;SATkT0s5b&_5V#zBEPlvG~}b-sl)dBw1STyH@T_s zTyp-C8wLNGiu*7J3Qd4^;zI2P@T<{AB{4*liIQs^`P1pr7&rP)CI2Or6Dj|p@oRV8 zjQP(7%72amdoH}+lgM@J)oZ_~S3-ASKljiC z2m0NBUfQVsDUrWS{%-US=S5)0GV&sDKzQe#xsU@Lt)Gk6NBh%S%75MgZn*G1>_?9i zf3a>YygxS7_rW;0ZMm5HB;-HfZ`9!aD(gg=FHY8IK0YmnILb!!*2rIz;q;cNz5?_w zC_w*0Klra*gv@XI8=u@(J~HXi~1bwx+O`>DKlfQIi0*bYW$ z=4kZC{6r2(w0;NauiYS{KjlBZ{_~#&b(CLyjQP*j4F3Dbzpr_HQ|xx%qV)@7JaEs7 z2V(b!YcTf-Zbq`O1M-@zU8l8h$>wG`y~)BqNy*^B<3|5&CV6_fh_%VE%Ip_kK4J*rRGC!CGlctw==mB$Lq+LpNRY_-hZhV{C^bP4!$j4AY0F4 zp4IaW()7o9{69wjV>{l1{(Py_El;e@XOgdjB)XFOO_N|Gsx|oRP>+PT}@yqQ^B+{-c~Z3)_ny z*@*pHD8FLl&uBYHx{a1U=0B2z{eWc3e`IGh>_-aaCxJQWUwrpjSdaI9ivACOiasy@ z5&7aO^zT`982im^#=PYIFUbEqdN)!2qbxm#{!dZ<&`0fK%iorp2&z_ol8fsf$t4|0 z`H$%j2UulJFXZUTJ!j$bteX56lK=A`B6qCb1oLZdTXh(?VKe0?U%mirqWs6d^Bi0^ zLTUL3_8&gJIypb#6qkt9gwt=l|CTkU+$2VLJ-5hzdMW=o4#zpYa3e7Ez$Q2W3EqSK zc*^H=;`qgi&L03bZvxKSu?c*m}Voj>} zy@ON5{xLJ~_+e1~V?>GMDZE`YE{?g0vW*!hdj2bmWFytj<-i5H9JqhF+(hzmk*DQ- zwdX5WyWf>BY9gh}A^*uHj&+5h-8VKEu8(m{5XY-c(!z(3od;vg)AkT|!Tq^v8{|JeroT#jgghZX z$)%i1&@FN+E5{n7zX$ytUi2^bqIY@aCdfZ3E4%-j2>y}CCKzYcT#Eg(noGN39-c)r zx}pD5-VDrt3QIBnDUdoKm-A8nWBOwLBh|u@H&3d??I0!RKV}1+Y9Qve zMt>*eSI$QCw&hn`5_!)6{*pxgS}FP)aNW#uqYLJ>T5FsF?_WmFBkNxV?wr2`xa9tB zBf_D-!K#vIG0g%5*)? z&=WY`J9HY(Ki_-eJj~a6<~J|HJOjVqxdrmLrLVjM{;dmMBL6KgUh*Fz2Y^M=@&7{q zv-hAk=062_wczh_-wXae=|=GPG0Y!)EQj9TIV>IH^Vy4e@f7C4C~la>m~ol%6KNFfM>&El9mTwJ5+{GUzK1H$gabj){d3qM_sv;>{eUVThy3Kw zZyx^_$bWXe0si0g?1%B3-)uv!TQ{o(^B)8J7ZiR_6MNm83O|6HvZU|>I1bnPF!xhr zoM(W`l%EJM%QF*&znA-FD<8k+WmcaVihisDgTi%zgi^w(Wmkz z%&#gR!u)48cpkcN8+gCggWR_j{SP(=!T(^P2L64%(uNofU#SAi3C&3BFAdtC`nz&J zzNM7{%ufOfF+T}l{xi1$^Pj3{1g=w8bs~cM$yc+M3V+zIdXU1uulZK+?<=|${flM= zz`tN7_?Ok-e#&$QQpJwzVmy6(e0>Ho8i&vG$shZZdIFgLj1MdX|Gzg0`Bl__@oNjB zQOtjKwm^Pxtfw`JuRk*n+Jk$W?}Y2k?Jc@9H^x0hvwX4p%NEX5Vy_!IF$UXPVK*G` zd6^6ce7Ve%CH3o{PyYFKe;@c0$15~`%_QVMwVjY(-BOFW$C4Kwgj}Tc<$tB|M3n!W z+5*=LKlJf>IG`Nbfqd)pxv(BWpP_g3gm*l&e>-Kkegr<$2IOjZ{{{^GyO^I;Ib*{(G1| zJPVKi-Dmf~^P`{n;W~Ov&lbbqm8X>{(0)Ixp#K4m{=4XWsEw%7_nm@_Q+}eLKMSC@ z)F4Ry9Y~{t@*m2tPEr1IhWv>yK85~0U59T@%1=(b0J%%ksYcjNO-~oY@l5$?;CqHD7$xugdK$sgL=flx1uKP|2~3(I}*FWbTI;lH5w!yh19LYSYl zh7Lf^u%HwB$=rXS8~qRC<4WxQw=491;Fv$?8MSfcX#lH2o2|xB~rKDmvl13iGV=pO=?|z-zu?`(3LWzjL9H5&15p*}R~sM?@~Rwj zA3^f&$A4&wWRX5_F#mB$D)vX#bnGvlKndwjB;ypY*_jf&4V%B6$qhiOVVKGDTKO9< z>Lv1ODQY66!S`R1Y-Ig$7>k-nNy70+CU@H??gxJd-L^>mdIatDWf`k7P#k`-{xsi^ zg!2K3{7U3nqvQRsR;8o)_mxC=zMJV-|2W&okCtoA-#;||Oa*_Jg!3_FOW40^goJs@ zSSbwc)-iN@qErk0dL}w*aeS8p`)TDlHp1;f2liXC@*jrz52yS}^n=MnHt;TJ^T+KU zWMNp3VvhA@6?yq9zOF=)bE1y;WNOWujja8w}IXDufqx`A7IK2h&6U74JJ9zK@ip?_S4aL$H*82%ma`gP6>O!e@bmWw6|LtzYo{FTGE8v`8;xM*Eq<3y1FJnJ-VJlb}YOe z)`z}u3~bj>jdvXS%j3u&>!VWp#`4d=`1uC?5+MJE01NJD23fHX8CvLtFDROn;u~XBbY(JnD;fO7_8?(FW^Zo>6q|nm`s>0U z@{^c9U_($j;m@+i}9Q{-BAD!|a z^e+yfe`5&qx26z!H|dSAJr?Voz!tp|>OD{Io=$|^!F(KCpR$An(4VE`Cz;yswjC$M zpW5GX!Vy76nujOIf4Hw2@}GdOVLB0VsuEuVlOt55000sNU6D$o!TI&Ch`jUI}#~dxq(H^#&%*`B3YcO zjl)odBsvmlc~k!#F%HcgXL~xzA{V24X&C*fgaxr4Vm>|>jvwrY&@T7Wd{iYguCIW` zSNf=*9gq7D%UeXHJVRy6kkT@2?|GNu_w(LP9B1W4UpxIYACjNO#rabGHCobe`BRRv z9L`5{X|D&p_u~96-Y&ep9?iRK(nzG2>LDo8xK){QA5QfcuH8tbiQR<%O7ibA1iOe4 zpkbreqTwNbPX2;oNyFn$)Tkq1yN2vD%HjN0uxkJsMi8jc`jD8#Vez&XiTow<*Mc+A zhuChhJT0}L@Mq+0k&0^LrIz%khc1SBfQxd0pfMH#VUyss+!#U3PGUQ)|8`pc?X>Bs)9pz9-SmE+CQGyP#zY`fjI5Y=xs!i zUC}W~TrOw`Qa$PW-!}R_Se1v|KT~B~)XqbOJ&@ygYmr7KhArZF4DNyBkjk@oGAV!3 z2grF;mYxIq%h{DkZ9{ejF?K@T1m6f#$6X~R?zD;>fMSDD29i7Q0(_FEKriB5Tm4!Me# zRSVLNf0_JKtHb*z&p;)KEX@G5D_r`|^-_4PTr1bgwKC|UULvnlNy<~M_WUYM84~|A z^${GVVqXl>Y`3cYvw!a^?VqMTK$-ky`olov!|WfobR|(wB~M4rvTRH_Pa4(|_m`45 zc>iRwD|CXUQg@s&Y8Rb`5L>!-$LQe`=0wtD3?e&5Bp$>h)ckV#`NM9NAweX0dYfpUx^+ z*!(|-&1OF_|Cg~Jvwt%0y^V#;-%HI$%wjXm`^wFqvBy-Hx64@2{F&_<>2$!qEN8aE zneB9DIkFrha~uwbbA%)I)9H-;Ix;6KC)<2P>@l%Nn$9RLu{7Ij4;D}H84gbbWz7^-F7%LL#Fv-Tn z=&WEIXdbb1%$?8t@HEL%7~6(+vQ%DFfsaJzL+@S-h+ zH*VqQ;5m9F!M8FmrT1iJxu^xECY9YVP1iTHlj){Kkiy*OWoB7kd^w-{xqsZx=MKvE z$LzDS^YYBhGtV>oOw7Aak3|N?zWelSgBiKvDTl#aX(Tc(WPpQXN{FvAuNe(10`iGG zQ84hY=DQ#eI&`VZSlKYvPivrTexjI~Rh)%25;?3DD@?{3PB~VmvzY8R(2p02?a8hL5fTyOPz_VVF3#@EbFHZ3s^gr z;~^R8c{3Dp**Bm8EB4@DeDeMtLoOgDsg9toqn0BxeU|yT$Y1N)wTqI*+RM<6nw`Yk z(f*0GO5GKF+KF+=EM?)*(!!qV0XeymWkIQmRQlg7ZSNVs2CZ)ng!8MTv#cj$$*8x7CK7 zRg{YgIW_c&+n>6CCEru&-}-~mpk8Er@b&47Yh>DCjj8=QXK~Q{! z^QQ0zMV7=<|NhN-=i=Gqxh66f?^cw#DfGSH6%SYQrrh^f`c*HG@q3Pcm4{}4R19#6 zt>8IYMF5JzIX_hIyW4S?pQGf^Oh4>LT^ULrgyUxmEN>qzWme$WsGKYc0oq^g#+{c> z=cu2>DKQM&%fYH?3J;glWpVcVW#nvk?JGFWsc7CLptCcMn|}Z8#TEc^jtx-GaV`%- zVnOLwSZ1WtoVmHJ%BxO)*?l3q?2AS6Jom@<1@-f~>Aan5J=2`8ra9YsrMW?(ampz} zxx+Va&5WonyKHEw6}9!lCA!@*y~$v~oQ74dUG@(e)upOegJKOj2Fqvp}`B zlTY~klJ!yN_^4^qES{rq4v@zB9$3$aA?HR}G?t`UoTE~37pI#@HG zSkNKKzq01YmuUWcFqiI`L%Vo?S2KFHw`!=S&_(Df+sXg!st?Jha96t3{Nh&gi^oWe zQjPJL@6Jn9{qL)YhTWx_0oA zR~@Pv8KBmMt5R>j=R?=VRvs0^CE!pKA?n)?!BKEu*6{DQ0}s zsN@2iCp+TvOMcjfazEKw3x~5Apq5EwKFW>8*W!3m{h7aM;}zwEQ;P?*{3AfC+FDp_ zjR$mM!^4V)mBZ+OBjUJh`48WKS}vNg_4o!v29B?^>6e1KdvFTrKauV#3i&FXoyIrO zJkyEJT^)e?DwXJXa$A^8<8ZknKGhNb|L}imz!@L~7%>G#p^ZEa(jgT_qbP;cT8$w; z=`bFRO(XGG^h!EfWcw8sN>o}g*vAD)cr{j48Z$Q6!9g0bv6}r^s zSx(2Xdc6=RppiVM;|;j->UMJ|lHU^5dbc`IRz`nV9lYJz)hw(IEB0h)mJ~;P4C%qT z)ZLxiZAO};&AoW86L&hW^@8#I^xGk|O6Bu^9&q`H!kgBc_E699d08m+f z(Gkkeaa7W_uPNV2_@5TYY~&au+_lLPG7CEYPsh#KDAcz<^znUl6?gwW+6T9JGTKo+0&&)W~iNIWWTtc86N4*^(r zhk-phmU=*v-(gFcI%E|qcUXL9&#`i3T`4hIb46(y5~6j;GgwoHp6(9UnT!>l0Ho1q z8*7B6aCiRhFK=|3uB2E<4K}U|u+2!l-bDJK;+1{{BY!*R#IdRU+oIG(O{8w(m-cV} z>}+mYjN^?vzn*clbPcJ)lHs`2>v|4JlT*=WW3Rr^p04O zQ`3aB#pzNT+qp zBRHP>7we|dQihDzDY1;}FugBn=H{QGT?f(z!RVJY^UA->)o<5| zva{EpsYYiEnXWh76_t(DbG0jtxC~uPw}m%KD?>X&L-wGUq*?pc)f4Cx5=F-A8$UsF zNbl8DXxAxZyzT`0Tw2grza@CO7XPZm-2}C)>@*EZ(c%{zSM6|z@-bebD&WMa@JDzO zros&LGaa(w1ypPw3k%?BmJe82orY^fDg7S{M$$k+eE;3~6U%Ex2is{A1~F zIvP!nvoIEhd?1=47s7HOcw)F|Qqc1(kAC5%Nmh^EV_*aWD*NGCxZP^-4Yz6g?L(U&|Hcb;uH|$sW8lS9Gm2CH>ph+$dKCHZIC#GbI&l5j$D31$@R~FF}G& z0oeixLj==6)m-G;Lxj>xC0-9AH7c{^-Sf)Wf-N|F}=>=HL}#gmXk?5o-f=_r;NDj@BkDH5&zf+qR$UvaliT)H(z-RUkviSB@R z)Pck|aAwQt#Ch^~)jBbf0g)>Ec@(?B&&tR&?2*dI*>cr<)#s?2El^4{`#DH;+<7_H zESivTAF&Bi`}_MDq^?7b$2y3k)?_31!KezN(Ah#E87Yo`133?CQ%$y4%r}WoB3;M< zRC`2-=1X=V5E+iNAZ;&+g4vX>x+ubyPYkoY=n(o3S-ytqq>h@gM$jDZ5JE>ys_3E% zu*p7UBv`Qqq}_}}*H$7@kM_!L8oS8I-Lk;zQ-IxKDP)nL88;aD((TTz!3HtNxL$GPvvCO$!Y-5ly3x=S^=n{rpz z_eaKoJRpMFKcehFu-I9&2g|)X#HAN^a6}n81@rFUUc?4#NR6%#^vFtGAxkvh#w@Bq zb?OKA5190POf$|4LG6jWpwj-I2u4okAZ5IrM|C-tx6Y8l#Eh-i zqm+EoR0jqHSWCW%j9-$c!~K{o!tqaS_qGOF_2fCaZxreNi_4;Y_Br)mexf)WhggcA9JG11FZ`wr)q$AQCaDy6fj#D&HezML|hqTZY-r((N)d zvZinVMHIzeVEc=IB5#Ks{Mrn`M-@awut0&0ne;thJ~9IpycS*Qn1Gd12=H z8n0S6n!ohsJ6al}!gF4*meYB=QGn8r_)1&&QZ3Dk(;{oUaxi^ys1a zJg?gCAg?4aQV>mF^uYHSZney5yP-G8dZ?h=<-1X+kU>^Nc6IM6S*`9Ee~hmHwLN&= zs$aK&1=ML?Er388_q}oR6)g=JSU-6p+mjMe=us;+1k!ub-3umKbpoS#AVM{adVUSH zX$^zrn$`qAY-4QL3>(+4sOflchCt2CKyFgqa6EVcHY%66Qj;YY{u4?!lbJ{ z2i0SbBIA)?WDIJF&qq$tdE>K?jl4H5D-1LbtB&okCe9khV+FACe1#_1v7qTvmHh=G z^el9;+tB4vl1zs(zUW{Knk-hJN?13RGq4_PAk~N!krNG^N3?f1-w^GI>u^GzA=(?4 z#SlOo)3$oP;nxwJl zmiq7Qbf{M@%8;CeY$8h72eCQSy`4?lo8v}`=xR^ zeMAw)u!FKI4S>{P1!PnWGMm%nZ|M#_2vLFhs1q#MVoLPUs?4oC-Gc*5^hRo-c?S5j z4mnt8o`f`=>})@OMX>fixzC(wNB-ho#iRWzY>B({PC|DXWHIc*N;0y5Dis7LsfwLk z!C+h5$gDDGtgQplRtEJ4>(C-tq5jA%JgRycZEq~u?$$Qtm=oUYOUeu_$~Vi<1wJ_e zr=4tA4Hl7P5kcV!A#VbScYoWGs~sGiLBEaG%F>(?RiK?~-rXNQ3(RVoh>(#T<4?}= zz1NhG0tOoII1=BarIFdeZf*R3vv)6WQPleaz<)D4JG%=jEQkh(GCWjXDu|Yr=76Y} zRxA4HYDa5PN>ei>Z<(PChz4jkEG_G#uG#}%9lB;|z81ocb+ynmwT=a1rRFKiM~J|l z|8rSZHhgqG_ukK^LHGM(`0woO?tfY@@#~GDJ!eAC{7us9<-8uf;%g(PG`1>mT z@V6SMsnyf>*h7G#fQdLh*BF0=r+NS2ZLPO8>#amsvL-Q9EuheQ(6Dz8jHSQi34>8NQYnbc3Sk#(TNT8D3p0PHOn7YX)!p2=|$F{^$9M~xk8CfC|AH481ItA#dMs^B4b z)pKCh%?;F2+En9`&(Vf*m%G)Vky3ZHMm?z&wD2sqz*DJ(pK>di`=gmzojfFC5sR7m z`=*mjpMPxLN_VwmxywD=iY+>JpiIowVyeTLb;(%uyvEEdZgUawAK`o zEoq{=QP9#zrbxHQ>lQoc_V}h;xy{gX+rt$`PUzH)Y=7P?95-+P+z+a zCE`cS3aXtNYOf%*%utQ$qgBA~seps2-k>(1`Bb4=Tn014S~Dw%+h>5gX*cWuW*AZ8 zN?~_1yD=kM6O3Wx-j8sPk$iu`4QnC>GKHgo&zw#<^0d!!UeZtK z_-QBmh&m@U^7NDJb#L%^>hp38s&$hcn(VyFvoYlQUmS=aZ5m^@T?t3bCG+KkK?u_J zlH2akE*`IXE8-un`9`1Jz}l2Xm+My|NIT5xx4#|F(`cq2aDgfn$JtNHJ%H_0cOJid z2G~tqvS(e{%;(S0u594(6FFx$B4`_hF=985rz}gt-zV8ePFm9*59}iO?2^;mz+-ak zX1mr`S2TEAZtZD2Tv3Lc3y1k&Li^gk7>=uw3fG-o6^lW;f;h5L~BaX9)L z?juxDx*;Up2=pV76A1M>Nv{_rolcM>2`S4ua;Bj{(&2$u_;<9~$$Ci=a4(&N`}Xuk zooqCa-abLP&fdBb-g0jS z^?vJDf&QDK;C}1ZFH(2B=wBKIBdi;_`9#Y)mwxsr@U=uy0f~;iz7V0ANmF73Dk{0F zFu_f@M!2aFpPEa0J|WT4x}rr<^0+E91sjc3#6)+kNu0Sr%!FIu>evB*{P$+&J7Pf#G9F|u!zz82(us}5RX?BsjiMaX`CQyU9AaE_- zl~`x4_rm-9e`zqTXR);xMb7lKVYM`VJR#k~x z;HgN}M6+$Mnl5nBLC!W9sHtM>ibxA_tY9%3ZINOfHak+>hV89j(~&-{>C;<@+wP_> zQx~ely$jT>nq{AxF|D{?7ivese%&g2%-fn+sasVTW56!quD})`mDUuNtN@v6k?pzy zcz#6yR$17rsOY4Y`ZD9GiSdfEFt~%59j_z`!5ttwHsZVxv>fJgA45v+CQ%=!&ZiDP z_~nX0Ko1|9F|yqG!a&mJHmx|QbWoN}!SS10JK6?C+F1Wy@H~UgM(#%_I2*M=wr=De ziJEXkbw2a`1(MmENAvce?~Fe83!9UT;nF*OgraWeN#D!3_v6B&bU@0aA@#AwJ1jPG zkHvatY||Y%bpD3jXHPmKw~<1o=={!gQ{ox<#tnKlK5J8Xd~NR2k7m>L?_TbFL?&%T z!w#Pf*0HL~_x1I^MX~sorlZd`+0TASW8bT{J7lt)m$FgkJ~z~VM?WQUDP8BV`NsydCp+7rM`~|NWHqKn=V_dS*8d9kyH{x@ka54(FY%8QX)_W3Jbw6$SwmoImqcTd`rG~dv207o8< zv$IcZM&Di)Nn2`Ji~dT=Fc+ITJx@LBHJzgUA_#eaYYYK_B#U2i%T+ z!{;8}j(%`@vnaMR=zMerow=Q?N59~PEzuxK5^kX~8F71-5zWy1h$d0gn|wt-UthgM z#;MB&lisA0MWZaEqIUPABGZUGB?Tri@6M^02(u&+?-qeM``=OGbIT8F?YKJkGqTP=|%rjk*hJd7OoqN8Ca+v~Y=0zm^F4NUXUvfr@XrZUzbO zE-eyB3Kh8EF1YJi&cupLxBnIy?XG1b(?=-r!@~=F^d+<6r8l#f+{~q3&Yd!D-Y02wm*!7-Cbu!IZY$E+IAjX)inDRTl)m$)Uvcij&LDQh z?nLIysM~`bFyr)|_a?+3t3P;ef)WwtSN%cRI7JAPtN&XY2iV@ImWi~t5U>Gmf?cH5 zdktLG{2M9?qU9u`SSmSc^0JDUL(rXE!?5)wKXL!)t8ugLjyHCa^X<1kXu?J zrV|e%hh6J7?EPZVw!?q~cZ~&~Ls7p<4`WUa zN<(=Vi}P}!yPB*PYLg|bradZ&nw*Z+l^C$HuF8-O*kjmkNL@NOy2(*4g>UW2>@)&bPHCENnl2E%ap_fi)xH6>z&xcl0xiH zRj^%|di1^a2Z0No8fHCpa#M0=-Ed}yVR-r&z^13|O1UE@t(t+N*EX0)e!t zyzorTm_(aQs&liRx}1rR$G<5; za%gl+OWD33PVwc;>uK1=m!J98$#sqbntuJxLz#Sjlk;#cTK;spoTCM3K53rF?;Vn^ z!EIzcpL^if1AJU{^4Z`LKDMmtr^cDQvj61c7ka=XTEi8bT>u`HR2)AwvG#Ag;;a0o zE9PUu7LKeP$qxXl-t-%fV%iTK-s?`tqH)o~^`ApDZSR~`bSZ|9<(gLXLn)6ZzjEd+ z9v46Iot5v2mQ25JkjIY~T#iMtMwZ|Cs~x~Tw$N-I=tB@Od`Yx1$EU8od_eNl! z;n;2FaGqxU&cGUA*QA*{(r=6Fnk5UrTMz7hnG5c0`UKU$RGK$VZQ`~02X@u2y47|p zS33ebs_Hz9x>?!xkjzYC_V?m;54Ul3USxUaJ?2H`VP>VtLt{(R{vg#`6ufzZQ(KGk zl%K|6GTx$WL4p_cT;Jcf!_Df`(&fxo+VBhJuYT8OHgl#o<(AsG((kL>*swaUQ3*vNnQILIf29uqD`wtJ6pH(1%~;wuSf_H29w+ z5miYFN2}QXeFD~Y`>S&w56M&*;Q#;0MZ}3 z39@}(%fe0~o`WdgVw;vk1@4p6wTZuB9l`91U60IW&Ye=Sd3|hk z*Qx2tk&doY$1dM|CIY(^srA5~R)i3!wbC@uvCw2%^FU(1(CMHJPTGN;qt+*+<*)Q`E zq=gxX-7lE~qx&O+%r8d|^mNuEl|f;Pq=7TD(x|i3f(9%q7&tp;a!}5qBb}dWm^`3q z(UA@hG)(S?G<<`se-8PNN&S8$Mj;Qjbm2kWH?K2SM8%v$epVQzoXo2di9!`D!U7Sv z4y0HZ$rO=R5Vc!8{uM?EwMvyLBWt`^tsF#lH&rV~)S=C`vtyTZZ>PXfb*Q;3@;Nn4 z()%}Sup<4qK$QF>q)N3|sX=ab@oIsLgpN{y7-Si0>1Zwx`yeySl|FqfsaT`CRyVs6 zKX!AX)oOGTsIf}3D)pG-8t*a2D^DJC1V0!PuO#hrSRRb=jY!(3Swa;bPh;Kf#0(+Y zk;Ur+3hjZ{nqP!$-$GEhqnTeMDO!;xDj!8ywZ(;z#A0FqPnp6jQbIxk=}Ao!QNPsVN%VYusi%&sQK`|%)I4Tdt7(vzLNoIQ z^S#$ySTM9aedqa}hUek;-`Uyg?94mwUCzRBP<@nvqm>-F+{fGh-g&|j6pwnhe)(P6 zNu1--b^qKLgyQFuLwi)yvB>}Q$i>POO~OqD zF6sN`RF?#OOkOv_V2w@QisFagI<;bkO2&Tv)0iup3V;*0PfGm$LV#^5dH%U~A4s)L zq-8K-*g)GvQttA6a>pKZHDvwvqu|Lpy1sl}=+U|}bdEv&u*SB3Zp7D{ZIj6MyK2sy zwK>T1zxjT*uj@YH@OxOgwC%%nv@-sxZpd+~B;%PIxbI!{gN67L_xW0GqZN<~=5r14 zSHWZCdbwU#bk;!Rl>)zmEVGhwNc=O%CHumCsohLgd7Y!Uw|V+n2J-KE`#+w(#$rzY zLSv_M_a(n)03C1m*^KyZKqBR2ntAUamT{TgH?XHC6Qdv1SnSsjDS!e4-WR#Nu$`p~ zMm-uP8XArxt|$^HA#d8O2h0UBX_q!9anBaE{e~UUnXF!H!pdW-S((#|!$Z>88S9eX zFo(q>-fxHmv|ZqewHJ=Ev`G_!bd|tVe#tC*B&La zouF~v&aYt!+pJ+>-QlzCAlpQK1vv@+4a@agJ__kweEuY<*zg7FA z-+F0nKU~k7E%*4PvT_nuPZ@BFywP%!|Fr$(yWDJhyZB!+HVwb#K~p5fxY7s#ELl%kRs7%!1N|DS%f{ z*_93S0{y{2FaY$04hG3U1^wWTQbC>?3Gi!$|0(X4NG>#svyc^TVz30na7>3+gwde za1}+B#bDcSj@bu&8CnKizzokw%2Mr_64JJtT!scNEO4>5EXr;L9J>li;=O^n{fsZ{&;;f}<1yJC?d zc1R;rp@SS^@6>K~2QtHESD<~dZm~~B5;43F5-{UrWI1$zUEzp;s)5D^s6Vf@kpPYB zLo*3pK@*#um^pfWclxT5yBZmUO$DI})d2=UrBDY4eF8ZiIG;jJL`FAuhes>ZpXiTu zJ>?%z&OHv);h}e6hlSpu4T749$=FP)7uW*XNWGXH&;QU#GVJZt=AT zkQ=ZXGpxL1nZ4{dR4$R_JS`Xrnh0}dEr@%1YT8X4;%KQ3E>9`}=Dh0QO5{$Ww6i*_ zvX4iZxL1zyI+~c4Qi4oQtCG9yg-3rzm26?UsP5np^~8A& zL`!r16=ceBf29+$f*OYnKz25{0-0HHiO?#nnXd|TVDtSQ@tuGfcvYA}Gqp%1-=GL< zwaD^?2E}iEeq{N7Lo1M>in$`cO>={g!R6gcphdyuJ<)#W^@EyTXTsT&Qtj+0K_Z1( zZR$@NV`ye*^gBPbHwT2{^>h0l945%5K62us+W!i)kdp54Yp%unn@L~4AN7vc7C2Yp zzH$o-4gb0;fmcv`Sy$=>8Q}I<&pdwlPF@3OoCJ`c%gwA|vMw@Jt^(p^DcPpbP*m@*SQrx&fJuW!#2uS2`R#{(efGL7yoidHD~d(S5w z+PUa^GwS={*_ssQyp(m(PP^`b5miykT(r%{=NAmq+3P-M|L!i0&eODX892-;{Qvk; z%~}vd#sV?w2lGIndpwFae{}XF%Pc!@zw{x?*gQWZqC2QC;aeu%&4UQKKDlcTu#?Qf zHFLsOp7vq>4gbmqc_dEw(Kw%FyvJ6aUC9zEQIF+7N*d|=x#?^<%gkx=)txMUW!{<5 z@YCXb`sdPyLu~T)iHoju0I~zO7p&J~b)aae098P$zo5yY_~^KCIh2;pAc{mQl=CMF zP=D(MCEmwXO*}x1I`Gg4(yGrfbQMzcLrtDT>Jg1 znHS+lbno{|8;u<4bzGd+@^rtk)F^Bw)xk7JBNb#4QVK-^MG74a<-G=lwQL(>W8vXK z6`C3BBdLMoedTG*9P{Q{Cbu#&zDiAz$t7?~cge+5jo40AP%fn(HYlrKrxQ(_jV)!K zpk81;LLH8M<=XJI7vNd>l}kQu@yG6m&VWbJ4~xyr!e^j0$Ou%1Yj%zzF2XJ~FEaGO zenuUIjiB;OX_S8xK@;!bHEaMhuy14Y9;A-O3VB1Be!ZJ(@tW+{nJ8ejWFZy__a{7# zEF4kt5qSMo%Q;R=ii@S*1_h!Gc??sMLnji)^d-iO`lXmT~T~y<0)9+hoXZw9SMjE7GOtkVlz?S z!bT=jGaEatxpBzT*N$DL!%>0R1CG1}Xxr#HceL-t;uDuc|HSHHwjFfW0?mNap#JVF zA#9ruPhLIC;xT_atFSi28$S#`!5%xOyYx2OX3K$pPJ*$KY;!V;t(Ww3d8}?{c=Z=c z+4`_+U(AC)b{yC1-{ry>zX!Sg{0nSe#pmv~c-kfZ&~W4`pownQ>!((;+@4WC;AC^T z6g>37eXRax=D0|hW|Fqf>;J)J!u2?QWaH_TY@4_CCVk_XS25aL#p01W&MXJCl55Q0 zepJ{wv*Qn^tZe+SS6>khu{3klrc;js`laNn-`>MwpyO*9eCp0zRlADC)!&9qVe#|o z_dNhD#yxo6eV)Znl+>a&ZTN+=vjG~@3tt1E>oFEj$vuh2@xm)6zRIKVx?Cup+rM@g ziydoESFm`@=6bX(-5dWu7j)@15~jkvabLl^K@U79p^E>f!2kWgV3@H-@laf@)gSbQ zxBG)$@c%$u=G6 z8+cw6{X_#V37ip?Sy_35AXp4We2-*k^}YKn>Wv70Xt;C)KD!J3>YAx4E;O54`E9^j;L5y0J>ohfo@KIL^-rCvJe|o?#zG!s2$l& zK^78kM{0J^1uJ6#6SQb7(o#U=nK#=~{stGiIp>k1I<@P{sZ!lBN+K$ul}2r8Lo zE%{tRHZ1wPlh<(M+9q!Oe4X=Cq>jC~Ro@CVUflFQ&`9IOO6dMb<2SaRTb=KTi#}jvX1;|6tP_I3(J-sd- zp8(qSwA{9Md=~PBCeF0HAR}jVfu?{qv%9`vLrzX`B1cY6*m1+gQaPwYA*xV#*g{%y?0|h4`T%i32(r*v z9HP!(4)PjM9A%#|n3y&AMa#>7B`&z0iAZ26zAfCYVkJ8~kp>hik_3jDw0)hY`kO*vU!wS z){gB4)#9b7ZZ;Vijs!>rD^G(eM7tv%$kQCQbVoejvH~xU#|Fz!9D|bm%uHrp(GTYY zhF9YDG>EHK_UJ4&NbY1bznA`-};hn zs9&X##zE6&S~lo;W_&?aG&Oo3rzrTb#ZSZ7MkjC4&uM`%?rA7A=!cztK?-hf|5BFG z9w=zXP&~JP%ZZ9KgO;q*F<=kaL<2>O>!F>WXBCn)M7H+HJ*K=D)g?K(?< z^m)wb`q7rU8Xmu&zQ=3YRMO1P)SSpJHi29pO`jT(2zL`Xr|HMEx@uDXG`F8VtnLiC z-kkrWaYUVq^xuE7*s`{+HU`JfW(b?=zUT0`w63EkPu11XbEAG$t8>SY=jp$DSY3@7 zZ?Eg_+`5|kC!zS|XJYp&v>fY+(zYF48ZPDoS<6EcRN7vx_lYyXY8AOa&FiV`V*L;| z?eRP5$|u*eU;fndM_0ZRzwm^WZ4$8Bg6d&B(-Jq;)LrY1C1xmi23VjMMzd`6`Ylf0pFkK}r z{D``{Wj|!@@Np3F4;=A9>PY$pjig@_a}4z%YQ`-x+{gc`MfFv=F(=dg@0IM=$=#be zo0`*1QfNG`2eG}6!J$63r9Mb3qn3O~EPanD+?XFR$@?$e1Af*Zs?2=JN6Rgi_YwU3 zB7W-QZt_6!lUBT+XrP(`ew~7^v>gAs?Hm>2V1*oq$yD_g>1xHj)H>Souads68+D7X za?AGewWO(?=zf!ap;}ur>Q|_u*xAuAl$}`~U4JHy#miS)VHy>V)0bT1vF)C+oVH)R z$6{XpN`o;T2jJ;vO&j1hgX?*WdIK8$1J|EqPeW-Iekr(3WLH!JgW^BV$B)BvEx*10 zR1KgBo301d0b?D9a^t}-%7q+yifof?K8G^=ZJuagu~4 zbmmQF3D3}sZs5_|Q41`N=g_EGc)n&6Z{Q?!H{8Gi|4Dd4Xp3ZqkLM&mlR)|+@}^%| zMZp%91mHQ*x#kXNQ56hOk#@DQve!WaQkg1o64VKO7CRVQY9HKwma535@?c92QG$k- z1r3&Rn`i>ijIwSMCWTjW8s$^P(&>tT4`aEcpYzMQK^|;RjP~gRi=gj zE}IxMlh|%1kdGS{avpPl?fATfW@zOPuQHcWU#G6{Isj&sw=a;|MS)ghsTGul3TCu|8!37ot-HFWP!9wJ?gpp{NUn=-AXB||q{d>^ z^NJIy0;B-l%mkXwH8KfkKcR0s2>|BF#=>Ls1Qky!bOSZgKdppkkt8e-n8DZg;wnxP zg4=*TKf*Xk7OX@hIM>{jMnGR|u82bVDzwF%$ zSX9-%0PwXRGqVQ<7!YAJlo?(kVh(CL3d%-adU~NpuT@6O0$yF#RX_^`6V60x&kE6HzuvGdr{hU&}s@fSJ|FMYad2VKto zP3o6I3yQzI6!miuN6Kqc_Qpr4t+Po9S4{w~J5KFH;Y;g=9amK{F7woX7ze1WdppST z4C=J-Zv60&&P4G-^8maIJbZ4`)gnBGqgGAerasv>8!y}7%bZIds@4;FPrE zty#2>WMJ5C>%Ami|K`_C>@}C!q<4)Ek;iwcC!LOkIk@7nLv3qj z)CZileoyM;Rt!0~1IFa_g=7D4oFV1q+Rax^ve$PSe)_gVoe!H(xgeV6Jk zkHUQqi=IE0;HF2CZ?9ar#Nr3v{It%kkbAlcpX7Gad%ZQa?GLaVV+F7Dc|}%?_;q$3 zxoxguAh|}Ix1D%j0Sd17TAFe89YEJH?x&bQ5P~liz>KXz9avh3KMzi=n9l0eE~yC} ztn<@*hoa8_!&mr1{iCmf9|n?w*JbUdJ||e+Sg#XHfW;fGt3q}AswE4vN9SX%e>13@ zkD+&y3w7h&d@lko!t?`jn-lkELdvdF{xBHmHv@*%&Pcr*AfC;?i zuMu3=f7N6X$?^@<5y$IHzsP|%t>mNrrd->Tf{$fnVA`jSk@}3i?b@4i&oz=gmvNTb zLN)tWrUGAYaLPywBig)`dz37vJeGVf^Qp!CnFhbwdNYj5d%L|y$$n+^K($om7t8q- z-TU*WHrvM!f0?>2fsf>Sq}$`;mqe~M%v&?vpS`%_u%QKzTVFs4OxOdAg*2~%7L^h~K&aAg|*zCX55%1b(xn zS)tol{h9sM{;{k+tmp-hz~TTE4arFA&yA-GiziJ)-ecvI2D{a z-#H*D70|jaXJl*|i%>-EO4T~7#vWI-Jb||zUnm9i?cg@hqG1W=T$lNsx`q-+I zrsuAihkPt|&EtJ+YpDM*1Z#rcOKiL6*yDYq7jA32r=1u~{3*Eo5#(0}5BEn#V-Jk> zy6XGu4SP!$Cupzmg zPRPMph>t*na@#jBCqp&4OKP#1OU!xQCNMeX1m@gC*)m}iHz6@m9$e6q;{h}a$tNad zZ7xV>nvt&+q}zE3YDbRU=Q5|;fqrZ`bH8OwGvLOSH|_{+MV^4#xc=DfUH*Rci5(pF z^B1wfeyoB9{G}gf+|Er7Fowdi3)Oaw9M%emMx>F5_8Aj+XiCWw$4n6hno_0`Q>TiL zV`qr>L8FK>p#a*1Jw!bvGzA6T#oc#`Yt;nY6*_4>X!f!eSsA*&7u{aEQn0|4qF@y) z2WpYEM9EwtLMH}~r_eSroEi!QJ1IDIsEKN5 z9*+xwiWub{K@;>Ynb^8*L{=O=kEm*Y=Lq{8+O9hR#MF|kxbs(qC5p61`W5wy6|66z z+TNML_biFaFb+Ee61mhD&OHqdzd$qQc$j%V>Bk0mCz7Lj|Iooa~MN`@N(&28$Vt<3^1(+#?K&S15Z{7kDBH~gN} zGbzG%GMm3}**{-r`L~Y!c;TXh&ga!8Wve9Obu1aunJaS=KI6KZ!spBMa60)T?j@NX zRhN%C^`7i%#QoZ=-+vRr9<%6?b6aGI)bUI>cJz5RfBO5DfpRH%uAnAyY`(i`_*oV& zboNbR?X;dM3d>{HAMI+~3YL4fU;7zJp^ty;fzSS?xHy_e>c>rN{)NsTu7D6){_Uep zV|@no>N$bM%WofI>q@|*-rm)>=c;Pz>}oIow+WaaY&h_Diq+z<2dG6h4$${O6g1 zwJSH+=mDdF)Wi9&r?ccW4I)Gz>CK}u1O6;Z%!(kF=+9TXMV)JdUcLJh?8aW)K#j|u zK+IwmP!}OJadW6~Uh0_1%ngf?+T;x*MnXSI+b{xsagRVz&)T1tZS!^X^&O7A;9;tV ztWSi{RU+|eq(z(Yw8p=0={)3^5#DMd zGG4)k+ee_W=7MI}7a<2+qZu2W-z^%0ZeYII5#z@QsF{eX__e-DM3D-*ys^EhRMtLw zhnI=ot|peQPCPWykNnfpLG=CM%Op2?y?~omPZabraS}CyiO&;(98qt{z-tzi!pz1M z`$1N3HBkO~I((fv7@6H=xUUvu7Bi1%m&4_aOTmw_bHUOabtI5T+2g7j>tv1kR!(fa6Mj+5 zC@!-N_!!XpP72@8%_;!@RMPTS7XR4!%~ha~i*7}GTn04z?V=&lQ1u@3cXbU#w+ey^@X0KZMQFrn{g4&cohAPxSEgXfJ*+*dFa zMkv$!X!tuF#$)h5){Afio-gA}S~fhwp+*#NK6m_EKowG=pvC{i8Qyt~h=wi{G^qQb z232?o8k7c0K#jB{UMKQ`2LAomUOSno@HeS|no9E2Frs`tOM5aDIKqrfpdredP0$Ev zLMSMX2+tD}CWB&a1X3>6MnW^>;z6VH#6iqi8O8C?qFIw{*m;vo@#%SnqIvUP9!gxb zAbpx)0kLu(b<*5<)9fP znvn`tLG_P*1VrFjKWV=8&jKqD=;@IJD-$^ng8(mb86Ha55)Td3C_PrFA;uzC4y%r> znUtYm@62#xAM$Vzwti(ob!_!Rd+JxlAWP~iVyb6V&sXYoP}34m`%}YaNl@M#mVpd2 zYcs$SWkMK8ka-6+4_P>oH!2gx8VmC?jS4@ust6ggq^f8JG?w^8Y;jdl6x4zRTI_5v ziYSgsDL$B6GrN5JxZ;DE)C?+z%|FQf1t}lo%85XM4v_PZY1moiQ3GUn`ZJeDMKOVw zCZ>UC#Da1_RJwAY^){WBJWZxqVYy7VaAG6p^Z<*f@vA`pz+BVFpbNhX8Dt!#$|)X zRm{RLPwbCk7uT_(oY(&)_yL#*PHdXrA0(ysQrDcuXO6Ht!r9`i^n=RB@YtS zz>*MiBtGao_@=QgJ&WXF7u0?wFK#9kCL7;5VpkhpY(Vk(&ZA4!S0~{1Mk|sVx2Mxw z;kln5sZO6w`af#bqot!ylYWH{Zi%rR*jPIQ#hJ%iBUrbwpw4)4|M%nwx2<7dp+xWf zD5k(nhn>WiRB3tZM-qOWDSKOM9BvX{R$Dq)(2NJLGQZrST@_;?G72VeL$$oH57+;x>QN_{ zNZOx8UOA%!wq#uBt=n>ZCa{wG$CuTZPS$RzO^sL%jLo?JsWLErAF#$5$+kUN0_Rtg zLh* zc}G5Z{5dv;R7uipIjl?_+}W?3<#XSCeArn4^6++(RCIY|#_zQ(wdq}0zJ7+h=1B$6 z8aIVMg4Ua6O#9zGiT^|T=E`LGy9f5-cp*d!daR5s;*kq|7Xg~+X@&Vq)ZSYLzfHeQ z|3@d3{`4Whn^9KxbdU?~1liEvfhiyhp6l-c_riY@VUzd0e{AWOc-V3 ztXcN}RE5Q(A1zAJF7P6*pW;c?7S8I9^1P!tyhg*LmRP*V@#HC}d6rf{GfAR%PA3W) z9f$iCia2wYAO@m*@gn?_pzC#=x~J~5FV~YsFJ&Rmj|%i)x4a@{2(3W!a4$3wdRk~z zs3pYq5}V)xr!%SYPNI8fNm`kwPwh!7f$j@Ha!{=?T^v_K6rzZHlyQ_{B=*lyBelu= zjJ!orR?&tuA@e5?<(w%dD?lDHnSqIybG@vWbL)LIdgzvOQAL!|E$bAxF`*hJ@RA&y zjdG6%ZQq0cO-%~^9S2C2rH8l{btF~&s!OpN0~7mG-I#z)31dNhi} zn3xa;O+uWEX3E64U_2%+Z#>aNM59KcVoY36=y%tqyQKv)W@gSisXp@EbLqzFs_v?L z|GM|DyIq>pW{PTD-PI4&nE<(gco+$wRqn39_HPWVDzqcRstOkXU~3Hhp>Tl=4f%qb zErULdAtT!|sMQQ^3{fXVgP>|lMj%phw{xqC({f^1`3BJdEXqK2qZxM7nP8Aw+Jngx zA0#fJ?s%~E}G1!}*6CP!02%21^am8GiM^YS>c(j^(`l z@r6_N`g+_Q@^3k>UlqXN1IC!oFNa4csTHXFz-@~mA|e~7$hhw4(Hub=rM@k3LW)A- zSa!2@P)at5KaDu}U}#GA&>~cxv@JLyB_$i>^#qMA=J^5H1mmkiyk&*$h3EK%@KE7&Wgon zT6@IxfwDs0Z_))HH1+^LzrcF(cb@R`Wn)>nxR35LL?yAx4JY`F?tkF=p+0k96sjG0n z4aGYZwa`Mgc|)$Il8tUR#ShY6T(y&IAK$Jj{X5lrW6rShk;a58Dj*Y3>u=t;rqXq= z`v>h%%U{BO|BWs6C)LmZeBFBRu^&2v0c5Vn?B{+?05tCSuGXU-%*nymiG3V#I*=lh zeeHWH4H(IMkdRxxMi9!bp0~faW&Gyblg@ZE5EV~jsolv;xm2jl)x6+wpJ9C73bTxA`G@|P0>MHCjt4p9MRf|`v*f+8L z-i{&mkNFzeH-s5^$kjd}kv{_BHO}3$$Y^LPY=R0Qkx!=TP<&XX0;1$1?`A9(IF+d& zm3H#bJ)grM2!L2fxFCA&b zF3HfhDq20&5ql6bpp%HkECGuzxGHw|MeJm9^{jwP}UyPY8DK9F1KfI zb}|XP9Z|~41(6pA!ZKcm|DItU!|HopHv55W173;zmpg9+G8sFbe(bx~fU3vm*@Y=T z!LKtpKTg{y!(Flp|Htp_XwG5Rh?*V8VQU=^{{`tY0KB0DqQbaXC&TMU0ImrS@liq)@P=X0Euk6k@G zhvj*{0ow_1hog@VSk&|QHbBSaqudC9<^Zeu^zv!+@kZraj_xgh&5<;8N0(9_!P_my z_hVLXcAQ6tS-f)ZALxXx7vlfywj&0;7Qe4|K1r+xbbLSWK%+rB-Uj&px}Xoy2*AsI zKoab;KLRqq5ctRh!@)54Qvu2F=P(?Hc@gK!LSZhv_=q~ugp$Jx@abk8#?p&?M@L}X>%v-b~klET6VXVkcu{K+uto=jv4b{6ztW=-*|@K!Hl7i~t`EdTk=rBrO?W@;5Rf&0M2 zYUn5?@HE;}0QH4R)y37=#wFGM$SX(=YV>eex&II@x_tJ;a^n!LPx<7DufGM|I(gB$ zbGtZO4YGupiam>6xUQb)U#~iqHijS-r?JpFxJhHhdDJ*#9sIU2twdl2L>a^xsJzm# zz3X2mSBB(T@{O&^A-ST509t_!u3ImMBlAzm;W<)%0Jc0oK!m21D*@saIehq?N-kRV zBEOQLpd2dfeF+&Lly$^$NI?_FhVn?M6SPp!Iw3h1`A}Y^mV25iXn}lanuIkW6|903 zT`XzUY{|v?VY34*meW$UDhFGHQ&RQ{*+|uUHT@LuP_V9u6D;ZLiM!Veu^#qf20ASf zK2`O-0(+GJtlt^%DTwh)_N&9jdFtWtCn<`#B%KX<&>m6+8K3xtsY)^3eOnxX^GYScpit+fXNY~OW3s- z=TB;EvEH%>=_+2I9*qMm;!8M}($$vZ3oJmw?`2W%liMsbX0t%?`EajVh;wlj^*x-y z@;_zm)`!_<(sj^xOJU^&O2Wg9=Qtb_s@{8hdSf0LuJY$S4QFh5WHlG0HGe44vIDli zYe1B58{V|?&R+zHo)%GlM3p>0>Kf(fi9%`k+b1U z6cEWiTC?u@6F?**0;+a~<-oQ)jxAMgKJ_gNntyZ%oC9U#1GMM6z>9z;{<8a62Lb5^ zJlw|4`TmXN8p+xdxEdYM@MlAioH%qp2rfS~2mF!cAfb6ga9P#g z)>zr6B?i@_wlR2YPe2%}f94t8d%rkS_&p8)5PvOcAHBVC5}T;sQ*Uo3&fHXHZsbn3*9 z#kGLuIw*+$_AhXc>_g?-j@TAh#^*IWN1h&PwjBvTXLLN4ckRZXPO$pNw>NfUWtGDL zFw(B*8i|IU;&X9}U}UqE9jzb(Hl|EdK|GS2|K91jw3eyoS#qaWxG`hp~o zf-_?EfselMfg)W4Ku`EcgwM3Wnup=Pfv|+~Wtn(`kEqw_1+&RlZ}9i!1kNNFL_P28 zYldZkGwStvK`;n{S>$<2>C38h;n1PWs&m7KL0@#&aKP!D@F5!_N)OoPgnwSs z>OpBv_|cja>?<|Nr3XWh14|E1a(6#-GO~YZL*}^f4_&;F8Mx-dnmFthXnkhj38#OL zE3M4zbbHI;xKe8-&%CkaaK1r?CLV{5;%~(t&xn*?jp1qM7J#J{`Y*Z!epl zITt!e@-s)pxw#aoLCadL#afwSt(Ma2GGsDQO_q3U7!uT~f!Mvs5-U)!G8$n3nE33C z8uzXOZ-O?@_B3oM-(3-Ez-9phJhzJSB%*B!vVxh3d>LC5i|jw8`1v(a8<>-+Q$75B z|B+aG$jD;*n%obdZ`jx7Ay4;Oo3|ZW-)rr#ZO=pFp#6}3Lzy9cnc>W*b3`*X+bN&k zYBx70_5GdGS!H)Rx$o%n#K)KyW|gHu4_=s8mNw-H=)$s`DNocKXjoX53*FZ+rEJ=X z5jFevL)SRnO0D$th5eJtvX}V~Ek2cn#iE#P(Wy|7E$Tp_4#_)Jspy81GM3%k?e5?I zoyAM#r_GgPs1LY0b2xO#a(QO0HONIU^E|ZF5BpVVFEI1QLqUg2W0kxcwxGi$F-laU zE$EOy{1a3M?Sz#)ec8hjs_H7JhJr{1*pP`Duw|*8q(n`XvebuciMz`K#+1d{0(O^k zsb$f&fKsA#FN)N-=vmkv(etEr<$7kOhohh%qFnFWBOzajkf4?fB@_r2tN6>z@i0vk zk;_s=d?^WwrWB`&oaUkm-3xbjQ7X_al}DP3Qn_McD&CJpsdRsOHR@-p52q;jv!HhU zD&3!6GxKk;EH=_I$^)UJNs3g%HAP43ImiF1tlaye)!#radx3suV>@G7~0fTWc9_# zhcj)b$ux_QTUU&;>d1=D8*h8amMh?TA4iPN7D+yABhf7W=fO1XI!~EH%tJlHPqzyhdr}58hQkj2C zv;YJSzZW&=^k7zBV2vLLg1|2PzMeHEz!tcQx9!CKi7a;r@93tobA}$py(AK0D2S{5 z3me2Tf7JKy!&l;%oXTHPSTv*0_g4bgJqN$PEumZ>_``Id;it>2e)o5mF0$yr%!NO^ z%gTALNwLnT0iH8RR$}UA-$+(|a^;mbS$Wfr%coem;@yy`9l8YuXpKwIgo2<)2c6N5 z^Y77TJRIAO-sT|%w&MyfzILB|r5zVj+Z$5;YmB|RmqqfT=lnTO``l;$S@Tal=b?`F z;$zfIq`uqdR;=!pNF0m1I(hqfC5##K@<#nvr#V?4SK;~5G;n=T~welQnwwo%z1^|j`kuCxGHJ_ z*{fVMRc5;GE*I}@p$&1ANkqY_xL4^_lhd-{&^{)0>4-#RNv+cX(9mV>hEbnr+rHzV zj{*=oc3G`YPXIQKwKxr9p$?3a$+-%q*I z;dhv{|1Ic<=~0fi(x7K@@9N+)IrcYr7k3f4R-dQNEku^&1gTiXDY%O?MPi2+?$sGV zW$5*<<_DFTvEz~YSMwkD^abL?P0%68;m}U`<2Gdgklrb7FgB2y)V3oNneyOxWF&AJ z3BUheAk&eO4!Ji{;u4wTi8f@s1SIIn|6}i7;G(Ga1%UtOvAeSmWqAeyG9V(TDX5{6 zj{(%c(8$!IC$sfcnr3$Nn3>8fAg)G*UCT!=w3l@}_k($FRyT4`>gW+m&ne$s*GE3m z08Xb)s8ay0-ckCgFoy`CJ`LLyaeRv^ft zkDyS97xCww(F-&-q*;rYL&<&wKX)Xr$9e8?F6w;bV-xM0HRmx)H+GG;>g5Y#Ie@#v z0Z~8Xe00|CJ5iidbz}|eZJuX|9x&HU;!h7;n3h2E3kK}ZK1tiX4BFoiR^%N&ydlR< zzFjWs`xk}>$f#j17`s`Fk>pyuQqg_2ITD%86wGy;Dr0p54SEMXne`(KKKN;^n>^-* ziY~`%-8BIyzW?(RuhzPs!_@~lyRNpIrIEj`Ja%=)Zn{32pU|OgZ%bZRJg1hP!7nGM z{>WlBw$#FIcl2Rnp3i$^1o%)&3=8XB*PKEVf7XHnaE{P@#Kgib8}_NN1=`w*@t8vEgQZvfUF z-x7n`&j z4fDIhC6ge*5}3(gG+K>%-8F% zO%w00N|vxnQ;k%U3XD8)2)`SuEr$v>=ht2h+Var}%)L-$`P_uP956VbFGFX&G`Ab} z)zq#lInWV0W2G7Tyw@erIsciuU`YgaVW(*D=Q-7>3%mCRbLPy%&hxWw&dh{`UHXB# zr)IvhFsT`zn3<2gZ>Cz0ozcks0W;KBsl|HWG5{Wy-M~(e|c&U(prM1$P2eeuILjcf$%_NB8a$- zX~>kw6?cbq_PUX}HnI>I2#p+xj3|tpgA6PTo`QsDBxujIAYS;6*&V9HXCCbiI+RjR zXmSQL4yqt4kp{1Wd<_K&UgNMsw28<^eAJ+mhiI9|K||b`mDm%+;m{qSpc1(hdv9SQ zCpXoMwHBH~K&6GKQB^74S}38RPU1PHNCZR?mzli+Vk^h_itM+xhDb?ZMHbYR1PY;| z%S`2b&1m9w4j8v11z^;m=&q5bW`OIfAbHhE4Fo(?!173u&%K@zq6KPIBSJbOOQ3ch znC(b_eV-WWYc?|k8fXXEVPl~o&@rLkW3xg}L$kaFp5|J1YM7GZHiQ62suHVpgeEjG zNg*aGoxI8k8N|4Z#PkFa$gw;Wmh+&22{JX&*Y(X=MlDI=U4fmU<^)%$rCC*KeyEfP zKX2w+TalY~9i7rMZX!Cg;l8p@={cK>U68#eCZZ?*2+pt959A5-{@6!f*PTiUB&Do8 zaCJ-1%*lA2LHjK)r#wmWf7X*4gdm&^-rv%2jOTGzWiYB-c%8*VcQ>pqrezUH@4(yI z0Nh6p=zG;F;KJ2=D%YS@6)(l@(T9E&6k)TGbyRRjsVZKLs{&ttXWuxRjkHT!y}IV$ zcF~2~xChtA8Ixsl-|5V?qw|twawhxhwgZzi)tryw@T-v~OIuK!o8qVkIV%|c)!Wt}`u*aDJyyzs!* zxF|s9;Mr4MQ%kEF!JB1Qj<9&c)+3XELLMmmYK)21DAv^f?|h(4#!dP@+;i?Ed}Hvv zwM+Ve1u(|<4v2Tj_e^9RuueZmtYWZF${HIv|3SU5e2K&YJp`k+|CRB zw*mekS`bBxrPU3-`P8T=CwnzA6>6>wIBW;NC1X{nV$AL7@>tfatB9K#Sp*IINX>o+ z8v2nlyEJz*^1iYWn^(QG3L3O|)e5G|8Bi;14kxapE@`)-7+KVAh0PgICloS+UKXJp zn8iFap{_#}|DwT}Fs4I}5gIpUZH_U2urn?T3!qs>-mC0m0<;W!PrEW{19Ctaw;`+3 z(0djkr#zNPoXX5tRKgWEaRL!cn94(K%?Ow?QE6?01LUAyC(LvQx@!(q$lddFdRIZY ztvdwz;5A?E&B`%TiO~Z}fB>(GqX&Gg2$fFg#dM)^G4aG=)!&!_7c+xTJlCRY`at8K zQ~%NDMCJp~tv=o#{~9(o{xzqsBdLdp!r}PUenuc)xE6o++t4?lQ;vDvf}Du$G8ubU zm&p$3Ic!b&xw|?{cGMv!Et0R)lsjVlj3g=^Gw1sXA~WWL^GIbrs5twnk7=M{`bWT` zw1djP0>S|r=c!o%@n#bFd&w3F=0R;Dv6u;BaE-ZC-}<*z?4RM8$!0cua1p z03F`4MFKoQK=Y|QaTd0%uWqEB7vO8QCEEcuwFQk$1)5CvS6Sq!u~1oy6H}UMCxT?^ zELnR8sy-;&TCbmDW|VawP8b!h;AzM{IU(1-|CLxy9kEOuVg`eTBdZ%JAz-i2DKr*m3@nQSM(a)pcVUOca_SK(eb%yIdi98Bp{5S=@ zf85S`@l08B_H97h{}qjhN7n=RZ(n$({%hcEnsQS~{Xcd^3%1s7h&hrviu&hPoYI05 zT5%e6x}U6_i+{T}%T3y(Ua=K_tK{GAg`JJ}x8lK@^zVLdZN-+_C$%PPZ}oW#es`OE zo7&OOSgPELx0?JPC-xRSO0Bp}YPV=>sipn1HKY7&ZC;7iZ0o1-25sp$mv7N0^6*y@ z-i$ok!OsA_XSAS??L!ui+ql0J(38!uojQB;&J(`J1v-50X^>S5s5rTb-Q~+R74V;k;7!o9p^PBTh>bXXhTdoG77o7RDg1& z*gO0*VMT+HE88s>6k=nsKkiN{C~V`=`QvVLL1jRp^Czf=)FQBZiR#|U$O5gc>Q#&^ za9dRMbLucLk|)OS?smvKjLgy|YHAxXj2eOjZ2*x&hWje=rFI1?Q$b^C&vNw5>@6_L zOhs-@Sp*hI9#L8fwbedQy4FYyYhqiX7}Jtc@(5(8M>{h}T^mH??7s3?cq%5s69-lz z+MCfp9ZcLh*lr6=w#nND+l#TIkZs}*J#>F@=$`_*9(ic2pHCN$LOy(@{L*Z!e(8e8 z4G&Wv8jmy~uey($ipL?h3B@_%&k+B(1L?})cN{8(+V~yY)C$2R@jEir3SPxJ;WZ5J zqN>e{jzqP|HP5Z2Om(UKMX;`j7?)3d(bqM|lBHmo-PdQa=^LTT3I> z8Ef>lM`HoD&2o_3g0im$WbA0sPymujlSbPN+mxjBT}E~td=_efJ~n8Y3pxm!+l|`U z>qurcah%toxt$g4ti}$X^}WZLL-ZA4LC2EL#+|e~!2^l1BlSO6(@Ufz)WJ zQ+JwhnNAg~T2IfsfwueryZb!OzoXYSQ?FxW{=4Yig9N(+7l{SEJ=gnDBb^7Z?ZN<# zC-)TjOA31&PT#Exbo`{Jhh5rKRZQwRe$u~MV54J(J~PD9tE$+H%ZzH<{TVPHKhCrl zzkQcAqv7-@AZe@8NgNHfyCO*ami5j7$&-xud#s@Uk?iD2QaK%c)VnTi`MN^1YHr%|8&jSB7&>GQ(PHIZ#ltr6+$ zBH%)U_za7m$^7QOL2(3rk&+&i4`$%zbYQ{VM^inW^7OA&;38KtS9IGVV0X_V`^H7j zI9Pe63!lN5bd%ECc`lIb_55Ps2*vx-=<=A?+4SCn_eQJ)fQ)OO`$csm+`DMoKxrYn zT6wSh{81KH*9Xi;RnI6M`{C6X)=+u<|9l7638(!%L*}z5ej?A@nZ+;6?=q6b!Sw+} zFvjn#u1D#xq*DfNV`6P6Z}$4P!>?o~KNDIp{swKSzmR|ZS!?~8Zgt+Z+vP7!>~-Jh z_4mJAM-_w@fX zq3@MpfR|CLs=lB%uASQAJkN3PpMf)=CRzdv1tZT{5hfnhVF^5EHVFdPR^rf%i9)Me zeWU66-@bMtkK|Nj5LASQAuV=z_Jg*g#$a94?L+~&%vYn2QNUEiEDEqM3z490?aO*$ z!LnXvQ`Nd+Yz{KsY=m;lWOEVn?{Y-ZuyuvpRym>&xeaPqSLth|;rmMNICYZT|AgVR z#!UkK&Y9|<%7AmGd2VTfGGM9zebQso9|nB5{yc4w(b}%54V2sY62o zeY9e~bPHgp9a@UCb5&3aG^cq%77~6CSt{_z-+TT4y63ydu>z# zq*}*RGz8B3T!Vt_O_XaDF>et#UExtz8kHDtM>Y|-!wF4}$ zgRg+iNep*p1G^Qu1UuZhM6p}HCYElt#Vbpc@-ioM{%t5i6Obt#_EQvWf2EMW-7RDme% zV>#Rl^xvf>-$i0hJ*9+3&BHf4est2fc(|($ciFh18uFj%6N(FsKdLQDyV!uPNrH$Q zVY&}5#lMH*>uO|Ma;O`hnkt%WuH-@ghW^Jqa;_;U-reHE4WyX z^VI8A2Onaai>vc1rp6383?gJ4-+SV1BOvWDPtMX-9aai)SAk~r#OlMvf5i3B{Dg}m zjjpwKkoWMvPaOtjxXtXT!MgVjmlQrrog8 z&vrOG-W>5~3LFcyiDX?xr8yRo_ndi54R`3s;d0#9b>WVsr2KO$f0~v<8v}kn_u89Q z+Q6`wjh4A;6bHoq+F4D@%yz#MT9#F`0{_ey2 z7?w3$5w63n6q z4B-Gc>RNxp0{issN)ukO%&tLxPW1CZe*u;5C)58$bNrNlsRpW_JNdnzd44YQ^Ky3@ zyU`Tb^ZwH9be?XvdDMm7xU?G|W75yy66!!^$StJ%ZBh@t<>v(S%$`mqbbTAU(M%oW zFWnxAOtELib*J{`+I!kT={6h6IDf5yP4CX&9!if>ll`ov*7Q)8FTadQ6WNzZH+PGl zY`Z`7T1y4{j#!cN{SY)_DT+s*m29k)?@D`EYsXlArc)%_3%VB62eo_Q>ujsiPrSq8 z9Uojq-SfzI6W8Wq@vcK6sw?3wS75qwH;Z-ZdGvSuoI{!<)W7RJ@ay#J^#3rS{F*}n zXGi_8GC(?Ru|jb={uztgs?dFgGH%@(52Nw;uEH_6*Vf%Q&V-T3YebER?h@qTKj^kX zE$WM-TtpSe7Vr)(dG+m69{k383U9>`F5g_eoJu^X1{TWqmdd~__=r@m#R$rZS z{B__yTh$F6PVP`aPKAEbFe2Ei6?)Czk;uZ#=8?fikbCZoJQ57{L-p9*1H66}494HO8}HPokzv67D_Fh>tvX95rZhS={n(pqE+bp3YXflBBI z9|xL1%m~R@KhT1#t{-Ti1`%PU3py6-07Scw5^({vw;jmHAZQ{IbTy%i_)ATur@ivc zHm_Oh$nFO}FUW0KJaJ+V)Hx=t{elNNot0_A3RY9$Iv!{O3aAp$gl;kwZtsu_F5(m_ zU{(h50C5+!>VTC;X*#R^*2R#U>%b`p+>;z3Xoqc_RCPPr8%=NZwsIgh3#mbFjldea zCFF*$7NN0 z=}ojR#5eahq`k5Rr$U{*Gchi0*#b1S4y=duZ&jDM@vR#buP2>R)j7ERsDS&&K2`mO z91e7i`_t0ma8iWIx9Y!9)rN3fM%$2T>1)UB8nfQ0j~%rv5g#6`ZRa(gzBvF_0O!9L zQOV|)?~IzIsu%HNZ>UlEs>Orbp=P~)qJp(sT~&{-wpiTwmKS6D31`}<1zpHeYx5>0pEC-`^pb-PN#x%o;R!KT1VuF3W|ShKe4LHqZ>`0 z=j3cFeXRoH4|jXqpW^Zb=Fq>ozzIN}KQ_))Qi$8RX1v`5zsJ*YJyNfpS|iii@dJC@ zFR=^4I<-F!V_arIS;%%EmEsnyxs~6=1Br~as8RbC0uSle6x`Nd19Ij+fnOI`_5qiO z-$UY+lO^nqgG=rGZvaJuQ+&U?YXIC3FMdweXG{XCTfg$Y8}&QF%bvID#{uj_xxjEC z70$;8_t3U@Eh|5_^6bkjercy2ae<4~vKKJs_NdD%3Ufq_S3Ps3^$C(z-gMU>0|#s+i&Q3L-Id0aw+YG6Dk z;4bm7vjrXI@8=XirW)(9008Ck}{x^%%Xg*n~0rXCp~GK-pP1;c-i&=hUH zBy4zcgl6mJs~qyx%~z0NO`Dpz_1N~pvf)^z^scJlrcHaxp&O~SO(DcaE7VeYq%nAJ z`3uHP&{XL2N9rPD%3mmX{&HnxZ|EAVvqZR@K>RU5FO}E%DCz<7E$UXNojJdRi-Uss zunI+lYmV#cScR;4*+(?VptHZoq%ci%R3I#mMTr;{3(6tyE61mBTBshHh@1$88(~#rSvDWe9^2TDvGjqrGky8K`F4(8o1Z*_&ce&NraHd=x&2`ui zE<2++1=LfwhXZ8`r^wLqEqZ8QVkOd`qU?iWsILU&5QuIQyR>NEjG?tn}@9;##c?o#$qF&ImB}4DCCqp<3JzILat?q>Py>j6Pm=9UGl>5{k`t7GW_T^ePDI;z zAy(o0x{~LSQ~RrGuhw^i$WW8!_FiJ`9MwSP4{0?;khZb{+fSpD-Q-wM!1vnsq3awT zYU82TLn@-~ipO6Hyn0e$*EO!Ir=C&^oH*XL`_gPdA{B|a=F=PQiy}AWsOss04PY?N zyH#MmdUu*=$MuVyAL-}p`;uM9G${Knp2ziwX|9WX(kyH7`}t>ELyO?Z#bsXITYs+L zT>XE+PHnFG<)1z$$FU=@-r7K~Q4SJ#5HFGPefy5i<#DZR`Tai) zK5QZ9uM7WR-d^bpXI zS56d@6&SxkICufa>Nqi{u04g&;G+b^2+|t@!hX=>BLHoMESlr$s%T55H{&p?LME^Ltny|K-zK zhOl_op>Xf@&BB3ks4o>hc4r-6tGq3$9}0B@fN#(+#P5ln+WIpBWqTQC_$zXjvLRQT^SIA5Y>(263*bEr{E&q*RDaHu$H$ij~a(h3s%EBwu%6W}ZzueaokR1A`e{!U4#63+pquzt@^qj@&1G% zg;+5J`DicVJxCB6BoKMH*?A7Yvso&Kg+E$&Xos7Hd2ZySL5|VdyFOQXx z3ST2f3wb6N?;#4F^sX+)jz)%h(o@$g@8b^jj6r(5){IFlBDQbMitzL;o!Y!LtIX5K z8qlgfU}|$YHnh1a`?@0N;Dixto~ zQnBc1zh?1@YxreyEwdoVxOddD#NK#*(186Gt3$@~HK+GktUSJsrSRX#$;-%{=Bj$C zfV1Y}LslD%^%B@f<~OQl;C`IFA1z4>fXkaLiW|ktrw8q-E;)fy-zmDj`;BzW$dwc9 zDJ*})%Iu)G4@#uJJWz3?8g9!ucU{};Swt2$KmNxLJQfk3zt4I@6YE(@Vns^a@0pkB zAdgK14m+s>HnoQQ1k2#M>UXU-eq#9}=2X_jd)AR7@4H97ZE(1Cw2h};lSfC9E{Hhx zk%Qh70MyfpM+wLCU)->i#-=2@nbdWr9#gdk^`bujn4PfTX30-Q@uB{ zgaw>xR6G{){2La>O!mZj#I6vj+WR9-5mY<-)aK&r(vvnQ>^M z=OSlj>)8S9X7)Z^Zt|onCZBlAMe}s5yeB4^#mgTUFqq}4XjA`>y?c+2qDm70{?((q zt2+s)GyxI_Np(m(0}KYpKonMkgW8FaVc4B9>W&kUM>PZth!~(=}5MQH%9SIC@I1n*1yy*Y}qC!xRM;^8JyZ2V7I|&$_bM~Lz?n8bzm8QF@Z#{0^ z$9K~Vx2VuJou6%t4Nizn)|or8(0g)5^P^-(=&Uv3n7SGg9|n;Ff04*Rm_mut^3J=D4# z+}%Y%Bgh?1T^{$}i=G*e&SKWjDO${&5p*p2#LUGz$=*_*HGCJke+ajGVh6uu&Uk~G zK)ol1=pYIS)2R?QeZAP`7*NxFBHn~C#h?H|fvJTEo!I4v%y)<`DR7qwEP}4-N{P9O zsd8hhsY0kx?TkhZNtTEShKPED&gDKr)vNx%Tw*#+v`~wI`gJkbgb=?e)~F30?N07Q zs>VF2X?uya+|wr^u!nfQopVmY*T7pv3)of&5e)JTUrfAo)) zd~9BX=VBh&&+?)@7jr|*ZRhkh8>qI<^;j}jE1g)xJ<*AFvcIm8RdA8B_ZpG|E^@rC zC9dwo`CS$|)$3ylK9JEEpB(u%cazAhWOl2>{PI~?zWJh=0aKQr3n!l2ZC)2<-+K5x zSi%A|Ef|+J-fT@|7-&}8`A5zWHft84$|_^ zTYr~|0cbG|?%ry_iOhH-<5AtLSG(n#)6wikAFs2ihB<}+@H+w4r)v2U<6g5~&0(nX z%`pUTZ68={E|;+16;JE7cv3E78*eo*205FLNEeT|%{g!cqbK#ERXsW1K-Gn69!`A8{Nh^nl{W#FSyf%aXMITW0`?(m~O>&_`exf7AxC}K-6x7 zTj4fRx|jqL;VyEP9Yy0i;0!zk@N4p%2ooTWEX$>FONWu4xO6=2wS|4=CGxP^WJwkz zn^m$}vF6Hx)m9b@t+~P&53*ntY($$C78?x&A>yB{85LMO646WvB(x-`Kz&SdNse1KMm{0AY~84G_g2T2vs4j zDfb9UtsUkO9mK^3mFH|0) zlKe!^5-Y5U+F6?4z0$v?-uqW2@yea-l!0?NM@0H@d?8qjG$9&%w2bg_Rpg;7wSDR7 zruy~BqmRohY~cfczP7si;9`0icxCO?sYafS_a!>yjfnBkvPQuN*Q&4Zcn9-`?jGB6 zfz_8_-9vPoZy9@yk~o+5ReI@#t5fzaVP(c9qkpR$!}?}bmPPDeQoe|mx$fS2t?KKA zB<}=UG7@m@G#7nL-eoRk!&yu8MvdXTt8|}xHOx9oLzIU3cl@fM_{OI7x zFB@HK+kdtHbg#_OX1n9%s74>Fr}^VF%PpB2KUj=@(0C%6{)Xi#b>K+4?SGn*Ik@pO z+x9m;x>lH3#Nx7^y6*gw$_FOr9FAYU(Zk}PmOtRwo0-BsYimQ_e=FfZ!nG^v;yR7> zTPnSG&tDo(vpS@Ps~5hn3z+M0RBt@4?lE7Z zTbypUg~hy>u(SIrcNtrU{oh7Ert|k)`p5W5`bc&j%HMA3W6mk`#)tL>;CcPV->w&$ zf&QK=H71#trcnnQdYS>}9+}f?14Qunr5}<18;mzW%F(PV7gVpmdOyUlSgCq!<5shV zs`OvK$^zaiJ^$~vJ`lNr)*#$f+gt_Z@odCH7rO&Mu58K*;5&j=gz7du+d(>2PL657 z$`zTuHU;MLo2rQ~QIkz2W){~ey@VZk1gG>g?agI&&pcFkQht5EMdu)znfD=8Hk|sXZ+vOxa`V=}adVOu?gZAzZDC{^W<=C8x(O z!0*LX%6v3v!tyX@w(~J=7T3uv>0o3Js@Or=&nF*eyzW#7y+^#eolYFV2N)ts42t`c zLl)DS^9FS0VtL*S<|oVrTd7Mscrwhg8!4O|$Mm@AX+dziAyl}bH_ES0AGtC01;boGL)ffWT5?@ zMVU=?)TZ#$Oc7F#3B12iP> zgBz4&vYZ}6YyP|61LPt}Uw{8wR+l+8d1>k8NubBk3(~|L&8y6NvGV(CCju;^pX+)3 zd@@-()9Vw+iqG&gGCF98%kre|fR-){EtDk+V6(|padk6)PtP(j=4GQPbMWya-x z=6Ci_%{r$Ie``8n)*+R-hwd_$3#=}RuEUh~97zByCi#?izppmaD_)8`h&9`6{jaV9 zUWatoc3U4aJ^5p$FYsxj?%RBY>~^r4=D$HZ!Hi+)!;O|(`C5aZhMHCgeYqzR5uAb^#GuEk% z?%zV2`VIAVs*gynfYAZwvw;dP_ymEvP7sz*hJkgPJnBC?WV=pnsU$SXI9W$v>L5E$BV4jP(WM$S{!Qx0hC)JB! zQM5IvtZ2z%E!W>BD4Hg^p-nIi#%lUWeXGnyD)Xic^^lArx|wcw2?%PoCun|%F>U%M zmuNyf@jps6VahL15A}&z9^uI!@To{scg+(C#4@+{o&*n|JrgvTNsNuuV1^EhWMYvH zb~Kp?RMC#(PndRMr5#(Zxw5EN##8-7!EUwsUyT=pXshh59?H!QDsks0S<7;&hk55$ zTgygO4__4S?QOn9OiH6leTmN#%lvJ3@6)YnjS6qLsKnA^O|t zMpHvgpPy?PATu|_y2Whb;)HzheaS7CS5d9yRV9F~XlGSbX3(qL)&KR62aMgXurYHI z#(FU5n7Icxq$Ce18bildZP;?=gz+&O6J|F~Nlmrv405jd+BJg}hoRtuFA@!YW{GX? zXEiS5%)#{f4+k|w^L_2R*0iQx{PnYjAAHB~D4$?@{GR;@dU!*|Mz86`c;tq*j@;O&Ih_d9Gk^r zuC0Cx@F<+ot;fnh)o7i^rPh>YXiTE%Z(DmmMas&wzHiouL+^kZ=Vf{N%?WU`F_d=W z8_~Rd!7sRg`;l@meNSggFLG}a zcNWu&r={kb<>Lqb97)Qe2WWe!&A_V=t6S`S{Ve$$HV@OYkM-VX)*+NU_0^l^{iJLh z$M>eM_ons7eSvnot8a|QzI7h>Cm**DB46x!G=Xq5$z;t;f;gj4~k3+X%4a&TN24X(Gg*{i;ClB*JAn= zXg3x+R0u9`2PI#pP#7Y)qzR8gE@~kb+sW-wM|Ti?zv6B~J5QVtgw#f-4;ff`V+)_1eU5KTnYW%uQm16dEh}SAB#rSlhzJ{n| zXnKGc$z7760apn?gkwpDpqxTia~ooa(PEf_E$C9>I;I_UY~$8)x5wC1m_mwR1ysgv z>QuQ?0T22yrYcj$?(NX^DMq@yqtfzQr;0(MDB1I2864j1x%4?C0cxKb`z(L zumq@cErA(gH)%FCQJVeRsK7X2egea#*@brE7Vbw>Kk@g4c0ZbGn$xL5*KB6$=+1q$ z?e%h(p$GSETiGJ?Cw~4xi|~5RwZosc5Nn!_bCb~5bmqdK*F(INd~?gVobQMm=rXNI6z$G8^Y9vGKHb8oZ|Ij zypZ8?k6tg@Z!QG25cA#u!IB~5hWRD&%g%({Ty!U~hFlDGK<+ry57W^EKcqWyI#V6U zbTVt5179X4a(fe>cT-csl!C z3dQa==fRCs+tkH8B6xgaUM0!f6Fz6;^W=csN9-OhgebPx%=bAdUk|%-fz2alGg8DM z;9+CiyoCktAE^HML(_&}`ad`Cf6ypo^=C0H2NoD-4B8L=vhj~u#v?kdH)=Lcx02fn z4b!u4?e?A-58+~KYEz`j`l-(upbaI5gT5g*;_Lf^4dHjSehlLr9XIOb|%aOzxjTcy1>d8qhStL!Dk2ng;&2(AL zkX>e<@A<>zon|`wi@3_hT6SzrdG}<}#z$Fu)Li-a$C>uX0uF&>*GI@MAI90 z1WxIZth}3bu1^L0jIG1^4?in}S6A+3-^u^5cjxgaq#I>5 zwIZz)xTQf-K`8^zSH!^-P$DCW!(xZU-Zp{O%1B`V`8YmI`$`2KqVV(y&n?)FxF9N{ zj;LT;DvJUQdx5t1o#mb^rIps@kD2G?^U3#@OLCj!+$1Mw`JLo;So@PutWgdX!_Qy* zI>^G2Y?_Ne=FfO&JmbZSl|Uw0i!Uf&E(3DW9uz-5ZAcmbr0!U?BWVVFLy-Qx58|Jt z^)S*#7?1lH<(Plu(65fXeZBq)f9>HX=HA-&d%Aw$MdgSuFYZFeu^lvCp5A{1Q0Ema z9~!=!&JSH`^$w@|_k0nD`hoBcbyjG*((C{sm;RS&a46MPx8jWZ^BVC-ULkcW1JfByMQe6jF z3p!{0mRQ`Z$UKL&FmGVfG;e^F*f*io34v~~R1ZqiyltX>VZvIzFx3o7R~_l|zcRj| z+L1qGd?O)`X51&$qy~EoT1(W`X5>R}57dL*80$GUa0$`8M7Osr!*js=y>71y8@_i% zs^^IL1LWRK$kNok{nC)875&l<1ZYOy-N6~u>{9ceV*=f04viUppgp@*HOCwpHGIEn zo!_zM@aW-nm$D^ucm$R~o`V`9l2tXHa}u#ik^mGCdEkcXk?=f)B~1p`2Z#%{@ z`f>R)!%n@?XZfV^^~eW^aSu$=uOHI1JMMuA`t`=9mphSNgEc_wf)za7GdIYDL)bo@ z_zrT`p=q_=%sJ3Qwcb(3vFAn|AGzSlr?uxt9Z!F(5IP*{_>`mmU3E%w2a}KyOiof` zuL7IMj5SsD$`+6%@OPPCwi9tdtDV9(Zul&ba`~v_a#Kk*a+|3NTa{XsJ?++Y)CY(g zkjym8CTc-ds+pON6wFL-%hPr@wtT)@Z)RdF<#|2Tt~Uduq-TimjMWNyY>IHFNVGxY zpc0a=5$vLsjpeI_0%TOR%_sc97#roju`DzOIhD!BMn&Xra8K}Aj?E#;wdMe=o3PQ= zXF)AfE@DA>M6`7qaQ4`;xM)~Kg@#1&M4nHDMTv9(7iy=)@*(_62bxD3lC;v1&5IgC zQi(mAkJ1=SC3aMPRK1CmZ`aBp-(_>69iI#BO0vSKr;Hrh=N-CVQNAkTB1zl|W22Td z_{?)f4&(uiPj97ht1_V7$dcHxEh*W&u0>2hTG zd^@STl;)=&@TzOfd~?Zr0oG&ie=K-(|BIGc>bI4W2rLC!-03HCrzLuvCui)Rd1YMZ14(|qP_#%F8KJpx-{C*{`mBkoiuii%zPiH z&z)5Uzz1#z^fiQg7NhXx_nMn%U2V>WQ#G{3e$M*H6dJ$!Nz8-vTc)5oJkg&A;gjnIsW9Kf0~z|F8$l@9A< zV{!g@31>7#mm~w~SXd`RHLlUn;jmtoj{7gIa8D+zkBtPdJ{4v(a6$;ITk%XNtJ5%H zT83pbp&=Zr;|;6;D_m@N7^i{tu5ebzXjlWhG=?x5BM0xqs?#}s`ey36ILr{yVyXhj zh=j64L2qNBiLuDF0rn0y&Zom?EVYD9?1R-Mj_iFx3$0SEL2iWJ-g}GoOTRk?#i@pD z;gJc&+pJ$YZ`zTtq6%BJ8ETF}j(g914|G@d-^}-HN3I~|t}s8b-Mx9O-{itA?#&{! zMUWqecpqv*mO@=nU2;o)kh5FzTm?Q4`Lt5K(CBpRg`xVgywSgHa#Wi57#= z(0xlimU3g9UMPJBnt7*CdeBlnanGG0FC5G$zYAJ(Fk_qQ7QYjqySF^_D|vFygxnop zAwSH0>+2tN`deRL#kPNaX7|Y}*RHiIXWls3c1`(8X>PsJcCG#1He&wi=GLoi=aHXX zU49mN{Ijde&R)v@Zq8Js4f@ArXYY|VkDnU3Y;vSjtc!|V2xT}RF3gLR0MtqqI|>Vt z!J^_4)#B^+R7v$X5$O0L2hyyQBkjnklY6P&giN10d4$~(U>;ULnk=l4C}t;{EC8B= zG!CZ5<|J1Uhx#?e6Yazd;x6c*Sm)4PsrGn%Y{}5INTFniYAR9?RtjqcdtX5xWc2mA zgtZ~|2%vY_u&m1#3zb=yeG2#$sjyt3 zvyle%d@)>q{yetm==O9w`EtLY99TAD0m&74wte6=12EzKu%{eNlNq&rX2HA*Lm9O% zZPmPs2N}_X;}9j83s-+Vten)czrCKEU-SQTWv~|1<4+rBW@GLFlJ*b$(E8Dz_OBv& z<>xt@wi$J@x>jHU;N$Wo6qgLUZQq6F5L{DvsN&K9K^?PN+YtW;?@4l;1@q1ggY`aA z`&9aa`NufiuC@67Hj8%-gZEb~Yn&?jauf6i-bYCv>hkpT5#HmZCUkpK^k2O1lH0qo zxevT`q}}Y{(qmie-DIrX(~Ik;nAEwQj`hcDJaPy=X!bW()_aOcALL8>F3$F>An_x` z7YE6uN?dKP?? z`0>nn=3)vE$ozw)V=fK{W#ssC|9or<{KWU5c+s4umuP$16(ymKu1msWN&Xf0-`uZ=opQ)s= zb7VrUZ){+A{3sg#byLf9-+obe(-#}|zeUIQ-M_WDidMf0Hed18=?bT$-a_MtRv&)> z;B4FQZ;fcM!T2r|Us4iUfjZXDvFA z9<8U+C#Cs`_PmAXpL^@7W$Wk4byM}{*)LZ9|7!lTY(Mw?|5NRFKK)wf^Ns9oC;qQ( zk2mF08D7?-uw-Z>TJsrQ2gO6q@1yZ=+i%;y>V_sp{5xPxx8rg2nRxX?l+6^4=DGun z2czM&Y`kY2ZrRGlqv|Cv2B0+-bK$jY9C2jrMD&kkL-CS4EE;Pc%AsVYT7hBt5Y()N zaz~JredzK&aKkwzI3vqy;Z=@|(${Lx)nDW}cKECkgEU>|8k9x}`e`5HS*#l>`DLN~ zRmWguzwqZ8aul{2TT)+rHftuRhwjaq3mSqgZYc58?2VthrlDkVO$30u_3 zf1um?H~Bgxe0d|?K66XOCFK`39^Fuwh7Ax6npMqMf z*vGKtNHcPg2z8c4E)r+^%yE{9*O}K8sAW<9g+$3&mbM&OT$Ywa+!=541}WIQ2>@F$ z+GnM(xg4A7_fBdoaz*)_eMVSte zC01t;vMj1#wuDlZWdW;Cl(HuFonV$`3p6(K%t=ZIXh4>h8WQ= zkD8>J#TKsVmp4R{kdVKoU&Ro{1nrHDg&Lv4nm$-?opBXL;4=m4GNMtpPyx9!(-qR0 zl>@P?+l;J18f37Yn`w4&GFS!WJJ-~uPMLp>o9X7A75qjhP-U=VWv&G3yd%gju`j#6 zEJk|Q3uCTkc7=C7`M`<39tIgAQoi!<*yKsWAOUmUojwR!zi$aAr-{wgk{T+Y1 za#Z;k5Ay;=;t!(~&#BAgn7!>|8jnrE|DnXm%06}tIcB(f%%tMMrJ znam>?`_<(bI=+lol9_tF72kDfPTX*hnmc2$J;mZ#McT<~8;pPOl#zC?&9BDRdpsn^ z#EcgkD?O`eGkrmL z0vXe%Ip+a=@XH3S!Pkmb1Z1r#8>o{mUjN4_2VGMl=S)$2$m>9?$7Njvv~L4DkMG;Ad{zWJv3Bqa zZ0Zm_5bJa74J7Y{jh@bZmb#ZpPM=MxtEuk?TiVf+x?s1G0vn*3JdoO-n5mjhCG(<_ zZy}m*iB%fu;Z#ZD z6r)cvfykIj6jW`g1B1;Vxy^GsDt6b5ARmgNl5&5Dr;0%i^ogf7fvvjE-QtrEmJ8Oc zYElI~7W8cEMLzgMpT-XILB@8a`We-g8@p2daHE#pP(0lWR-{!Ozw42v4%!`mRGrzW z1t+?a40p*srAoSJz_@NYzJoflyj6f9L2CIf)RA)2a>24UQZ4T#6ZroI@{=AEKfmSc z!>}em`jJMQdrwW135xpm8wo%OeqgiQC`T5lSF|fJMF2ECh+nTQ-&N5*nKi}j|3+ht zlEk3W#m_}aL=$N~K(VYJwim`^jWgv$2>=zi?`7KmT!bIM75JEfa;${TUt@85n}kn- z#dhvxpypzD?cmAdfHwOoU&u7pD@o{`fakKkcdY$1-Cy%slpUy}81CP86h3BB|2fzG z(NgeRyWRi04YecK0BafnZUdQsWQ!ON>nK({1}g`zJx$i19*O57T5%2ubUO*pTSOzY zM#4*$<8+*0V6_}sSeoTRI6=qbmMQ@)MvYsw@OnHbp@cp}!2bvD!K3k7A$m?gOHCVo zy=N+4uZ-$%E~rEmp^R!VkZo828p{WoOU?J0M9iShUPqP7F)=ex5HT^$ zF3RsQ5fhW`qHDk3yOZlh9(o71SHy$KjS+kubUWv-g0^!3Uo45X`RM=@!&lhnEkT0$BGICX21cOILZqw;0{vO10sI5Fjxd%L zpaS@v>Op7@Q9>T!1bYtr5GTf~_Ol-0Qlb3=bkt*Y4li^Z^xWS;|49K}4lznbe|v?=CJUyUBrKptsq)v` z&1@6Tm~5WaVwAK28ZPokxfAUhOeb977UU_Y*1myha)s{J+BY%PeCY1~WA9$TqN?@< zfUo_SnLWb*!$SmA93CR2;vlG4+H7GIj-g>+dd;#kDjBCvHfg4Y$R2!wl4;pJntCNO zqB_S&%Znb1?IXjo^yH~ySp=kDr7~)oBFw()wE;&)@X_hq?{lO6);A6_vmdkfT5JE; ze=WBAK{e(1Q>amfYgxK6%AkK8S{o(!zRvTdwF96UK-7W1dNok+)p4Ncr$Ave2R#uk zWNDRv zA0sGtumPq>(tXaIl@q6uF^cnhRqgN(C1ceDC6?uA%vPT6+&zQsq(7{W>$~M#200Ct zZ2Qu#DD_rUE`IaZNn9D}=je6*t7V*t)DzFTqc8gj$+Ph$~SiO1B<@8i4uKv5y?d&?PlA*oW5 z(3uTfRAQSQ{_(g`k~2JhpsRt@XWu{Qp5}Ure3?G@Cge{R(!BuY4dn(|Xv{y0=G&=% zvIkz@F5mBT)%)NI@Vp@hx2b(vTRznux6}vWZHQu|%w#AfxPNa=cbR?{Ph7rqQKaA7 zhu{6xEYk^YG)gZuAZd}C|>t&wQh3`H1;~H5q;dObtqOMlz!Qge| zl%r0NNb))u-A5OKAiR0N?&^pq)Htxb&{IRzeyP;2T_La<(}>E?r8Om~r;%aRRjYu7 zCH+IjsA0f#axOjwv_I`q`Z*58Yc9WW~(-<%Qr^H=}omAc5)18fXs#|ly_I?p+d49C81D5gC zJ};ur-GKH3ZQ5#t*C}!s^61)%rab{DXVP(WNx+u{GM@i-pU~~)KYu}$)-ixJTXCG# zF#0dbwly4&FGT%SDCP?FXx)VXML@d0A49QNDe$p-z)+A5L>!}K1E}W;{-Dk&lN^amhX|o!PMT+qCHNmanB;Lw=fpE1R8*iZk08r zLPL={WE4n&CKEXa7BCKQwW5{?Pm`*kBk4GoPM^S4uXB;8#i(j5n8j*Urj4OcPV_K6 zm{|=CO7G6BwxmEKn01yZ)m__~Fr~UDbp2J%AP$*v0{Ov^8QBr(5gb&ANH;{k5jH^o z2=ujXt&X8)2!_}eeFpRtq0t7U5F6!}NL-GL!`h)K&}w4WYJFU+SdhtUGo9tG5-Aq(=D~7y^`omN4cb~f;Tc?f06}-tM+Sjc2 z@n}3g&?`q5CR1`g3p6JpnE&-^}L#8LT+wlZICY(>a5E-N*Stfx}hu_dY*W zXHBcaeKQYjtv6f6M{yPX!EIk|NSrwh$IX=P=v8yDXbp)2rbbM(t98#%#vqWq2ztfB1=>^aq>GKp zaW_jV_w&u#9mb4BxM_9H-M`5wIGyBkeqDT^Xbm2}hVma6!$^eEbEA4D8i5n{xBctv z(HWrvsn5RtUexy%x-Q$lG-g|B$*Fo)R#JbMPqGAP+?c6CBH=iIQvw-@#(Vj? zPw+rz$Ls!IJ8C0G^Pd2osDOfF^aetEoc+NzQ znSO4tkjLxDDE<<>cHrY=>|URBz%mubY)NdjsLqXG{x#g7=8BcLQ?lByoBfEk3`lEe z9yX*kr$q_ua;KjE|5ET{pf6G&W7|P0owDYa8a_5LJzb{FQE}F>&wG z4z~BH=c&iNSnpw-r*wVyc{tK^r74}&(!Q)0Z+Syp^#&K3Y0Ikt-lQFhE4vfdP}g_T z4^(MK#!e6a>P-?>1xh`PGq>-Z9zIST<;^H6d!2IEHk~SVG+^!~m#>8Ot@7}5y@&Mu z=`eXKDTGsqW`X z%D1^F8kUs1G^_VL##Nl|q28^S@pSioYX8=uQ{TH<=1yiV!QV6EZ@>j54E}C4t|#~? zCpopnlry3a+7kG_)|La@qk#5@^=qg{xuWnJoO7SN3~0-2(&nSD0{Y7mz?XOOLbsRO z%Wtrt%=uaco^T9hPeArFjp4Ue6S<%t^JxJzS`3cEr-vMns^YU>VNwZE%v z=&p~UgOORpeX5VDuG??5B~#}>*YD3m&RYM69O!Q319Lv59)*rZ=0oQ^Gv_EvT#L+} zH>Vq$yMA;!HVo>34x!G4W_Dxq=8l$|GP?!l&CO`BIkRVA#oRGa|G>W^1N{R3o&$Z6 zny(Ef^3ai2xHV_ItmN}|c`-TYi55kqY09%L=ClanS{;NmBOh7-wPOKtBGNnvgyVZv zW)RL10dpo+u05V4Uu0YyaH5IC+7ZJr9GLRZxX!mp-u#NYfhb88&yQlayy z(_6H(ai$-1RjW@EheN|G!KuR&4AV^(6O_${a!dl7P8Cfiz+Pn}3$P5<`;rj2%MvaI z6()46fxh%vLbvnC(b)7h`kc2!c-TFA!RTQ9d2_~zB^kW_eY34}5p*Dc+FC43YR8W} z+}o-Y47C9so@Z?3NEX=2kcJlRWj517qNPYS*s5Q$Sqh-VL85oX_5`hF88V841WRR> zVRVaKg#pm}UezH5DrnKE6QV|CfrC&sB?c^G`0F*!)BF?w7BIXypGAS}ND~TZH%m~s zMTji0NYQ~{1)738F;H9)E)H-e1j=x~4Jd4NS0_v?bSrTRL)%D_A$(V&gUt0KF+Yll zBCQlFUrTCy6{GY514L4rM)^#6umYbErsto0i>Gz5Cgq#?MxNBaP%g`bfK>h)l{?%5 z&0RF@l{2ra`L3p|@$03Q54+BtvDl;V>rY#~zr-@lOh3bSl0!kKB7_k|l%1{_(hx%cndqMnG)xf?D6fAV>92gMFn+b)9Az^aLKn&IoKkN?yZ zJ{LZYKZL|z5Y@SyS*4~W|0&8R3s@4T1(aI#9u#S`rQkn)a8FSU}(S-A~ROSIhtIMSas7&0lq^^o(yX-Xi^OQp0u1 zdhz#KI*Q-B-t|-U@lfA^zjZz&Z+3K?{oe69p3BW1@80st{k#3W7H{9b-&*y1p`JHx zbpJ`rNl|@SDJTks-Qh!sQ+lCI+ZUCal{%C!`+BC+yuI9B{$DI8i@<$=H4nnQRfE92 zU=*y8i8vqDy*MY94gQP%qFJb|I0|bh9)Xw!(&2N5;;dRj0H;HfN~2&bBhUHbELbQh z77PDy8jj&~XcQsGXgTyC%j%4H#39G(w1S2q`Lf8EL=>~d--_&rW>1-G%G*f=HO4_q zaxu)}_Pltd1EKqvR)<|=oY-=x6EMS86Rn{DD(F4!9}0F+YwDnVptVpR0bF`(fe_{+ zNS8_%7<%~VrOTxY{H*ut<;&&JQCNTLC&<^3mDt_Hd!TMCbHu$m5_=&ODsxEPAelW< zN1RX+8uq`MS>A_w$BGfiBIwh@sSHwTF@c$C#=<74QIMEO*km<= z&UmAXPQFi)BBO(^p;OX8tD(9`Bm?Dj)frgs*aRd1n=%<(so3Oz3T@?x7LL7I5gP%G zfj-jKGEZ4{B9w4b$Y4@gC^^3Sl7L)<=i^-KNhdsdR zilIY47X6E*$gN2_(I4)w*MhH>?nf^&N+fteAY<-O*(#tr6{tUkQFOqJhY#iXYCf>e zoQ7iS0jr#m{Lzf{`1v7{e}8&!QWG!xgWaUe#LE6Aa;KG14oMu%Ii9E2emIl%wMcA@ zs6IY7Q?sQ=ASa+-+@H-e(z*0^?k!gb90 z%YGMK{v^MYTZvRwWRX@4S})77>16I}_6Jd&zi{EmPw!RpQ6>I(CP1AN@#Ev#CmoNG zxq;@4>pwsp8~FUwQTMy(C03(ooGx08Zd5|&yJV6#E4TlT<*paVJdP6EPj=O6@V1&e z`lqexIK*$y*Zks0qg8U0H_J@sO?+ud^LPiZ=EwTk>C%xXkFdrI1&)3s@6@;ozx8Gy z31qwRTjip#z4&uJ@XHptfIOd3qJYSfIyivqF6Qf5b$iNmj>%{L*bC*^!q1nwaW;vb z5B|3I(o~5ymiO0Jot8>z*ycVyODZ6r0VrQe;2`<@49Xo(uO0t5&ANb&r*UrvCukt8 zyoKT&qtphryMq?CGU=3?g`Zkzp(;x^WxwvvUSY}anVkZ*+(X4&v;@!{*GIrvGyLP^rz8s7m-*4AuXev?6f^NfZ zcz%SiyeO*zsz<&LjlkYZ{Oi2|(BnwUD~ZS7@^vfJnRxu;W`|jjNn3~cPjDu#MrJsJ zRwsQ#9JFZ;a>YPs+H&2BfwnpR*|oY&*z3BofwoyDYImeew8=8`2c0YfW^Q=)4=9t? z9-ch|eYf`T7^;kwC7JA&B{_$h*1q)k(|!$*u1!`Q6JF^`Hyeu8F=c3Zt4>zS1xaTM zn_O5fgkvk9xnYwRR}_Zx&?Ob?!uc9xWioXrU(;*ylKn{kNlPXo{U#YFRwi&QwNxe; zn04YL9(h;)N(jO`d$-(}A zKWvsunw9+b92Ss~dk!1ql6lZNgZ%D18`LPjM|5N7A?0Rw&*R19N^ zop<$7WF3&b1jrb?O6a@=H%m`JT)SgBcmC6QTxO^?P} zgf#`GFD22UUsK>eSrSLIYPh$*i4aEwtl5Qq!LhT206T@~XN>^Ev3|`CenH(CK~y5F zfYXx-2!uG<-L=?xZV5Y|mOMT+UDvay)dx-fv#jW@Y0XtUUk2+cfQ|Z76rGmm26S8S zeD2?OWEEKU8lM00YX_fZH?$2}SU!t4?v0ubW|D@ITF z>~|C$H*n)o>hT6t4i10iudM~g*xNB^$I)zL6mux=nVxJ5S`3<>3VxY>nf{MYC<6kG zSC|1Z@Ti1ia7NZxXa;Vv8U^D__%j~2W{rlwN23>x0{7#eak#x}Ec_P@S19OEUqN1v z8np1(g&b2VD#9yN671f!nUqrd6(JZ|RVcq8X0=#B7idO^?|?!60y)jet&iT%tpqx!9-XC0s2HKY3FrDxUs{bp4EY3X_A z{(eunzlQEbiszmCn2!yBo^kFwJHYjI_?Z>R2j-pG{Q21d$^#4E*u3gI^``+!>cTg+ zt@^2-lKOOS4>8)asuC$PFLbZG3t-p91Ko7_bJIEz=p;9f_k`Sc83VKQwFf z^HcYKK|G);j?}b*sV7uLg&sfQP+U8p-#Zky3+jQEr{%AnkL2=K&vq#G@?f=OAW}l6 zBMS#QgcdrHv&$t3>w*UBgxPAi6>6TXCL;r8=Oc%x%}iQHxvhq;F70s z(4J5pn78*dYXi_`wPuhnC_&;W5t`{OXkj*15+4!8 zd?`~3Zx)D!Ql>%_ThWP)8d)X^Qn=C+8>RG2EfWKvp{Zqo&~&UVYJ8}!25O~tBj&au zs4@1i4;gQ0VT65%+1n&$i2>M+5!p#4oTQA7$nIOBVq=jrBx08Icx(}NY^aQo$uxorzC`lFDlTpGpY%0;T|HuGinVl^hqY-Bo{UDU!7Z0t?0dH0)#wF4_J zqIDrpmyn`q8ZITg?!(Fxn%3(D6klwr`gwq;;3o7uA#A(Ws{z+@S}>|{u%_w$g5rXq z(ilquIloK!{!F)C8I#DRr=|lhyZ?%_4X$VjjZe_^&f3`5aPAt9JBdx(5FayW&UD<4 zRrT}tb9d3S|4W`D3x=gBxGieHg>PT%W!Z`Iw@%kze@1(XTp~{`izrQ6K-$>C8X}ii zjO31VfX7srl4A}epQZb>q#V}vcK6x$fg7KR#Mx5iEKwATFX z`onBKJ?ak@vv|ab$`$Z2_&qmhz$078dGwI#W6Rz2kT7q`cOSUucuxOKMZ4Mk&=5F}#SeYhtyC$r<9NoOFZ5AB5x$#U-H=cR{KNVd3Mb4t~Oqjq&xM#(>wE ztJ>*Ckb4hqyvh@Twgb121KOSbwLOCrUun9#Li39hnnrkW4{y8mc(PTk-8wRZn&z!Q6i7+6W`VE3*V~)g znro*O+BY@M+mSa()(a!m(rgfwG^oGm<1(hux+MnYeO>|%55)mwZUENiE6*g$%N9a? zHN)Fu)FVW>P1C64#6{lAByR__Wx0=;RK-W%X>WWdCEJDSqhkl@gY9sT?|(Vynk%WV zwrMvXNz2wl)CJV}v}KF=cqe_5Bj!-2`x?vyRK?4ns(On8aC_XN)|J0Dha9(M8C1uqZ5v4Z z?;DCx0h!73gX|kY(?sCPC+vE!&YaHg(M9je$GnKAtt^a&6#_ zJmTI3%qOz4unTVZ64iM%@GSN^^p9C~=OJiqmfQK;zI!u%ZQ*1H~}hwVuSx8B`ml}G%-6l;oJ4;ObIJc^+X97gxuY%YqH2m z0lSltD*|@ULmuqGti0g^B6rA36OSx^z!ZDvzRG!-%wR6|(D2e+!q;dtc z0Lw+(WYW7=4~qHB$R%OW_?`YsjO%9|Cni?JyRhZZ#jVRPHpq#Y#2{p$fJGa+PLvhU zp=b+jA>LwJF4j>+iAzsE=%_-T^K#JAbD3TiA=8VJpaoSzQJ8u*vtW;~Gz=7roC_=s z1;qev$4pZw@M|fD1#KE^0HTfvS{jNzN^8O$j}ESnVVMFjrU%L0GOZmcb;eOp1GbxF zn8J)G%PJ4DGW$%4*wU;k(b`9f*kV^_S!GFFWmmJTrOf136*{sEDmR-gl*Nm$62Uki zKhBlK%g`UQzj(XPXb}Bl_Tjg4pr2#a=%uHiqmU0mi;!sfweIQq9@j?GbD6>n>ptFY zz$b{J7SHjDT}E-9>GC$CV!-jUgTMbcDK!VzXAf@>mKcF(M{#w-`8p%L7+W}e-)7w~ znXF*iF*QUXSK%tCR0ho@`B(?eH|5UFA^Bd(XL<(@nllrhDQ`M(EN9>}(x$cW-gBEP zXospN^WE>5X>Fva`W}82CAw-9o3uW>nbu)?`mu<+D~cSr{o}c~_;j&B0sBWCCOpB(A4i|8_h`yX%ZLP><4kI>hvy~&5l2pBf+%CX13!-g{xXb zqs>n0sz3a^WKdggxepC!rC9ka*E(VIPYdweB83Qrf_?iM^7+90k8;oEJq;2^Nj(UBPaE&z|Fc z7w(O|L~-%7$OAB@eKX;8fQ`JjYuXP@EH--r3V=j$EoSwPEp#>>dwneKoP|s}&{`oKSZ$q;Z-#r@r!6IKW0;_G z%0B+HCWXn`p{(tj>1&v`V_wS=bsUg$@}9h3n3`g#n5AeQ z!LXyqWA1tm!w3R(&;4%S*XDD6i|w9aX7--F*ZR*||J9m;kI=HqTGQOz^~{Yvu3^5$ z4CS(L!Qe_Ji!Tjg##?lTTve)8p?w(#X+rp79 z9lpD0kVGS1qtofyp8>+Fca_0ctrhc_#mxVrhJAsqoT3PkKelXilWLQGRPYnHp-%}e zZ(r*pxKfcznM*neB}9K_cfmmn5gf&acnN#JFep|FiE$hVqn@LR&3#O)2_Jxb&QcRO zAXW`|F198zDM<}^F}CJ)tUb17B{Avd%DQKykrBkTkr6*&oe{{(HqcBFKUBU)oS98D&EO_rWn_Vw>O_Jm z-Jp33D$wRulhC5KE=}JO(*r=DGpaBREh&M3y{@K9mlGlfDaBd+k4}h8 zB2En_mQD@t&$Sk>L-vTtE#8CNNOWNjGr!q$mn-{ROm5vCT}AdebESLF=*mjue(qL} z*_G#jd+;v_qqDbu*W{pt^n|T8aK$5wRIH5E;tg_w84E26TvT--wMV%FUGQwhHpdoG zmu)-X>!YHVv&{z{gJypD7;F~xiP%jbCc-MB3@@jlHU$-k5_1uHQY~sAc4nFu88W<$ z$nzE;LTjc`$v0+%8AN0_Hk|5cW^x#I64fwCZQ1de+#wT@5#tr=JmjKCvzIS%a~DNZ z*K{+7%vEOQtVYgIW>&BEqXsSUc60?cPWkI?Edp+7QPAJa=xwDskV*;8|6W>@iPbsY z&HPTqF3zn;H9HnN7H4C(5Yc{g=sen56764{pNZ$G(nP&0$wp%X3x-teu97N9ZO`8w zyvVJlKZ?uYbq)D}>I^a*$Vj(j( zM)yp5jy5^%VpvMj<1|0Jy=$N0v1v4BcI@i)XH&+=B%98Hl=6>ncA{4?(H#qHIzE`Z ztDE_dNps=y{4th+vWYe;=gkc2cZlWFnm4Ovr_7q0vin5dA?JEhXPh(d`g<8HZ+lo> zkUm!x$>a2@sWMrsH1fAzdGU*ftdAOK6vkby@%&g{Rh_?Twb5(kI z#$NR{CyfNH$?rMA#a{c2Hyhq@X*9=G_nXlM)kz;`--+5MTr9U)*ZMAcP0J&%@tK!y zZr5l=L%8NXU(e%G_Q>*m{ABOv4s$>X%{!%c>l_e3HiscUg!~6c^tCLs$ex(ihQff8 z(1Vui-AW@`PwLn9z{C--lJ+C0b;mXUO}P((`=lrD{J@LCYW@|NU8>j*vqjPp`@`Z3 ze}wPp|12J3`hsthJMrv?VBopLPH4b(%kz);TOr>_-Uokoj0A>o(!#;VFtFp<=#CM= zYWo0}FV%QJrecyEXpoFu`QEhgZ(zm3{Ea0lmEmTPgRVd8#F^4NgwXD?4i5|NU zGnqNoE)mooq=A)VW?FhE)Qv=&c!mot34W)U-!hLf*+|CD*UZ$p)PmN`@sWO>#R4;R zC6fh4Bo;7fQ=^YUE5hw)+AA44rn)@SF z*M}k3pHK9s_Vu+BwKMfus@x=bh9N#G9{pNT-&{pcUXj9% zWGj2c9@&J3$;Mj@@ixK7>{}g3&0}glzS7JLk7dMr1nMZbMKd<76(wIaGPE9<*@`OD zMrHkh7dgq@A6`R{$)h!8bpjxCUA{IgroQ#yt=0di~J;;7HJn zq#km#I^ZhnIt7QXm~(g=eDbb(Gtb2}X?GO5R*-5JJXjJP!TXMED2zJE<7$OP^;7t) zmrtzn>%~t~({={L@Nx8!wIS$OqqUD2Z(e_gZ*%bcRh(;q{NaC}dJSJE$u?sTpU2-m zkUutOZd4*)f2HB{O<-+{8}5@Y@$$qyG5DIM(Dg^~dKWIIl^bwheGPtJ{@*S*+>P^N z;fz-)a5rSa{ctZ@^8m^6J`UYxp>_9?k%bv#%_tJt8b`(*-bcn6;+$D}f86uRq|@UO zfx*0k;g{sMJ$``P*5vAH_2r;#aj|QN@x8EJkq)ATs54jwBbUeqOQ<79 zT@r_#L+pz5ivwg@GefAN;z$Fcm5FcFZs*dU@EncA|0kY6L?Q*$%ZRjgG(3aEM3hGr!lsCehK z9?-_y2d9o|rot77Hl%FLEX^inm1gG%C9*XYsVk9lQeD|Oa*1q9)e^8OGFNsrS)A|X zLD_X6KjDUa(21>d9xPz4L?%}{^RdG#oy%6WU<7i7>uo~_aho9|-)STkXvP)V`?u=! zwl8qIIW=JgI$pcUn$U>|s2xnj$FUz%B%v6O7EvdfLBLv&CZZzA*f^qq1&c%-z)Whg zcbpOkNsENu1F?C+(1AJLN<%}a^KYXPlqcqfS$)V z$Kb4B8`gxRO{7^z|DICnfZH@v>o~@no0&^cWJ|@$lexGO1hz zHT2X;3hiU038y@H+h1E#JE@CE2SzQlR1FPe!_)}0^mX;ZeH2(fu*-uCib7h_ zj=Pc$R$riF`ZA6*uB)yxlJeeTa&~oW8^r1ZXv=biuX@3AwhFVgXb^T*XC@jUW) zKE&z^(PWTS;amRSSZTEz=4ZHf@%-|C`tMUeRI`17V>Z=Q|3)HZi;}+_%O5A>tA?=Z zsvuIfcaI!aUB&XtTQ4V9ur5X$-?%x&Je}5&Yu!B?%wso@n9YKbXFqm1X`R|0dT}^B zL7&6g0^M<*tNqQbhEu@y`%C>zdr(!Ioc@c?eE%aVlLvkMotsm^LLc9Cy2q1zedoqL zGKBEsA=VR5dSzkVc-}sEZEfdrP-$PZY46{7i#7k@;rFB%KKqnCGJY7p0B!w5H=XCn z-FN(lY+eVSe_!_`UVeQOdOqxn8GAs$X8<andVK#{%|8CC7p)at?X-k>z{evU^g-qn zAA7XZaAuf~YnK_11Dm^c#Zv+JG)hv>Ef`USbA6KQ+QoVc9)C}+gGJlR(RG9#7WPj6 z7zykmWH$u;g_q}#3;GlM9>4j0`3)?1x`Y8Bm{q`|2uHw37z!znMxt6Oq@ohe?LG={ zj`xvd4K8DcqpefOZ)xa9!ab=Z9lF)&L<#>xwHVcXA5 z^;YYE_><~jmb@ajq#2vuqH)x+#B`>N+`}DJmKcZ4#0tbjZxt7_IPrbtr^;UwcM?Z$ z-C2qZx^L@Fmjs{o|3lHvgAx?>e@5GxFToqg?JFc$#ni_COd6GnpU6reX&WyHFv>qqRx3bpS3%lg_z@g*dLrV*WE$qb|@ami@?F=O)X3prRI%A5ugwRL*reeAI3+l8G*&vQ;Jm*2pxp zLy)!G?%1X$e1@6Yj?YJD!c*1$T<^svb{_d`$k9=7`bBWu9oHV zZa-f`A19%{s^V^P#hUs-yqQ0~UFem^z0FSxX5`Vrc)_xlQMeK=WfhYR@YCbGVc-5htRs7dR}9$bDvlUuuh}vzg@~}&W~(6vk8^S`lmJ1Hna`t!=?$x zRKCrOH)`T|3##Hq^gOhzLtzR$e)YLn|I%dj%J!$$__{O^KI-w z!RYLzkmoG9Ly#_#r=zgwC!Dv|Ld%_}K+_Pd-^7CBCZj+!C&OSeD>Uv4pN9V3gX&{r z$h^^Mq%Jm^)YEVcZ7AAuC@PO4Ge?g^C0sAVsYme)(Ku6S0IqrI!~j_@38>yBh@zh$ z$byXPX8yQ$yd(>#z9#8$M|mUeG>>Q8`Io&!-zIg-L&OxUicDC?ER-QrM1CqmnTSp_ z+sl%>D*K@Cx{xfx0ZFFUm*N8_;uccA1rVZO0U2(MZa9W?e!_Fe5PRMWnc36`3 z4mo?`^TVRF9=Y_eD6YTb?7^k0MaL>;AXN*DnNBrN&(IT7iF#}h@t!~dtEO@Nk$z@X z@)8|ZO!S$-y*EUX|Fw0YNr4OPlhy5%Ce2Nn6)!DRD>fL}8x->cVPJhypLSh&5-jKe8)Qgoo}A^_c13ToqNAkB$p9t451*)TAeV z%PchMi;!VRjSD)D5rqc5!^_BZ%neBKf7rVhu&Bzs0pS00=A1KUaA1Z@I>^N%ppuI^ zAR3yN0}`M@B9dBLyMt!BeYR3sn}%}0k#MD=!s6M@6;#S@hRSYgt&VppG<(*sRX;DF zs8nX-T@g6ndpT#gD9K*F-LLQS?dkcw4l`#i@0mI8dEfte|NJVXkk9s6z2f&CBk~30 z>qwsp;!dA6t5<5i=x>S`L%7h&zZqWEotFOq# z<3TdcW>6y-i?xF_`oj{hQAh zSb}H{mPe}U%Fxr2$0|%~KIxn4zC{)*ohr%g#eQ;j^}`; z%LNCtT+7{?F2Crm??vbG0s}|5e=yP*yTpB-{L@1kE_(7$*L-W5lRZ;^t}w9I3S>TU z{=|WvT-38(_jy~=?y@k3`Pk)JK{EM1`$V5Xt|Gd21EYq6%S`)sHQyfpK@01LMfVDu z6`rnfy6K>47P_6()AwEoLft_!#nGgOwdg^~R`d_+HxKjc_4PvMPr9@Lv>erng==;#BKTsBP<~(RK_Riu#r0Gbw$O zd06jbzFAUxSf6ujQ4gT=hgyl&TkyV2Zok|T(FEGG&sEhQ$L?jr-ST%Awu{~=UcIaS zW5H4X`%70p&wuvk+S%uOxBTBI|LXndr}q8*#Rn&FABS8!75mLud>oVhtuN?qxm*5) z1;-2JfkAqZWYu{PGGHNUy z$*9Az1{23~JWsRjkYvydj}uCJ8Cb3Gf`I>q{)AU}Frpe+-GOCDvT2^=kM`nu1~2fy z3MM@AMgDFO@Inzh+7yQ#XW+=F7`hW9kd1M7e5YM1a_7e5-^_OU-D?jc2h2MmDiq1>gxR5y$S+#$-fBFz6dH^YvXBZ$zH=F5 zwWh0`==_2Ks@8fPRXXv1@;b2_bUZJd`!;o~VGW~U7_k=&YeE)M?=1|y)uXKLlHR}V3C%~@-Qiw-(EKPMt#CR8 z+0zQUf5fn!0J}ih&H51^V7r5eOzYqT?4C|7o*)n_pA-UMEeo6aa{;iaot($bnx9}3 ziPtrsAMO!gBQhqDflF<)V*$B~fooLx8nE*Fx5cUuP$18Ye;Lu-2@KiYe}-m*%{ z!TUn4(SK_>!DD@pFaqqb$AX z^M16a=i@84ts-6S$JW`(gM=*d8aOpHZ)F2rNm1bs%jiAgu@cDG5fwaGoAVr58xSy1 z3(8Y$-edH2)*97Ai+oBc(NO(Q5=2 zj6GImR+t)GpOfSBe!WskP8V`}^c!J!oFVlOcU_!rcPt{?8T(a0pxfa?$J`z`I^HeO z`17j$7tUBi=-Lk(YlPEoM+3J;_?L=o!%Y=H^DXW0bZQ z#l1~dg}xX0nCTun4(tG&=h^#ICD0217WF;2S--ttV%$FW9Qq7{zcm%R=g{XGb>c>e z+d&(0VeH9|-P+n16@R+vsHDSVsI8AWt&)u#Q_L;QVz;*5M)rK+{dAd5;)v>z{4yVU zhLrTR(4*EtGtlimWt;7g6KVVMjiVjf*qWEx#~^8$ZA@w()>TNyzAP=_oJ(u3Tyfwi zmp(V!BV>fj6It1Lkvo-6LdoP{XlNDf@|<@YZG{Z?lI|D|$p=u49$)duV}n;B=I|M%tZtDKU3ih%FG$K|H(C)QP}=3&x$I*u0#4~&JNRLqmYmp#YW5;VT4RG z8__VrfJ`9r<_uk_dITdeZTt+&rAwa;WgL0P?L*_Ke({dQ$UNd#(RqGPYi2w0xmSI$ ztB|~3cI_%>8#6Q$vR$hb?DNPxWZW&5DGD-@$RQ=H9I3RCp`uS(masTCQ+x4Vp>(N9 z*OndXpYJoz*~YMZpIGD(Nz=Z=C$?a1StBx_VC`CLu*b-?!|glFwtT5D#=b)ok%R3C zorr!HSgA0)RlK%ZQMfe)$(q|Mn8S;yy^B+1q9V#7BLp*wIbCFuG8v~i8;IW7N;?N+ z=k-p?gj*chQFmVN$&-nW$r<1rg3N5|g*-=k25?l48?rvnF)@SVi3!{T(dCOBz6LHn zI*)44Gw9C3TJzYH+X<~sB{J+(hT+BnlVC%RzeSkVMj)cj(>P$C2rleh?FGWT;6ka| zOS#nmY`!qBq)au&QPvM^jffowsIkg_E=R7%!M8_#-~~BtLoRODSW+45AJ`oGPDc=>G5vu zmbxr>C5z0#BM@7i1c1R<-}+8GUYRLF%Q!p!IDY`Q!Oss4n4p zu3*}VzLJmQ`kvEaPXW;QFOwR&81*VieOUc*e|?13-E#f~fH%l{|6n^aOV z=`axzVJsx0dIF@8RkH9LU@|13TSk&A4@bZR$bfM$hFpI*8W_P~FdDiU4Fa9yGaE#~ zh!@9Vc!9^$d;-IhwX!%P%L)ckWd+8F{*L}(Ffg2#7t4qSUNCYj!?V1JV>#9+;_DKP z=(LaF1Y_3{^GKb^&=IWm${wF)SmIpGOIRz?)JD6^Q4^iFH?`{Zw#KDa`I}f7c^L~x zUy+sBxYQid~H?jHomq?S&D=)IJKkni1RR>?lw<=&cJ#zEuW^gAVcU@}2BF_hc6e z&wBKd?qF|pUw#bq?;QrRaXOsuJssp1r$bA5t1jXxaJ|{a3hZ2HIormSli=2_hKN}fsK>Eql7~~k_hE~^OS0UruTPagl z$+lHU<0`o)5{M4016c;fd`HhP30vz${B5mQ4AO$MLmBIRTNPv(5u~x*ZbBoSIA0Ijpi|YC8eD>=3|`6elb@fJ}A5QmWkE0^;trqHV`}x6w{a z`4F``wnB4F8)ff&q->LUs)JvKMD5EjqwURiOUoZ%-j~p$#nUI7(phnz&ws;50uDQl)|0x#G#kI>3#Tw_S1sb__kPN67T%` z6^%ddCD3sTM*T0v(1YGT?ThB$ZL`#pg{N~_^R~g^bj;(L8qw@!1#&IiqCQ@m&(+Xh zvH5A{jYXnDGON9i5IRJURllPCHAk6{Iz#>aStciIV|#Ena)~sWa!YpP++X3&!o==zfK+p;h1b z{k7u$bWm}5QR9?a5XtRj?^=#YGJTIrQY|&EA{w7QqVAp&my^chFB`HixR zcJ~+GcRj_W9Xv)IZwPQ{gKU33QumFrl)m5mnER@gqCk>eOg`4_9{t2Y@wFsCGEM4U zvQ(X-rK5x;$p^;6bh>K7o3EJv0sTcD5MW=RKr_9 zRLEyOC+FUuY0KWi2RjVYp^(lNf4IwZO20C1!{<#i{_X{J^x|3lo9)D~J2<$V`7oF? zYQ92UjP#>&KW?<<5aP1DksKan{vt1=qlwrrbt}B7{n9+*%WTv7rR~C>aB9EQdg9EQ zdT;85cFw7}M6IU&+NHbE^y7Ylee^+U4pMC62;Ec{Sz2jCipTdf*Ahi)tSFOMm00b2 zAZg9gRqs@8S?pczn&~qAf;@cytoRG}v|A+pH+%OU7e%=@0Q{ND?#?b37erhUaTdhD zydWT=hm#B91tSmon#W3W(Na5kPN0~VG-rVTFDZ09ee^`OlqOwNEK9SpRS>AxI`%2w z=oNJpLQAvtLYN}^KG&69u4(7I|1^B$``dA5*qM2D=Go_Y=6RM}E^xE4k@-(IzxJ@= zIP(Q!uMSkT6@6-xq38gKqPyN=_He8^dpOEK_^J;NNBio_SB^mH`0?Q#__(_hzQgL~ zGk@~yOzCkC!!J3RhCfrR7)Qn9s89^%z)ILem+#Cf(=i!5- zY2i$Cz4?&(7T=WtBap9U2aE_pDw~M8n|dL4FQoOGoV$Wmk`BeB0UdwUP8~d&1MRoyDIlr+0y^Q0PBdhm; z3{tJ0<7fzSb9J_17vbvMtKH!*TdJb z$)5^vH$(6}dgUK4#IgD-JPt3&TY%zX>)8_k1d}@$Ue|!vUHVAB;p`c&#ZO5)S)8%l zaj$Fa#VqaH>}s}dVdE6m7kt7Q@$W3&y4|}L05jgE`Hf#*g}?C*x1jn-TF?1xnC<{P zVz|GC8_s*s_=z}K7b)Jy0dCg|z?37+#ejC*xOIE4nSkw#6W;@I{6b#Hbin!>^Y%i0 zjN#+I_4TW0c?HEUZ52ifwFX+6y1f3v?US3|PRl1TE&pDc8Pf7Mws+(=3vzJ*T=XK+c@HhWN0{QskphO)IBQT2Iv7R!uBJ22%a0FAVbV zO>bhUw*%$-3QI*dE!F`U*pdNh0Q;D`+nE{DkR{tQ9`tY=anS^VO1S^C+D`+`gw=C z6z!+#eQMbuJ@WZ73%&w8U&dhz?$#*4G`N`|W2-Z%iSi7N*g-nHV;9hLe4bj5O(B}K z25gjM_>Q_AV1sx38l$C*j)M&FkHVvKnX z?vDA@UB0K%?PPqvUd;p5nMookhti)+8d>+$NEEL&Xg`XHnTNkTuNrc4|Cpz?qk$#C zPq%7T^bR;ome=VLmpY%q%Y5H_dfDojv#1>mxZEP&+%W1Tyk8fZ@A>6u(LZou!!u*0 z_qPHOcFOU7$&%x&Z;*?R|j=YKAr+?doz9r5Byo~A#QBC5* zU=sK^$?6_fZ5$ZB z2=gxx-bV%&2rnAsnXTloFY;VqkaZfiuXUR7e|S!P+bpP7-P4-IRfcNCp7yLmm7$T? z`p`%f^i!l@&#Fe2+cT=`2S$!7x0OL7#+9d8t1k|WNGzXbtzLM~VC;hV-YL+D$V1d4 zGog>KPdO57ofxrXy|x0Xh1LfvGqsty#3|Td+ zfw~cTUBv3+Ra75$4L;!e_Lbdz9x8}XE4B1|J~a6GH<5ipu&KA*`R4U};cr_)K0bi_ z*7uVe*LQ^d?b{yCn>9^gEjN2KIiWXx()>)l;yl*Ar;jzsH!g8kW*@sEkFMkv^*`p2 zLo2|d-bfpW?xoL=WvCx$SAQh@g2!{T(-#h;b?+lj)_-SsJBHfy&?R!{HKyN{;idhgNYR7I|W5M-w%cuSj-Q)Zr6N+=k@{@X|hsr3v+7i~R z(vvzwd((i%9*#46P<*B3-kUvujOz`bG1b1;qmLOUMN7EvkyqAO@R&9h`G+H~L|Sk@ zW$8oCJ*S_jPbAws{*2Jmga~Y$wv#w_7`RP4q+APD<+=Wt3ONbTvICKVh62{%S~?j?_+jSet64ibh6LM zBk!oK4&aZ=@p2OlpB2*l*F*0+UMXwf@U_x1Xhfx>K}+k`F2^{|vwEwrxehy7e);4J zF%AtWD|>o&V3dPyhjSX?XEJ0WUIE4qpvK2`<;duf$LM&;JN92SA8R1nEIlBlvvqS4 zYEv@ikn45U6S|>}d@Y`zH~Cho%#-KjvYu?-CFcqF{V$no-)&boJjRY?;7^t2O5p0x z%o_O>E+e)XH2(7u#uC`{?hYjHc-oT z=fGRQD+%w{fX2S-*nCCz%OMtj^;1wLTo=Dj9_~A+^j4GD*VUvY*QEW7#Zeb~Ze;P( z<}+n1R=jQ{0+HmS8=YUR1QjxV9#jFfCLoe$4flO@&wN&&m>nlhWPNl!Gw%CXpdUC2 z|E;8xlYo9+6u6_QO$}4~n#doP+L*=@rxKIh)rwR7u>+xIJd0MCxz70K5!As%wLt3jF zVkhn-2JJMv`!?2}s)t5m*L#}oZb5oPYyAt-C8E(yy+S&N)Bnn*u{QduYe{~oT43S^ z0b;c1W+>aa%HM;u|wHRsS#9%j#OmA$7%iwNmAj$@ut1qz|MBFyePOfvU z1f6PQ(j(&%xLd&_>D%;m4zV_eN9i&7R8A5$gjvTN8`8?jcWV&So{03-nTfnP5ee_%B)~J{HL*Y;ZCVy(ayx-S>IaLmr3YDGkBc+ZL(scN@v4|p``Fj6$6o2b4PFg# z1DzH3pLmy5wPh`^?*hOZUz_r#+I55Z9CO7_uB|J*9Xm@|P0N$( zevDxA*UlT1#`=%kvgPu_EMDE)@sX<^b3N+E++f1{vKaL^QHbB0q8V|B)iW;42XC-X z*lNCI42%^NXD-zaX3MO2z&D1~KRTT<>Yoz7{}mHY?`1LP#2v(w_FDH{LT%Yd+1T_J zl$XT$6Gi8P+J)imKmF+GG8QZ9^RD?z=Ke5@#lKH?HlcCO9ss;N7)C?DFg(%@>cbt4 z4xJ4DMZ-DcpozE__&hG#Y{9P%l?% zJZ?0v7DbNNKm}fd%CrPtD~XbZSE)3pxjYY-6V)pCl2Z%Z9o9U`U28&`Me>X$HVw#3 zyC`}(4I3PQJ?~*DG&@a{ON#@tkOjp7vB=HE(_#-#5sjORvtrA!D`U$u1KdrA7P^_f zxrkV7S(#8iH<+1NY+0C49u}Oq$+94!{NCWiT+4#DbKWY3MnE^G=Ace29Y#6Yi;C`XbvT^W+faIo@JUASd&Jw^$y?0c-$L631>L&V>S(`rD#QD&L`?BhC06>N`5Syxvm| zC@>{;ZZ5~`1${M_o5<@m2536+Vo^H=6LnNC?0Vvt>(jN~f}UA@sI|O)qOE{gLbW^q zm9W5%%IPcC5|gRoS|t@AbxJZei0Yq<>rTHW;qrk*)yaS$_ung#`fGK2IkqbjjuqblH+9350a&qQ}6`DmK%=!1`@ z!t&_CNjB3w4<{Fvk0w@)F4SS;%XDeCEh2tV^qc_-{$*4dm5>|s-cqhgj#zu!h>F$%?}%g$IT&hm`6jg#L_{P5 zqg*PtHXS=2q+5|mAkk`-BV_8FIZ(SCKX;J=4UNK@u_+3+5IZ)yUD0`-sF>%i=5%9X z=94z>D(Al}0wC?eX6?FEvN3!DE{jrtmuoy}(J6C1fE{Ppic7$W{*i~@K=I43UYt25 zZ611d1N`{_7t-5@q%Y1H0#ssvg5qYU+``j!mrc_~AEo`3ub6Oc@6lX|*4urt%3Dv` zw&zV9{rUBCeQ>|$H=SWE678emp?zF`Nl*HS2hQV46i@Pc-&}3D5;d1Bvuwuy?qPkY zFPYym%rS?ShQRmZsPn?*E-lUwr=BA@`TPf^&mHyT78?7#v&d0NwlizzrIHL%bqj2# z`uxQaO5(V4fklpb^8TNjbTT!HmNP|OZt!7$cSXvGSjRci*8Ako(vrfl^g{>VgPr!@ z^pA~vjlGhzCU|sbv(Y|>bh4fu^VLM#dQx6xY&xf7@!#_=PPgT*!N+Imtokz6p1rD} z?nfKVQ=|UtZQltvAF6SFoedr*d1UJw##!JH8Pj^(yO(BzFtRVR-|G7+(2{ogtK$4d zy4tY!Z#u$iJ?6aD62{7tYObEY3cShx?)aK8_R{cG5H0rZ3|o7VIWkVqc? z<=1|m$r?3ndk36mZ3(YAgPYlxP?X+W{l#;QCKjXP2FUOMV8#bGLx9o`Z|SeOHzMiK zpCIyz@H|X)xIAxn)unoXhJi=#?W4Yha=~A;Jl91xSLEh(ONPS9XEiDA3(bv`Tz4STVHiG$y77d?&100 z$m%<^fXb3*N2RR+-89g{-u@o;ruOfiJ*k4HbUPf=zjJ@9$w;>sNz<>k1J^M7dPvLa z=_5LA-25volsZ?>1iwx;bzZ66)}*_1yr=Yfl8_t_vt?{q0YO;0bU*fqQF2f z48((25DkWaIA|P*fpf=z5qMrK7ztku2czLn4E%|M^M~R8i-)hYqLx>SIzi0~qM-BA z@S+M8O?mOWDDrBxgl2ORuhsBc6|d2#c}XXVD%2cHg3G8y2{pd@jrOTkMHSzPdaOdt zHWhMuJr8n_g>B7G+Kkt9Z=HYx|VGxIJ_uv5+NAv2Nt zx92UNV18NIyghH#eBxi{FWX`*B+CEC-n~FKQ6&rjzVk>jX_IF9u%xxXG)<*ID=CFz zR|`y`VuAixd?2nALaoa0;%<3}$fKFGr7c>tP~YpirGVgT<)Ivv6#~AXRH-WkPhvX`w%u2q3Egh$P8C^Nh{M0yifUV}Irn|qa?bL#;2y#hn#i6%fneKMi zR2*8>s~PECo^aS*SM$`d#_9(#B~MrPE9*<9JU&} zEyXl&T&dHZ3(YQ_igaX`PD`B{s>3Aut)P}`&QG0MY=)K~^QV-T^qYpPp44f6pt01b zFe*DO-{?0HYKKbIA{DT9(I_K%z{rw-1c8Ds1XtLBIXg8^DYdg(vQrzO9JXFFH9&i# zvYfgqi*sk&zo=Q2mE;D=6*X^XCc1&HLL7kPkm(GS3ow7c&A;=jK+}j5psd1`PDqPK zvd~PdSu-kF6SShtHbE%Mf=anU*~@H2sgw%>Rgl%1AV2}Q%RxmAQQst)WOq3a<)J31 zU3PyAbs!TWs5gcxV2Dag3AAbMNnYzYm zqls*5pQ}+I&jMYBpEvQe(BO)Q9TG$Hxs%_p+IU*I(Wa(!Gzu@eQF!`eKfalZFJdVE zL`fBI#q};7>LIm?KAW6cYwjb^XN_f9@!K6v3Gctc+C2`L)R|3s<7~ZFMtF1U`TMo7 zE6Sdw>^eiPcgzNuXz{PuwHXcvfuzaeZnbYEL)as}fq{n5#!UO)klirF<)Gi|~!;wue8{;6$o^%1R&_U9wt&dh% zYFGEG+V}=&ObXyE!so-%g+Gi35*aI`eB`k)fWB1K#l#E)b>tXLt33OfKlhIMvMP&k znvDN278W$f@m)B22YNh#zjER7Gt0HcT=y?)T>(paxNdLOL+AgdJttnVt`&_Lg4cie zyzd;K_eSf5QwH#Fukq-5(kjoidV+*&Y|n1&9b))3_FBES?AQ9AI$f@wAapQ-D^9sl^x?BEo+YjCUYn6VXb~hrMHn8SZR=5AlhMtF4TQ7F4 z)TV#+y20Y{x=C`DB%b;Jl83@BLlkPRh?BcRJ%#$d$tXNyMr@iE{%!hg`fs1m$y@+f zDGOxcks59Tx8nbYgOT`Mgu_5C49PGKwbaUnaYNvLGRT5+$S{ulB?CR9<9P#b;y6~% z@w}dcAzr6r86Bh7q0vfN0S!Nj1|-ETw9sg#;W{2Q!D3m?z;Xh^81y;=!*VQ)fh#i` z@WOhQ`;}eByPK3yQA>FRgk53`wReCXDa1si6*~;P*M;#|Z&JK6ga`&>qd_utC2|#V zHE^zq46qJNUA2~3#?(nuUtP;IGv1V`UqBxgJrn~&U1qxFFEP4|Z zI`|&ri{4bQv;H1v^!Qnu0_CWzW|ZF#ltR(O#yi$2Hl&0F@zNTF6;r`Wz*olw_yRVI znn{FLmMY-AM5aq+i2*583I6J?L^Ms1mQAo_Ze0$|hc4?hF@IpDhuQ>9LcT^_jZJAv z*$Zs>vCt}DlVelzGXwO*O2p^o$mK*#WwmCpa3ZsM};nsP(4&Jbs?9; zDgtQImnBJVL26>lW=d|WlwVqQXP^^G%fyq}5unIaS8V?I(9zDM_(@Eav^TF3Y9CJ9yb{{GK@imc#8TEkT zI9Yj&Y^&iN#~%RxzN_9hc^yttN5!epjPH;IXZx4EAr|-~QUVzF$&myH%{*6({YRc7 zU<^`+p2z7w#M>65wI@^9BeH{z+xg+Q5&v6!n7l)6=AQWe>e{>r{hV3ukE|8ywaL({6Yqy2(RYP>yg2#4ynk3?wFV4OQI8rw@f2eP; zRY>2ao zy4kqWxt^hd@j;d<)GFc=Ay)alOP~T`PKe}4C|UzF(&D$&V#}W$MkQ6tm>@X{uJUxX5YQ z34j%^=VW_a8%!~L#e1|UVSx5L=dY{G2eiI^aQ}+{Z4JZbwUjhVMa<)z+>>Bxxu5L z2+RgEz+^BEj0aO->_RXH{{1+pgz**N2`~#3!`OK+ZYKO>He3SD&oLZ_#=FvSoSxP3 zs2LXgi{YRQ!|^Qom}faO1QyT08PEqD1J$8_Ss2L~bPW2F=QtM4j(Z#GQ4d8O&$D6Z z^*g+tVOSn@MAUO=6=+qwp4Z_I&<0Vw4vo{r!Z^4T%l_&*uq&?+XM^kuNFOQ9{+Fl^ zRGb&60z?-ufLy`}~x!tUoY_b7|*7j|#{ z8TycE_vT|Cd$B)wpo{{yjyDxG+1=(RFZZbA0(?IRrn~gPKnt&BM z<#Ze4L~*K#~voWJMYj?mdv%JjtN20WOAqW=-H1{E|Aq zWD2YSHG!X7dM^4F>TBs~>{_!C^+WO=g$kMx!25v7c-mw^3Wt$X1b~Gl%wo z%n;{cPkErqgS^k!B&?4$xyie&=K!TH;pv3USP%9952iQsdg0o6~;crf}ky>r= zYeSY>tTxn#SW}?_i*+FGjnF&ZuY!FkgSa%qjVcZjp1Wxg_MbN``aQBmvv-gaq2C0! z7rF9Xn^TSSmY@x;SRXOjBC;=_uo9M-t@>083NJ`+%iIhEoHr}@Td!s6sXw7-o#2Mk zN!2>(7IGe`7R4gMp8`O2J2scv{G|)82ke&B(=Pnd0#|sCp{nmmyzG7J;v@^X4TFNW z`zETjQ*pTN^&%0P zw;cMaRxM7%XZZs!?O&<-`rzB(_z!o!Lc2+Vt=`r@7(H%WcG0W5N;$_2oY5P0@c*8D zQ6_h{hZmbx!*sxvGA^TOlf@B*zn6=ZHmkk?xIF*ozchb)JMEqH>V{VDcRt%36#nu= zyUz$nnZmic#isgJ;xruk-ToMr_Lm#Kv8~s4-idf0u0MZ9umBd9=JuXGc)GXrAWhE$ zU=;nKF1Yddd#dm0oj5&>{kN#TVfcgSi?MoR@jEzA9@XAoZ{&{P`CB`z7n1T5YDil3 zZ~OC?`0#=i>(ahcrIEM^2dAbo`X~j*_dC_kte2MJ@b;GW6NOG5_xUW#vTg66>9&0B z*OTvv(&4c$&Z^(f-y>P;Q1~bHz{L%sfWOP;14$1T(J^1otGgDYW_+ZObne0Iuj6pq zK31S#QIvpKl62+7TUn`KE2g z^C+Bf{`ewiT^ZiD&ySxuDT!{}WA1|5uS1f^`-UEy*zS z0=k>z0GSYtT?w-<$f9iGG^kk)QV4QNmnuk;2l{|wLZ%Y8rXE#HV?Ce&nt(K|R1!vF z0hEQ>u@TU%9131j;I=BI1+5F-MF22AsZ?qqoJ+Q?NgBJ zqT3&h7GvZ!0oH0p#g15$f$T*MBgP{SJX#wTc6iN@-GgewMjx&jvfDx2XKwzr{#&t1a4Hlbm5IrOaw4KvD3ZZ>T~ zLvgu@Vbdn==#l z4$1R=86-fW2OH2*BNYS)E)jI6($!(^0feQ%pf7|Mp69Zu0!D$rRrn1m>>aT6@i_A?Z`+pL6f{k?)V0&7Qqy@7a6pwbuSE zhd!A>CKt6%U*%>)<0Ms}>D2~!Ofd_!D9Y{vwJcC@F?U*-zaSq&b*MQ^QR`3=^n2GxI#nFOuTV z>d?Gs)Et#(+#`7^J2ZN=lDGh>rAiZ;hK4VIa5T-$3}6Z#Y9M_Mgj-Q9guh0N2_xGR z?c-vi24+%yJXOsccr8E=O5uREvjnn}Zq@$bB$jC%S7Gqi2gviZ;xV$LNrG#U$_{0; zK})m}x7t8WFOtagzN7j1MQ3lc!dOv-$I#_RA}IXV|OVmzRN`h0RBA$b=wv zsWzpia}!^-B~vdA2R1q&SYkrP@s4djcEuGy{|D*5J?XQ^ji53q^YmH9+lF?1dhsl% zSe=+Xu3$sdMr7_9sB8SdSeoKO#S5eCLCD>;|&{ck+O1sT6UVY z@8)I_)9DKyIrahB`m}-Vtu2jD0{GJRT0F0Xlv{)8x=-7CvOk~RT#1>)H`8U4RTs$X z*XifbVLwmGHBqG)KezbQdpy_K&`baQ3IHv7L(`4hi+Mfg8*7eD=U46>_Qq}==WL7J z%3~RtY`o4>4hXFU$fx`2{uALB$WckR{}|3cEjg+o7_Dj>huc z6@E?|S7J7Mc*Y@X2fyOb!qmIFD2h2{qvBd-$l4k%xcP>=L2qQZX}E_88typexVb&J zkRoNUGPpiR(ae3Y2ibn4H*%wXR*?-Kg0(>&f>(e2L#YUq*ykW~Cwe%&x3Zqn@)Bmr zZT6il>F}=PFxXAM4%P;K?_R}snZvm6tfMZpGUr;?Qs=1HH6-_WuC@ooQm;NHN^XXV ziByB;7t20hu3-F?g4aj#_E_es-pV>9Bp0y+CB|Y_(`>ZTIU3L)M<;r>M(r@Tx!8(1YOVH|`qQzy%uP^d4j@BpUOW z(QJPRjUL2|XBv7inY-Onwmp|j6aK`rtem{AUc@u3$eJNGvK9V<@soR+Do9M1x69tg zF=k(Si(d$jx9;xxS04ZAi^kc&au`DEoguf$+@7WL6pxb$WIB$R#vYFITY&M->XWzt zbb}`Ucwr4FC&Hc8LAWsVM5wl(!*gjn#+l@#&f_loY0TkC^JhKr(HX3p!CahBDE`kF zKFx-=hGBgdUCBiYkK-6MbR|#U8hQhi46_9jzW&x$`@jUP zgF!H2mW320+X7}?z_AKPlHbylJPbH`VG0Z-5sqXyoaPlBPX0Qb{(c|$N;nRV%1`k3 z5hayQ6#N1NKdoLb_^5R%QSuRdb&?pM_7C(Ee%t#99SLYe99{#2;9sUi@ulD_#k#v{ zb@RBpk;kEySQ6O?XPFYZIbj0&XlGp;a~1b|EqA|`dT>O5s}~NA&^ujBjPqia!$I7!B2ip5 zC<6tHkO54ADk%2y;T)GzrbTgAGto3T7!6O8hoezxa%!fC7Nw5W5Yw6chzAv0sOzW$ z3f86m;6ojyn2z>+VqJQh+G)tc>ynsZNtNEr3`<1SnPJjzX{@KU_myy~UEEsxeEoj( z5RqJGw;Wo@JY2}FL(ja(eWvb1u8ui^*z9SMxehy$$qr3S(L_@$dD`0ocbVQaCySaj zCyRVv$^w3>=tWtZH6FESv$9YDlRW$;vgP8%#-7wE`=8EGA)|?9PJ?@A8Fx6kdw1C$ zGK0bGd&(8pf57!c_j)yyq_&G6G<_JB-5Cp^T2iCpp# zP1XrU#TfLMf5x0gi48>Djt%~7dp793Tjrtc+meyGXbye^Aggt@)J3en_yYNhcT+RX zw0~76=2%eW(k*kT>wE`^>GJ{IeTwc^*|2{Tyk0W0F-T=r`eeroslcYUju?4FnPy)D@}2gRE9>>;w4Ne&%b9KUl3avwe!-1hqAb%k zw!rR)q9d|_w*6QVM;|&;8bs?m=Dl*OQYnT*-daP#5lKhex0a7?{!gP)3Gwu6ojYZT zy_c^&@&)*PG>ui5zkZR5u6vjLR3SXe;zbK<-iH*nQ{J+-bdl!`Z2EZoj+roCxV&Q* zj~}z0*o2kD82{MS`Zo~y`jY7-%PI`D_I_3{viU4p*!(`;9^!akSzs5YxI8jj7g-x( z<9*R$Z-l+f+Aq)}m>cr|&S9#`m>CJy8#gDB&#RMBC$tD@6LZiUD5?;}=>7wRQZ&FvC^3pz(E$_C@hQY34zn^-^oNBbiRfR2Z-^sBckic~ zCO@BbRJcvNnftlSJYv0_IQ?X!nJ7_a9wxNJD_T?L*lf!ITtr-j%5)>VwRy{{)#t zc~2U#Oee?eX2$M@+Mx2jL=|d{ZCBM!ax+*lq&A~`fK}Z>q(8QiJX&vl{JK;luqP^*8&?`2}K9#w~G^%*PRN5#uNBZ%{(FZm=ZniKQ_aUgmz zdI9ylpO_GbR=PS^50xn~x#m0(Do4hc%}Yfn869J8UP?CLXd|CXHOKcyjp<)fQd5tFD_OXgM4wc*m=GP##zeqfcW^t2E z#Qb971OsXSv`A6(YIwGoCBsd05L_E!<8N$Jc2D=GMLL}<)R0)zTo=PyE zs`H}WKX zb)8vtKNQpF=f8NPs!(P}gQeNu>>0z`cT|^beZgSDczyW~CnIE*7j@d+pv`>)S$XQ) zn})@K$zik(txy;|#%`BrH=gO$2?J8|Sv%&uKlmgLgQ4`j`rH}dvqCA+hj#YUz6lBR zmwVeU2AoiiYqQ?g#}z`DvR;2oTtA8wn2WewT)&47TTcVW4~8rRJsmS9r!xOw(TK0qm+x^mYK#1bb(|k zrpERXyQfdqov)Ec3AEjCaC`GBvXXl&XUCfS+>Y{wd8n#t01t*3b3wHWPJmyeEh`ETKdc<=N1!vudFMNz#=xE zZ?2tQ1gUJAoA&=&!Jl6-vh8CYdwKL!()medamnQ7WUjA^#-5#mCOiF#Dmko4A{Sa| zT%BSBaXi(ML_Uh@2otrF7)#BxM0@d6&`hovPduJ7Q;!~UIFFf{q|c?M=@)BU{FoT; zbo|Z(`s*%cIvtFTMMsnC?wtn`sjb{iiPs+>wrnz9|1e) zCcy~hO82J{r*vAh@l}j0cJ?Mw{Y!>L7>YN-{INK02b4eB6?Y%bDRQi1Dx-^Lxj|!(yVAID(W-wZ^*} zN5y^|sOZfe3%xz535k~GQfGTp)P#(aCO8dsI+Yp}JT;trA43hE!eil?sO0J6u7(jY zr63ik!9j}HVtk+CaK&`RBtwZ}sS2G3r7CP8nxh^mZL`IOryk=x#48LooP&z)2K#I0nLpz zLJD!VqJ|q14I`bx&nV5te3Si-k_#r3!_&D*pV+xc0r|Z|OX*b*FSf z32Q8!QX96BoB-H;mYOaTC}kd56<~A3A&CbeUqjD5aW|S?cIK*Vv-2}l|J!Xk9;@vJ z3m7Ws`Tdo}VN+Nw7WN1GL4sxt?R+6e2G)U@-FH9ntAKLy<)m?!-LDXAeu?b8jDBE) z4vc9(B9n@aD?Mj@U_8iGHjEcPeeFN+jzx?Mg`_b6x9EAlzAfo8Iq=ZBw7GAH34Bb( z>DBF9_!rQ2T04*IWwh?<@OP)4A*Wj_Th3x^Ju)+5}2o)xTVb zy9CNYPyHkoQ%%wW?%Z|X;i0++{sA7?v2G9u#*wrg5wo_BAV1S+YvM@q6aS^r-_ytr zH=MRH;*=w3t79^q4qs*MiGrWMB#1hdPU9OO=rw|mpVm+C^Hod!YE__0^3$n%=+;4Y zhd5UI$t{W#1)`}qmzqTka#w@qDqb%>r->kT7N7fr;`r_Snyr_ zkW;+FqJ)SY;7T%>FJ)|q%<}4LMQeEPR8e&qDg!F~LV;^i{ChuCG95%#a`9EBk!qFW z@rLJc#i-(<`1NEzh)n4vR0)>}g&; z9(bX`L)nzA$Oc7mQMnxIT?0Xx4IaP)c3E@cz8tiD5VgUZf~!NQlXnkkp^g}GHkz18 z#MD{ioz{AIh@0qP5*n(>@Wp_U(eU&d8;Y0-I*xa^HJJS*C@QIqQw_^`(~2 zFz&R++sWV3_Bg-pR`romfz~TMvr0Q?q6oCik+=5p4&H`X7&LfvvLMssD7l+8ak5g5 zxzgQ#nOw?pD&@UCIssByyWTB()Cy-?VUr9W%%PQ1lD*}B*}E6;CaQb^;AbY2WRiw9 zEfiYlBW=@C5jExgW?G=UiWIh9d;OG6p;|8MReXR|9+~t-z^e6eub`lSsI0nDKUV|< z3E%_p#d_~zmkTsyf#QeQB8ot1=l;)Q+Gg626xj9K?*K(Wy1(P(Yk#NHNivz4%$zyr z%>VG{p=2_B-qX6ih_yxj_p>|mk(I_sYQ{0ot+f3Ve|EKfuTNEWE zk^f|)DJX|TD;*Di8*#%S9zn-~n*aqNOfZOg-XLc|t^1P7~ z0tH|2uL0u%NbmmOL0l8bbI(%U&r_e(`Vm&Z-b0n{5!%#&N3g4idflq6(pSuVdhC`= zYBhCh2S_`>u}DY+V#{{ePSiQEu@|wl&vIOTt^+U%?y?}O6+Dm3NLY# z+7qxDd$0+_RB*7r6@&K_5_jxb047%K+`S;2d21@_)9NNL33WGY%4#)@n7tr52@N!C z5*8$9pp@`ugga~w;tVj!to11&lek>SgwN)0RGYn*3sc)WV!7}I>W#Hv3seVCcMaH= z{)HQS1l*-+#tv&!MBYaxQ|Dw3dy=^V&QMqnC~GZ{Y_ckxf#ggHHx37so|%HDk_oeC z4|y5Jj`VzZX-@~P>uWmTGX4pPo>RTie6q5$(+W?UntFlb5$wj+5Qu zC^THQ$eC1F<-_3mIy4^w$F;KniqGSqXhpSZj0Dq(b;v1YF|%bb)9K81b7(i1rdsOf z?0_!AW4Qn99XN-Ma}&{WN^q5sYH8G@)GXEMeB?g7@Rq}6eT)ScaNfD`yY;Q*Hm;vn zQ51YRjn=)>|EN;AiqwIfZAoh?@8Kqwhk7NQGaBm1{rWP0RMJ`1aivcr4Sa-_dtADc zW1ks2kPK=2+NM6U6lE+K&bFaB?g`~WBI&<{%Nc5CmYAl)%id_LAgw`*M!6>x%F&| zy{Y*0!jH)E#Kw_)RwA6IJw7xagZk~W!5_lNeFpJnfsMDxVzQzVv~~E zqR#(q1Kze)vOMcIMbCmG*le7)v>Yx~i+_c$bl-r~cxJkTI{~u(@7Z*89a1akexrn& z3x9`r+fdR^ek8gb<)RsAI+z1L)6ppSdnQbo0VT32P~OT$W6>CxItrdO6XqBVC9zES z%|qFXw^#&R3bW{V&cc((TY4NVixWf=F`nZ%5;Pw7+QN~rIC$Wkj)VCOI7$}&uL$Yafxm1 zY=I~zGgH905}P+gc(m1+k|b;{HIFGsF+4}KVo^I`MZ!_nPo7>pb?AhJu52j#K%~^F z4HxRDLO?Sl2`fF6o4FAQ8?wPI+^educkpp+?d#c#<`XA^7u;=5nCHkmB~JsZsSi|V z?v*F2uFIry?Uh=UQ09--GnoIbF&4`muL4o4==gsP$6DLmimhrjdh0|F;;Vdqnpd{B z(gr5(VD2P36E{t4vE8-BnfT_!rM9~^f<|KRWkJoci5s2fWk|r?_{zGOY+6stiwgRhcPV}TX3mo#TukNL;B5v%z96LYVzI<=8M65~iV%=JE zJL+Ug#qG?yxr2yk@}jxvg>s%rMw4!l&>&M8nl##r6(&Vf#dg}^(g>Tz?AxY+8Lkzz z6TWTCp5eOa12$r>1I`o~TScAutWzgPg_mYUV$H+@t@ds&$3$($ETdNW+b4jgs`$ zFBy_J6sD8;&otk1$zrAX#+KA3i-pb~f6-{N2x~LxGKejfG8*4}@d(T2PdqeE>(Vsq zR?+Gs-NKgM+%O#Sf5G|DKH&u@yODJ=^kkpss;AH+GbkR z%~Kt7=$8)1%CEkyJGsHt)hBUeV*@Q4jy%?c%Y$SY%Eo_%%ZX(A6FIjHY-BOwImM0| z>kOoAb=yHzvSHqi2;t55Am>U-^~Z93gp#M-KF z|Mq>Dr*&M*#)dv**>)X0ep>x3PfTlmUwut{kASa#AF>QjO!;|`B-4BG%d*c;^|ED{ z^3C_Lk|2`#r+yQ?N-7iCbC1Z9*Fy3$K8;_Ek_@EaSDvH$60!9&bN8`0l+=?s$uRPs*W- zCj2@`onJOYNl4vqEe*TWd{|2A61Q7>2j`H#{8W6dNB7;?ZK>L z7SJ~ov^uH0lWsn~m^thkP1neFkC|)*b`W*VT#Zr?uQl0%N;kNTr>67z&P`^fg{Yl5 zh${ZsUlg)}zb~LGs}8_7p6^sEGin00C-dMm>UW_!xpQAMQG2lhsWFIZC{XP+OrR9O z1yQe+uD6I(gP)>3i2bP^jdCDIX&k1Nu9vlJz{^mrW=B0oRp-vvDhH5um1#9MRCiM) z)vV4%A!=k7rCn9szM|5PN7f`3D=GycFS~#y;~~=X&K)1?;}J?AWtiO0nqP*!oV8mW zk#UbgvL1?0zO9}WUV5qdF15~sye6Uty_GK>{+rq->G5d^1JwqT7gnU)sZRgwICsB# zG;u}$Gzzvf3AE#iFz`k{F8I~AoPJ4%Bbek8+B8vNZKyopTh504ah*x|=$GMV%Sfjmqm zQ6KDmuUC?po)F#3PJ4TMT-klhujp_k=*-<$_CJ~T=KGs^t=9NESnEaV(55Skqs4XV z-!;DGFQ39pzOq588UA63W93FJCNv|rcW!rPAFUtz`*HwZ+RS`|x7!!3F=kM5gc+LEVGh`_YN;2nb_=-dzy>nYig0JBW$-BaAV|?{= zp7rnAk2*g;K`wG#mZKlTJVrYG@GR%)Go-GBS88QjH`&Bz+% z#rcbhtr_-m5{ql*o?5*1x)9~&M!JzYPxw}osff4bkoLmqC2$o&NP|9*xDWWZ(a4K*5FTF8=}bD@!f4`+ycv({ zV>H7Pc#`l_@pJUNpx2v?*X^_UUyHLqr`8V2enx>Zc2boNn}AKFx;w~&2ljw6wmh{& zPROqTE98V?)x9S{Pu!NhCtn0tS5qsi_Yvjl$=H={?BHdf2`tAJ_QJkrviBNV9zz^* z!rz5h&K`|@pUPp+*Tp2Me%KfEVFjio`k*hy_FM(OmUkO(6Ftdm|Vp<)dn8w6?!L2qX zQbkBrKpk&%y*|k%(;dL(MWp)I=`ZKp)n1Ns)*;Rg&aKPj>{gDO=cik%ZeHCuuFzVp zd*Cb>1O7r?`a!FDY{KAiLg7lPb7ck914a}1gdRG?ZFF<{XIb>SXFmNO|e>A zwfGrB%m*u@c1IOkMG>?XBeVEr_s<;{IPxh8h-;p(l15p6azp4l^ht(B$U;Ro*n384n_+H~^XA z;j#m3Vdk6!A8zM)BFBs*&PLXp^PC(r+vdo*#L2PuIUM5;>Ezh#0FG}{I;1NZPBfMb z$J;y4``0y!QiNlaqBpnn^eL_)5~IPz*X)Gpq&*SG@5-RV(4d-gVds>FA_?c^$iBPB z&M}O}`E3VpImN=rqm3UOuXCNGeUW}qj$b}kZy@z)*5-@)+lmaN?3TCd=6Kg5_l>3V z|5%_by6-%BU!8rd^4NXkec##LdyX*+u{OtUZskNGdCfd;?3(5r+TZH362DY=&`4f$ z+86b`r+=OCGqB1ar0}b`j)B8JxpoRp!1yYC9IrKD`N9ePkZrg|J^>o{#Ces=o}=Bk5-` zk3(x|{q3=fwuK~y4Z>}a(W{YMfcur9cRxKhN3B6vQFQ45xoHfM>w_I?%=$Za{A~^7 z$!8x@ANw3)V_I+iOSgKMPF7a+z6*uw{9R2lGhn?{SFcNrp}B&|hiJ0K6y`wYP(u(| z{m@`$bO7_ZXl@XL2C71x`&%boV@Uv42>w2)RqyXJ0bCZq@&F>OL6VK>&^SMk{IwZu zzX*9eh%P3bQ6t;`!-C1)&xAU6xyGjgSQ*5!00wIY);0&LYPaXLY73w}(=MA`nE zWem+g$47O0=j}WbkI-IH%X(2c)~vScJy)u`13nGe+7B&^>aQ+&vl8o4$1<7vwRIJ_ zBNpLtru*X95oE8Zn0_!v&A+$r`x9!uSxLs_8ggQ*Z~7khv-hDJ=|=hu6TXET@X(&e_{T5jXuU)$ow~E&ucW{ zI;#$w)YW)d|LoM&VnCM0c>(-G7yXaxWpCc_Vo12G*!&vODV@*IgN&vWokfiyJ=dYEJ|a0VSr{D1cDJidu)UjX=-CCQ{s zleDxn-KPr>P#~o(R48;>N-1S4Y5`d^w1{3FXnlTERG`yE?c?IT#qAbcNDFdNyxxKv zBEl3Z)|Ik|3fxC11;hn{2nB@Zoo&)2wzi=6z4wR12fl~tG|NmfbLMx>`5hjv=Xf+c zQICEbZo#Yf!oP9p;?yCLydoa64XOgsh}tq3-lItX<W1A9UhX+ExN*JXY8CWAPh0Z`;L{`a57bOfw zURac{c}AchUs%j;o*@YGiN);t+bx3Jx)`jVWU+$Qj9_oYM(mAZV`}jF3F*+Z;3}k& z7FIREhW%)QD~Z}iRN}+NLG942CTLk=SXPzOR~gDA#t=ClOBfcZDPUMbmh51Nz@wP~ zhAeVxB-OPi9Fs2cg;OzMADrv-PaIW2f}apaFB!D(U8I${8{Pnb?Mi-q#f zB5e%+91%Php2e2i^d27%mpEcxVtGAsdSZp#;X02sNNHUhQjlKFtXWebTeDxisb&oa z9nj%U4p?^#=wGvwA?`q0v7(n%zFMnfXtvdgE{`JXui&qUFQeTD*#^n-e%8S*9|StH zylN0o_5%^QgW9r7RkoE^^#d)rvKdY6QlvUb>D2l8-ezH|nO5}-94)|ypjRn!8MQA99 z8E@@yau~9pdNlTCb9OKY8{a>~Tg~|XEL6l6d6`em8_1dKI#q|%HBqauHm)iN%Gg+0 zqqEd8^{hi@8t#y>1BgLHt+#JdpFzUotqPB?_DPxfmuHM&pj*rRbNg+0T;AlS_NXJ7 z$+*$zyt~hp%%XX?%}y46YRF6^c_~dSxl|^>(%VXqK3!j#WfCuYRI=FP>d~X_`S^iSxognjQ3(V3u*t ziKTtNzp2U`fuHN)iGxyHcabj)m;@`uL*7OLa>N~2>(xXzHa%am{1%xcbw zij2?3sbdUVE}gqz7Rh^j^8Vm`F8Vzy-1c>hT0YmVy;2}0;rF#9ZO=QdN-{35vE}6V zB`36WEMeOlCB^DE!Nam^a3DTeCtSGt=lcG);PUpvSLZj=$E?iZ^3@n`ss6`NCC9X*T6*)F_pEf%ZC?N2bg^1qe3Sld_HK7yx7rzL?Iyz!a7M?HectpI_zxE6%yn!4v+1x8@X$>C zMqnWAq_1w{iq!Fj56ta97*vsc@?u@kVPLkW;^*Rj@Z{2HICAwnU?%$+wg1Ak`0dAD zZ2K=@7V)k=eKqzG;G%(JG?v7ki$9;YDr^i;j5**pENb8^sE4ZU2cLD}4|Kns^7FfH zJf=$bX>pjZiK=P7a>IzMze770P|ba*34RXfLTeWa*XIBAB2&wHXst+mIiC1dH@@%Z z_AZR0#&%((zqElX($Kj=chW$C5ZjHtea-925ML#8H-dlfLaVi1YPeRxuRDQO$?{Ya zdZy$roi(H3IxS20)6z35R3oVL^Tl>!2z7|R%=Kwg1ysIgCixv-d|gmN@pX2|V1BbY zKCxgI9|eFBU(+9&8I!C=&i?v{X}>yo{qw7xhtzS1e|s9-=IObK^KCluODhFI+W{c; zs}~$$GXYR=6NBYv)B%{}I-maTX*AvtjWdLGq41@EHq)3$2&WIBcRlP?65;JS&}Jh=82>=^j7G4Ox4;n^0)fC+%5GbEy(@w`^6 zG2j^yc}_3{u)L0E7*;^>EKbMKxRwTQtYJ_lE?y5;F$~A)7%rgOm)z~*AKmD@&j$lY z6_#Nma0XSV9;G>8*cd&Sj*LTAGumIuBXi^Qh8Z4LbZF8W=7Xo1TpjT)o!*E%nWQ%s zdD)f}Xe^SR2IsN+r1MFfF;V(5@4SPHOqAN1JUY1X_J-c` z-)T^d{hoFtZ(rbXq@(w~N)akQNWHKVx^yJ?33~Uaf#9bG=+J?{RpxOEQQmGx*2=5x zN&W&*?;y%h)T3P%p&}J@CWylVK&z+fEkT#6V;p|-BGU&`0NkSRY#+L^db#54RDzvbup=@eKeE9>#&{S;g)YOe$W}Tgy>Vh(7Z+_Fodc2c(CvvR| z%!OvJZ3c5SnzPxh&1UF**{ua;yFoK0yH!#Rwi^r{*+y&@QZg8!*%3rGLb4bqQYW*! zv=NHMXbRY+y{!qE3#~DlmgQ<^H`NS6E@`SBW%@JpW9SC#5Yq;ob^+0d4BWsO7v#$} zFAZ}8WSidKL?|oUghZA{f_T8&QR-Y+Q&k1O)J*MW=woY!oLnHLggdErY_HzlPOQ0OV3(S!0d>l$nNQA0THKmW^rjvHVvI@R+xpT3J3u0a%T%GOJo)p9i?wt>#_JypY<2HebK##=!gWO?zY%v{$s9Zn-{I=qdN$590*@A*+{8q= zPcFpuH55Zij!(dq#*6O0SI-~CXFL$teyAd44jJUx?*6(oIiAF6WVRy?w`ODH9sP>d z;ilHokTWCCx&qNz3;gVkT$*We;`-^!Z}NAzcTMYuw=ta>d6QMdum6hs%F@hm2~Al7 z4DH|W4@z0{$ojtRY^)Qwfl_r%F`?!)EFW0j-i{ffn3y-4C=TK92Q;37$vC}$1GMP z9^ZC9G;=_*vYgE8R2tzLp(wL)@5Aw*J0m~@$*=n6=h}JTCJ}cgm&2k))2!)W{OlWpGGJ@^E$k@#7gJ8lWEkyu^$&xf7> z)zSD)WApx#CxMgB`;2n)D=~O|;kNH$fZT-l)@u#zMR3oPTwk9v5o#XTM|1RV0#JkR zIUbpS@|uu)jwPwz4f|h@kX&O&2e}KCuH-tmnOZ4^@6Aclf!Nx~dB!d#E~jXm|adQyE{A{Osc|*E5-(%J$6bJ@5|JSMgc} zolC>DzqqIBF3zPI-Gwo#bbrt8#=1jddM%j!};tWho|Ru(so011nX&m6-VeEmv_-hgbDqTg#w5fiGV=q;)_DdJFUv3=+Y z1$qp-ia%zLg}wm29r_Hv(|&uIJPYcaRVFVA<#)QE4~OzQkoWPtqIz+b4Am&_66KYu z(*d}T?^F5WbQToz@s%%Hw4fNoSFRScAQ7Zgt_H{v*aR?w{~JRL_i?z7EVMT@1h;t) zM>9kL6q+Sdz}fsXcj9#|o@=^HC6#b3RR?8><>=;#%8o@A0Ct+krt+cCI}D#9IUh@W ztm{y&C^dYBb@Rj@_#n|{uh{uL^&5Vm6$=Jh(~n~RB-B-F{Dt^8V$r7p=J%X&a6?iH)cS2kA{p4unD<1 z9sEc=2S9_zMd@H4vVCJ;x@rNnBc_?nK+N=;SBH_z&5hZVH zpiUnJ#VJui2&mC?c$9h!sq@wh4nseLpUW#9Hhc&_w+o&S8pZ|?b;xzpw*$(&6z6(e zR;Duo$K1Ee87ha}q*}*msXVg2E)lwRZv8r_yjFw)gS?hO-YB;+^(PXr=_dw&Brh%4 z6O7R6?Ewzi2by>1a1bv~^)lVpF;GQy8kbiX4dOqd$Ng5t661Eq;TY7jPoABYIESky zXYf|3bOooN^3<(2#11=Gf%`zc^8TJVnRi!CB-`wj-0szQefGg0dPnuI#BrWA8v~A* z0RJN@Px{yuX$mCu%oCS|HZ{-d%9Q~J|0?&+L*;4jnPc5{6YiRH!F|IOrWe_!H1?bK zcC%!x{~Mp)czid|;IhmdS1z43;h`a~H5_j#9o-m?$|&DJu-RUS%K6RgN)xc)emzIp zVjmbx=Y!s`J-X1!ewQo&unrEQK$PcC)a4xO8CqI2-1 zp4zh_2C(>(8*%_JZHgZ7~MPi1l|{rpSDLk0_v-|uDj!KM3Y{_lyO^owjVkWm#+ zOl|+%R#JxQ-{7CS`nKAfMWgV33wFJ4bLsGWPP6J;9WFID-VK9xxkxiJ7`y+FMeSd< z{qW^)U3>u9%54BHC%NldQLg#I<%q)TKWII^pqX}Ky6pbf(t2LNU6tZ5TwZ3glgGKi zb@VSTiwWP#P5Mapyvs@YQq5cC>f>tF;r;f|?29&+o#c3U_Q^BTT$SXi^3GnvT`u}K zuQz^H?5vEE$#V^ES7>-)(not%DYWNAY45#TmGUIKql@c;*DB^X{GtoD{}>}ThRj9f zf9yPROx_xWKa-`#h>^0EC;2TR+egSwO;6G$iJi!Ih-S9;Rrpnv3;_r{{|lWNg6t*Z z%&-!-QeUuEBVEfyXb#j-EeOy`N3}(m%aq8D>KeTryDGxY*yLL55P2i@je6Bh&`4qy z5i~@C6dUwtER!O>5yiG(N3$(P=*G_EQpEdqR(xyZ#)?y*CN4KVYiGsB*kjl^V~$lE z4B~PZjyYO!P%|1@Td_(rI_F;KOISylYOE@QT^Y+{eY@nouB70iVwU zB!FiUi`h$o3Vy$_jv64zBC*VlhpJ0uB^_pKfc+OPl0eZI9w{O#dTcgQT0?AJvna&Y zLd7J#{$N1YuP61mSyJY z*i}&YY1^{OGM%YJ3ezhpC1%T0LSDsVl4eT?Qbr0Dk5y>4n6Z4lIRF{z2o4a+k;z7( zycTKVq0x?b6aP4Jj?PD!3Wye@7HNlyNRGC<*hZ;b zdUt>(hp$E4V&>CXRDGsD7s=u4M6A&2BCIULnTRM7l(7odzpXY=pM)aIRWQCh1HV&a ztJ)gPHMiBk&wJ^M@-h7454VD=uAT+RsKKRSi;LaME91Vo>&raU)e2e1Lrzz%Ko8UG zIKAtH4LyS(wbJA|S%~J-H>=FU;ibsnfX}A=%jYFlD;s4UI=PC!dtGb}XhadTZ=}V! zF^Bj(>$YB=gz}8=Tr;>51fDTE@9r<&LpmFz848AU9mM->(z~K;{6;qV@NK2|aRT$q zSa|YHG>4`io_r|a9sJS;SN+=`H$KG26ddu*xe%n7VH+MRIGc#$Vdv{ykqeMwg)xY> z9x#5#tEp{2^21d89h^qOMcreDA*&T?`F3mSV?<_JOQzNpy8xLb*rKm4U%iZ~sv$@F zOjGq7q|zkDg!jLD4QaHd28@-h^@jDnR&II#C+=vC9x_g~Mwe-e8uT%*(Q#X2qn+3C z`1G9rMSO&z%amSMfAB+y4Nl=Ar$mDAobjPs@mip7u!Vz2dXrWx4Qo1u6DPEx!F2m~ z8xiuQWA(_#cH#NqZ0!3k?tghbK3`WKiHB$BUB<~t8S3S2c3Qs0@vvis(Jec8c;4vx zWb&p%!ju0Z#o%`u*n#CwUmb_z;jB(u*|34qoR7n_oKb($!OQ8IT_=hV%7$~d zac4_4j~{cOUw4G)@n1Ua41VRSf*QQ}ul0<^VJIKee2=E_dAc{&*?GSv&938knO5Ef z&Ci{LpDC2RYOHgw?Zm0fE{(F>)}F`XnA51QOv_|Kkzdax)E-y_J~9Rjcw`jle;y3;Kj`INs;+$% zCerPpcMM%IQ^(aYQM)2>a@C!+)T{?edImux|q2X?O98$i0Yin zp$Y${=;b5ZGm06@&F>Bl;!bXrTvvl~yF-ysa_()^>O?LKTzB7PoNTiuJQbvqmu4cA?)onyu{N$>VYXY+Pg;kXj13|67G0a+8kFY(!nN-_M0!>3bCx(7p$uG%|{g(0adxw8sd?RfQpBFGtfBfNbKxeM(@aFyX=^Kjh7a)F)NXn{#YAOyGJ5AM^{w)@T0AV-ox&XI_I0d=jaeo} zYT{57jkRHQ;5?-BXX+&G8fvdKPH~sCuH#LzSrGF3iIAz#gz_0X_EX7Jf?AHgT)8fH30O z>s7#oiCDDh>B0oL!XEdk7*x~@VK3|tFIdNuzt5rXotdP!F#oY(_DTg zGvoukwz2ksVUy|8Vcds}tGhC(H<=f(pIG}{&@cp zji$ez&N_H^!K2$Qk?`1$8eUEMAG-Yu2lm^a`q*>O?c(!ueUE&m(K_9AuDE8IRb{^a zuMMxsCBq<{zW&|XNtUSwSnvE%Ny(NUO|agqif*fTfzO0(HTZc?ABUpr8_jZYALN~s zy?N$qOD=uAh4?eiLjUaB4u(y!sJyR-UdS@JIF}y>%l9WqdJ@gcs(8=*7+ro*c>FL& zu@4*X`P2mmTknE_QG->MuAI2Fx0%OJ+GLD!Xg&~cpYYQd2dmvVaZC3yKF_%(X^zUm znh@nsS&QrOJC3e)AbLCthX3n*hh~C(FT5_dYJuLWfA}r2l1I&xxv;F6ZTy z!N(jL4NI_#ZpyqRWjhz=w_H(iU zL{P0OrkO1s-MhQ#Ro*$`CTCL~Z(OGZ1*G%JtO=LC?ZV@qnAYuW9&UC;lYSy#p&NJl zRP*@o#w#-N6@KBgiGIcF1>pnfXD!+Ygv;5C`X%db^Gsz=6}LcNDBzL$!f@xT(yY)TEsPD8JfC zONB@;&1C&@3B4wG-67Oj|MQd78C4xME!r-TJsG)vKXn`P{dzC28E>S-4RH$@_oCZ; znvs9Kw5x0r^R^hK-qY?vCKvX?SMspLSK3e9l11Id+?ge9zcs}zZQY#isU1;eBwDDb zQ{L)SE@Z%Z;=D}qHj?{C52GW4tB5g?!46LqFT*_TUCM>ys*m+{J1BT-;J(Sdn@Kz0 zF>Jbt>pYcvai#W^JQVGorrT-DgRyq{J#Cd9-?95!C4U)PiF9o}%&oXJE3?&LCN#Au zW!ked+E;0nY>yq$^J(iP+{ub_P+^R?gO{g0@vzhv(HwKsMCzf_ZiR3PTl^Rq=reuN zMmY-EqoHRD&Hua;$@G@L;RC-aq*x)@@Ze^jNTke$YjgGMbrX5~`uCb9@$xb28+B`O zJS^wsD{tEBE0!;d&{IZyCb#@c((C2B$n|e&RLPg%(~;wfgnii3n9e`HAHEhLo?+ zib<}M8e-|6(wA$F@$j3wnn=BWIEpQ_FMF2efvh|TYk?QZGGP11egwU}kY(Ytncorg zd*0P=HVs2`+-TBUdv6qne|j_HP$K*m*Cw8f7)^hR$3JoGhlC_WkpfL7!6b@7L6W=B z=oe2~N3y_XuFcEEUaq>aKitF_%qbli?&<8`%KJT?HJAE-+y$QAThxJt9XQ*|DW0Ny zW=F+_w|He-S9km-+L;GfZ#LgBTUOnggA&7bO=lMEweInE6m#Lv!lV5M0y*@iKi(RJ^I_pYL#|Hm8DmVMydMT*PTf7du zt#u_`b6qq-0>oNgyY@--d#H<&x6ThIL>)4K*Uddr8VN?i%~J&2}tif%u)1JUZeXu>wh%uqzf9=eeKbnO zueF2l|AWzRC|^uRL-D*S8iEGk_<{JZsrV-ydWTQN|LBO(k^~I`B^@*&B)>{}XxFEs zJ!g^jflNJ_S5M*%Ital8AJs{$#8F3z8GntvBt`V(&f%rdssg69T7|U{%k-ix&8*ZA zo!mI3X02Xa)M^;k(AN4>M(TO2BL!TFopWB|Zdl?-NlD=zB!$W0#qctJf8X*QpTUDdA-x;@)3oaC-SUs2M)5U{LD7@N&B53`A7&MjnymX+WzELmT~*kVe$`Gj+7(6H(WJ?M)%G zO=+R388i?F326q0hfd<(2T4w&lPcNFXd`#HWD{%_tdXc}j4*)Z5e5zHPVCPup_+(g zpiDh$ce}-{z|A3A(uAB+)vmLs2uxAYy;KFO>4vJoBe96MU)5CNXG8~exFdKJbMHOW zgVV7QZN*nVH^4&y+v7QGRe%=pTz;!(4O+yqDIzfd)M*LJrV`5%mh~2ea$R}CvR=eE zDvC?6Gi5L(0ZC%o_M4je2$DioY#uR89d2!-)kG9Rtfn+DAFGmlWK&uM6V7vf>-omo z{}ggCkk$FJB_!s2@n1D;)*~cjla}#Y<}RGf79~2yN=(j*U`%AdFwB&3p@iw zktpV;W6MT}W|)7~s;d(Y`JJZO(v4l@LxD6)+7@Hl8yNUKbaHjJDY1V3?JZYGcz$}< zfq`Nzglk&5HuW?70IBT^hyY2O~F8@_nTp#;I<>VKiG#KGDY%ukOSh(8P0#)7`J+Z`;Av`fpe zVuzC+=lLVPe4j7h$5p!!FCXS#lp6F2`jLM2bc0VFFYlXf_lZY~=^M+E{Dy3F+K07A zJW+^}=-7mJoIJh~=^PNgcX!>Z{L!X`T^Whkxl2DThazPh8J`n<@#B@5`1Rm831@y$ zSIWn?zHZWPO@-y(af@XWhih-m(|A>r^~F#g6wWMFrPdJT31}zkBxn(3}Iw z9V>bmN%fEMvQHJ*rC*igX&JRIbIe-iyP$r|a^Z%K3Tjt@n@&aPqPO$_{MUNO@}A6I zMtiDspykFYOjC!_^_kdeZ)OhbP$*}2`)2Q^_pj^&)C}enx3sbLl!Knm;6C3~psoNf z27b;w#)a$P?Ji#GKk@K6{eEx>)6Ny3c?Pm0Pqpi%JKV`M?>=!Ad~UBqGYnh(fA;P? zzKLpI0QhevlVp-6P12Uqbb%>$MJYkJw*f&Xr4g@SEans>GdO=wZxy??wvoX@9x5A&H! zr!$i|XU_6Fv?98;BfX)PuHr%zn9{E*gj(Icj*gVVg!Z+niebhvM?wcmA;RcT#nIiu z<*4Is?g*-3#5i(&4Y^EVIx*q~AEN4*Jas64fH;ufN33CP=J)Z`st%;r{jasgqiQAE zw$tWwVC6|XgRHX=7O+;+u}RSpHDI-pxCQmUoSgwI|EipN=^W6lr>Xc&o7_k$aT z!Ep4yG3eh>@Brk)5Ey}eaBQr>@Ce%CaT4i0A07r0)g1@C!rk39w7kPH5Ra+!HY;KR9$--@sxt#42pwm;H-`Y-;g>Gf_AVNZ&BPa zFb;HN4sN0&TwY?PVE-K%uPS3Tsm!;dWFxaX$PUdXQS$BJap*sZ-f|cC9r{l@Q=4wI zFZiwcCOsDPdk1alEBX~}(7Y|Zklfz9A-zo13KZuVsJTc*0Y2B@z#3(PWCCm^Gg&73 zu%*b}SXuPpqc^n=@{?XSIW@CtbsFFiDZr0P0$F z(UhHB&UGOu?BrzPE1c}0Lc4OD+8)HN*G-ihesC#VImm07)q6H5wsP=ct=P>QfLP-N z>zl}dSOr;1T!r1O_~s+yRCgkCs4s`A5c3tq%p={3m-z~@fEr)mUt;D3$yngGTX>-x z5rlC;J^sEHh(vmjMq(uL#f*Z!IxtQzZbv@E>1}-m>7>ri;30liu}Ccy<0T&YJ&r`L zAN|H4(~wD}VwW_K`X$whU3BQuA-jf{3l^+7+zB^m*2zqFhQp-#1ZZ_`r&K}g@2MDz zT`wz0-o4(11){(~!7`VUtco5B1vdZTVSdgaN0-$M5P(YBiqp@# zTRz&V(6-|J7f&|URnu>F!3)~kw<>mW%%j)ZSADk1M*4E^Ip1x%$V#zO3on1LMX{4} zJL@t3f5&aDBJtz9G}q7HQc3&DetTy3)Cy$@+3E4iiL>@8w2%F!qvkXF94ko=rY{cq zPgMY&r_fiwXNsFWTb`X_{A;kzFxisFs%6meCuKP3Xbo8SLPDLxO&?}O`j#)O1@szO zTH{Nt8MGX8|JGyi4i`P=QP-|$8(yS6A1}84c-29>C_>y7eL0SOg41)dGqQaT+Us%p zv${i**sumrjAvZz5Mbc`Q?atqsld$_Ij9__3vlilt{dZlmm&iN&THjK&e4NWWpSK>hd|VghAbuBREu_X2E@GAuM--MFUitBN z@pZ^$b@kY>Rdw}obu-Fb#7E1xs=8J?Qd_m-GE#>%)IF-#ezx!Okh;AVSWS=smlw91WOxX34lw5+{ETtn;klD;P zUkmjOq_k@jvD;&tq!rQqi@U|wRCQLV#ZwV2C$&+zq2MYve{q~e=eWvM zl!_LebdeJU(Gn{)V9l}6V9O9tfgcN4_YF=412Vs@98ofGQN&EF9s4Sm|NIo>hn!1w z&Nw26Oog>=^`t^IRY5+PL)2gwwc{DylY->im`0T+GVjG6L+%(0sCJY| zLItEkEVwRUJw$$ETY*>{l#k(k9@mRVjpA`Fpbo)CD3bUs@SPGCNn*XozrJ)4i1jA^ zm8FY#vDL(TmoCx~S7QG{o!hR8!RnIzbPQc$%V~qmI@b3%XNi>Amwv*^PAR?$FNq(2 z-}X*RWTQtRw~r-jqaxAqSw&sXeXan_m-`((@R|}mlst*%X6#?5nCJV*_PkwI$Bs>% zYv`^h_7gaL>S{xa!rJdjbI#re!|806XRp=I1`BO*nVWLqb9jbM?{KuG^GwjwjLqM4 zbp}{y=lgYg(od+PdJZ+2E}`}0kJ*0aR0Ei4#XJ`{8+-vsxs(Dh5|Zwkn_jLD6~gXZkd~I>7ftOE?u$Z}pR~+q=&3)6_8tW%&vB zt7(68%MA3qT}#t3Gr%g4vc%}WbzKEkdL4fWoV=#S{W^B};4E|uq(`u#Ke++?^x73> znVl$OAjjrSH-81JJXSs;{(h*Yf7yz+w~wZ8)Oe1dEFNT9ZrOh^vJrgn98RxVlU1*l z8nVu&paSh-ExnFCFQYw^`{!EVwt(73^FRBV{{%oMjJ02`N9SW%D!oSdQqe4D`RcUM z>Uf8zz2^6E03n<C>aC7(pyhmnTm2pGAeQUwAM9hKfzUNbf|n} z^}sDG9rdUQ%C3o#8Q+mHVRq`k*Qrq*`8L(cT=X_QU$3aX+rB$L2$$X`8(w0*$TZSx zoZ(lXMa0)Y3RlG&n_g>2m=T;4`IfOYl+|n=?x3Bms0{gzha^?V4;kVg0R3%eY+pg6enZcBp zpvv8ntJ(LrTTp0MJ||py{&mb)X6OH->U9*ys_}WJ~jQ*mGou+4~e1m>=b*J z+NO3XaONsXlQ;N+7tVj6#=9Ez>A9`|z9(>c==P&afDQ2b?tIg9lpcoD-<~m^Q`eV| zJcQ!~l0r{?Q|B4LGQ8I-PdKgGR!UuW;XVH<`hC7>S5Ah|HaHA8GX)3IoxP z3uUYQSr2zNJOC5WIvH(~3#?6#gvQcn3?lBb&Z(W#Sx ztXvs}{D%QfZ#6L^yM$`&TJ=4$(%3cbdk#)k8WWtzpOMeS+hChF9xD@Lue;S7A5nm; zBwFQCZA!l*}XvQChag*1AX572nxD2WX+pV0rkn?oM zzKnE;NR4E4#zD9FR0*4bvXlAIlJSmslqp6_5mZ3RLR))aABG5vkyxTf#_bVH^byE| zLCdLe<$6m2cAnlmN3b4D!kUn!dTmhg1}lr=u<<&M-?j}adtL>Z{IT))1)r_pRkM}E9WZWd8f&{B(6!UpisA_9YP?0)7 zteC}|c@zBu;*`1Q{`dcZ7~{`orpNgb(MiX~acxW^&hzVn%0V?SuR5re%3EboV`bXr z{bzed*yag5$V!BLo{8s>N%KvBv?RTR1mycjUWx2_>bhDazOJh1I#Lzkh#bv2Z)RSI zG6w<{5|b*wHa#)gqt-h$%?t!ql8%q>f3bC3qe$oDePq3<%SsPzoAY*0{i@_iT8JFD zzw;Y+P3uP53fF$!WrBsyqXpVPg4fI{L87mk%NBa*JvcX`VV%W78v-XUzV?pggq^fY z>H}AbdxA)slW^RsPLYBSr>_Q1v~sLop~TtaYc}*3R=lGgv{p7Rj5A-_Ox`x*2NZ=Bpa0nb-;#j@%>n&2M}vm+_bbf0 z=v3S9<~aBMy+EPc58hQ*)nF3Xywg|y-oTfUwEc2x#SY6ca_x$YC%$O#bRzX*W8XRd zmIF94QO>cJ+h#RLv`=75AgZvyN9VrIym0Jg4|^=>>FGFv4U zCA2Ur!|4MPi8r2oJSEDZ@#5is@)_~-KmWYOBTw|CQxIRG**VU>P za4{uzGg2G#mTHoDvEb1Qw_zo{&})EskpM&`209~6SW_DTISeT$BAv+o(0Q~5Q zIuCK)qdI|@f$RreRlm+CLW*6#zN5$^&lVHDHWf9vW{Y;!f0!N*vBvcH1=p!?P4=2$ zhc3AM#9ib4Lf@KPq)%9fe3kmctK$`+r6zX|_WXw2+Ng1ga5$)}VEtY!2!8Yg@T2LDg3gr|FkmqAtB|G;%X@@6t=j39q}SH7>oFoUqtk(73b@*3tM9GDdbb-rgs9 zX^b3)T~3TiUM|RqSFj)_w)`)9_a5Iwl`jDNH;*LKbbtwMAuSK54@wKA8)$iocKQ(8 zidqD{US&04f$|YnxVXEhWjkp@saMp9RRQb01(mWsJ{FWkcfk!@bSqmC5VZ(+%R?;> zd07;NHutsVM<#I{2x}DQ&usetlq-fotO|K~hQQDzpbs#JW zbUVoaBtn2-2m$6ZbJ=>zy=2XWEROs6$Q-e53DKQb=6HaQya79xC{Sl-6DzT0ktXUC zQ)M!?0ILow%QAUlv(*F_HnT%TSJq-AP_;l^%j2o`IJB|4vh+*Dm!TphJ}Jxt*;FaK z!ph7ihWWk8(CjzQWA`fsX=M({7K0s==js3F03A0Y$7PF34ivA&Zi5G_M`SX&Nag)N z!BC;9ic$`R0eT|+@`cq7)l-R8f-F!y?sDD<1?o<$h+UTDjMNeu+{sIo2wyZGDi|PCYFU+H_(5=I^KrOv!up}n_T5!^SL_hexz~kPK z*Sb=oZiGf!0c!Of^PxjQa(%xq4B+>NCerhwr0>B^#<{S0kHD+Oa}NJ-`a2Yp z_pGW;yxTZ;mU8-YRDJW1&t>&Rml^Gx7GF4Tj5+hh`zHzkoFbjKm{Ba9J$j$s`%uk< zqwDBExzXl1qw1PLMvnj4PelwiK5*>^7ts6AdgJJ?nwA+c_(&CvY*+4Vwg&@z-QsCn zzb18|Z(A>3FrNR~)*gqA>9=fGa33zR+#*^on2q>V@5n<&eB{S-e*{(+S~xjoy%B%Y z!aZ!nf4nEoVZ>V-8;(Qh!@(<7Iz4aLMU5idt zSzl!%tw;D}+TA|x!NxJwZfa~l>C6YaXh+*YY^&s`3tFa)8JyP*FKl2vHt#j1~$t;@9rZ9Z+FI==pW>a{WMFIc@J`yTnq1GT%bYwxe!H5z-| zv1=6esNc!hrY%Gp_IhNIcU~4U0y~blFl!tTdBZW?@=l@zcjBXPEZ$S{xTT>Z>6+}? zh54P7;Qn@!qLNJn$^WF0YG0f%sfXW$(cogPLZ&B-=GTR?5GfK%12kdZK_(dHAOUVj z%o)kNF3`-loUzz!q)tuN-{BxD(6PkX?Y&{P{tySZSxvLu$lc*wp8H|uUBp}wxh$O1 zWTML}=Ogo6-V|b)cYHoN^2>YLTbzZC&GMf2F2a6*oDk?r{h?592{5P4YA+IfGgUnX zsCJlS2<^>mr$p;Kdg%3=zO>4;%N3xzKQW;b3(E(XwqVUYOs+Bxa?B=^eu)B>W4iPu z0%&FnQ*gP>NI}rCUSz_A(58g2j#**jkrrf}o|0q6mR_oeU50&hc-)8-4eK0{>ZA_A zI*{{32t!&Oq2)s;IGhjjV~{Eq9XF_&;ld6q!t$DyOGV#TJ02%dC-%llKP_%O=w0W@ zEkKT_Tb?@!>8M*y)_;Ivpy__A#7THP*H@Xa`8yA;NaLrgWD^kvdwsPPc(Z|=hI4&} z&!#)EyJR*-^DWztt(0}z_VnLtlMl!;O}=x% zH>A}qDYSiuYssjuc=To*Kex`g0D(!ntN6a_k;}>Ip04Ht3+VD}Indpy`rPbV;c+rTbu4`3|Bc0sc9NMbr^@O@v z&IJGYx#&BLSm)#M)7ZsTDP@zQ%NjgmhP5XM`@PX6NM6~3FY zZk%w4`5im({XSTsd!A!%;JatkmD1cj2V5apcj-2vd;WiyOWHle(6UQifeq6IhndH( zkjD(!e7y2AeOI`$RxvA?kzMpkm#+TZVAGk2%sBQvG1?C=*Xi9fo0(}SUKu;uZVkhj zk1{KQgT!}z19aJ5`5zhc4rjRN4+kuVm9 z!$@=+0mC2_(ovKGzd`rcqFV-Bhn`7Ch|Y!yB*!~`BneH;AY)BiSax<%5=24d1i_5c zVVNx^!6J%QG0cJQ-s5*<%wBHt3$J(ek%&=25-n=->WsEpW< zry-w>*f7m`lfXUOdn1yk-ioaumJ{QWOJi#0Pe<~||F|`7Eb)Q3cldh(Jcay%xqr?4 z+fJ>fwjRRHLv9xKf2G_(Jc2y7S*S;DYI;W4*4XA-b)R7Gsjd60%_hGSv3iqIUt9MN z=8Z%LvKpyg;slPG1=U4N$?sCNf>@yf7Lec-yZ_uEzGp+W75Q zInW!;Yh|0VJpwsLQ9j2ODavkS5;2=kDk|{%G*OGhjw#Zjo{pGId@5qHFlG$Xp+(su zJ|5bixa|G_2M}wu-(n+cy^CxS>t{#Rdgt1D*Upae1Q=60yRWBluFYCoWbssEbBU5+ zb*@Fns@OS54T*jq+Z1%Yh+O4L#T}WQOtrmTE3vC8(z!v?+{lrfi5eClw@ODk-P}PW zr@FaD7xgqzum{_diaWd7kU*Tu;Z7dyEXVfe z^l}Y3kVi^3=*hGaCy7?RqFl3PBI}UZa%gYDRuZ%7JYH+QY@M*(c$YOOpHuXJqJvRo_HmeO^>{N71?=5Mp&1c`a6U}L?J?)%tUom!twydGwp# zWr&}WQ{*M4z8Pr?=xc|b?%i{ARt`B8yC^+%wAo8@b7$_0@54Lk4(v~f_OY@~2Y77u zeO6pA)Ba4eJqK!JaFLu%^~b(CCF`^XUUpr}2QsT!x{}AgFS|L?{`T9~TUN>Jy2@~0 zoKP?8c{rZ+oGnpwM{78~Z`GNXBp~O0;qLW4)e2TW?e{}eh2)MV?~~Xp%M~)sI}qNQ zASe+t$q{+#$*3nC^Xcb0+q(Y|M?9VX+c!rJ&{*|+w9XI{(i+aiYP?e(@igbaB0x%}?X`Grxy#V^7n0>mk9qcoOSMkF7wv zx51}pj-Q43w6Q?%m$D6bCz+q$l{CL%bozO1>*2#ju8Om*2Ofa}+D3ZUTkltcN^_j; zIR4`)Xta?&@q^BZk3nM^*?vlt^P54>ETHS9p%`>m1zj)S)qqaA5rVDd8WZTzI*#|8 zZaIUN61j%9d~(c(MwhS`R^u@&=}}wKS>bU2`5=y`)`p?yzD<_%#1C6n8Z8~Ash{3x zv=c6WruSZ>CxOypUyPOvxnAOA%hx}m=?=Jpg_pW#DeFK{Hth0T669j0dvJTVu~Ds# z7=BMZ!JP9M^W)GKb)xfsm|Litp*KkQ>7x8fcDV#MP}$m>*;Uy%ewkyLf9s;JGFiit z#&ia$2D_HY8UR#1NHNG9_PLmPCzc2KLshZNHot8Kn5r-okvs zkj+TBVM=IAJFzUOd%BXToMCK`+~wKnXy~lrOfk&r#I2!q1iL%PouQp)=%E&M;v7RI zv>QKeKzl|_!||U6$Bs4jRM#FF7y;~u%Id>oXzOHpN!X5ejjjKM)!cp~XL{3xBj-^} z_I@R1<$4s8Yv;c6?JY*!faAIDvwub`#__Z@_IP0Dt#tVyZcZTQtv2lZ@+)AQ@!}hg z;W5F<@6@7UKfGtGyQ3*#XZ?E-L{)=1K)D+fKAiQa{m1VJI=+!1cw1kmt@uFZhTFtvsv_Lhgi0+&UDDCBt92aPg z7K^kYha)GonUy9Gr+47YM+6l)g$mee<&58{hKUdJ)o_OQyQY=jge=DD$Qoi?@yo6J zX8qf^;>A1o&F(fAVe7w*o4a^N=?lmiu67=p;VSn#!0&B`rn&f)QA``wM!gRifjo>9 z42MiOd|2V%#%@&rdCN!0@xsuaPj0ni%__dJnqhNPmg|A=pb+ch?K<{-OBIG1LUCo|6>;szPouS+&)FjrfTZ()mb=|t9&CDaZ zinO^4vBR;|ucyX_P^o@BCDyi$8oh0fvih}@_~>mZ%9_`b;={bMvSw{kyhN1ZrAFCa z?l%t`Q{I%vOHOOdKN^YGeB{jJWoI~Yk`>wOBaM19R;7x_JfeV=LR)|h&qadDQ-S9s zO<{r|5b2uZezIy8X)d$pEwpDxT9))j-WO?E-2a1x_F0hva!fm`wzRj><*?71%2igb zBJMGC`&I0-CQ@hSQrF~BU&2-sr);ZM6e_?=c~F4!xwt<-s=(<-;m!bKv09+VVWH+g zz6eE{0yB_FTBJC`^P(D{JIL}G%4%ev@)>r&)k%CP9!!Z?k`JIMUs;t{V3RswksV@X=%=KQj<+Od!ona1$6MM z&zt)!NL#?#Lc&gF8f{na9p>hwIcfXW?5ENP$7j*F**EB7S{%*!u=QY{;~A1d`djH@ zU+?Gzw5>}w_4TGLph?7%&z^p~1PaODEgrplqj@Xm#qrD)-@H809Zl+z=Y2^n+uXDg z{>J;sM?_sE&zbdHbfT=&&$a7h|9P^TUh}Biec7^`p3aq950uqQv<*ogP?saSSCQmv zcWr=cWY(vtYPDlu-T$$7C*Vy~`vSoKvm}}B(*#POrA*sU3IYZww1p}u6s#K*FYi&@ z2+F;nfFPn45IUiyEaI~)B3$(mlq=QiRjwN#SDltBTtz@x#K&R;lmbdaD^Qj;?`)Gc zp&ROb-+kZbr0wryI+@Ip%$zy%Kj*MIfRk2Mzq%v*QL@Z`d?Bps4p>7vtE#E*enn#C zJuz2Lo1`Ka$X2xRTkdu~Rxg(t`~KOrD$6i;xmdjf z778le&TluG(|6qa;0?r6v9an8;tnp z*%$N+y-t^_7r}Je7vae(k+on~NLknYZwyR8X_Cv2ue}-q9)T=pxhL@qI@FVV^q^x$ zSAe3C^cQE0(?ILpTm9wedb$>(&`mj%?cpUN$7LrrO}pd2uGI zh6s`MM~d{Qgq2GozXq59^fQ3l)yVuiPG^5z(?PFUH?=ScUBMNR_ZsuTh5y#?)OY>4 z=4t(I{lm|Ob<^u<_B~UL)`|8fE1EQp86T|Nnni({byqT15u=#T zn%|~cm>oV~4h%Fc(1k%R(CtS3WJ9n$0<73TFPtmf%u0oLqE(?uJ7y6yR{8NB}Oz)vsn9+X!vuUH7k-NV|Wu{f=#I!P32Pm0>j9S#Ry_-{Q(G;e$ zCq1V)-_Yd(Ee+D$jB1ct+pN%Nfn5>G72=`T@ypB~6V*qrn;%_w(xBhpsHso9s-GjO z>N?FvY1)o=_pi_nrfqc3OFH_2e!eJ>&VHnqU6B}VP)R=Fx&MMZy{zlUtFg0CnuN~T z&U?^#iiXh*Jbq>cuqw6py=lZN#_n02dJ$Ne*2jn2j&miSp84$ro2q7UtWMqgG8Wzs; ze7F$Fhebt1ME%-8+Gg%RIjA`eicFFT&heC(0<2v_oOJmcVr@P360^>CiCNc-KLt9t zig=#+-r%#kLfbt3+d7Du5$FQlK0zh~x{&)U$lHSD+a_%YdOk;QWVE#&L$ib0HYJtr z|HY~`SVNP#gDeenO{qkEgSxC|vvN(jq8XPn-)8o`S!L1_V&51y*(8aUV*w@yX=|es zuJI%>dsH)KHRr@2Zy`Dy!(+(rbJq=udQ>eLqqsff(rpPVY=s3}` zciHJR|6Lnfb~!c0ubZro66Ct&rN2xT%i>~v3k6%K3vIKl-$xdD1V;9KZr>Nhyu_sm5(ish5Ge{Y%^ z#R?1xthP*F9-U9x58p3eT@yhv!aIJ5{b}_!TJf*kW1Q>-4|(5=?=PFDgGLG-1|Gj) zQ9tcT=D+Q`u*qXKN5a1LW;72mp0v@;yV#BlKfd8ii{4Z1rmH4nwvFW4i zZ$J3sN4P+(t(eZtV9x!O{t^B?{GNI8SNa39|6srYhjW2f27{eMY~2R8 z!<{e^M#EhwJqo37gIm$x+fjN1M>-t(;W$Aw3Z!2i z5swi$9M@&yMUgWa(O8t?u^fGHCY&^oUVjWGj&#F=Mj3FxmtZn+__+~}HSwIliRh0g z2_d*Hqyfzchkr?Wn~80R<>v5Lk!r*WjkPnqjV)pB>A*}Ayr5z&Ufyp9tcN(bK|y^U z_IzydnAER{-LPA+2f&L=Q}=;qOFv!rO@O@APeCfqQ%DE0vX638&ORjtnTg$DC-%fn z`8l!Y4#hys!JbI$>Cp8c*C+OJcuck_>)*z%pS%9;2xJjaL)w-T3v7Rm0xhbdz;=i@ zPWhJD0b8LPrgeZLCaeXH2v{>Qgeg&%V!z-aT+(E?v#}14hB334j$mo@mek5G1go$o z3M(LE77@jk)O0y8tSeGPYgFcwWg1={KLq1)0@vzGDavW3w!L z_Fc&F78r&MVTL(nr3ocs9`%+y@GCe$nMk!y!%m0PY58J^X*y&U}( zRwH*c=yD);x?RMj#Bk;vRGx_r%uCl1C1e?O0dl8x>36ydnI_EvKU$ZTnH&zNw7yst zNwj7~I-~~kWMm4lH_;xTm$~s;9mGeG=)!&DWA>aLNc)3!D>E)dNtdwc%0E(Mto`qCQMjsu$h1-u|Ai5-RlK5-cuWLex#Z96a3@V z3zyE<(A@78-B-fjqF7wix%%UCd?CA> zIDP8sx%|2?I{$e};=pG+(#+)C0SRflYo8@I%@^HWIU)%}a;P)c84SBS(sl9q&ieFx z{LIN!Z-%q_1y_7u%|mIDWnVb@$eo!F0$Z=2#jC#IfD`q4-OeWL5WUr;NQy69`qqJuA8mwPt~36fk%=K0!(%6PAnE{}5q zBzh-`k#t{lt+#XYal5uKYh+qK`9V4j?@NM>(`eCLcAPx@lb+t^HJ#hY!b7Id5^r!P)A7^hR{d2|JCb#I;{IbB9U{HAz4P>m zDs2(n0}KBU@rB0fkPbTTwP;IeOD<2P_e|4@=rzHjd-sggMD_;0{i;?;7bw0qVlg~R z=cAgv<@&|hG8exeqFG-=kDvJijAxyW`u3?{kf%U%L!*l(yb%1g@_unBZ6dP=G9?%I zfjm}48pBg^-Tci)tOpq>5lxX&y6zso0`Z_{D6!TvG?SX;*FcTq!lli%mDJ7DjhidW zWKNPwN+*@!SY9kg%-67LX}*dsZe>?#I{suMGm+8Ju65MHgv>=qOJTP->g#lBUaXR z`sIaoj#_X!fNQW4M_L4^;I41{dZ;uc!7nszi$m+z_X;>%)GXZv9JnL}ZpDTmpJ}X( zxH!b-2r%p#wTF-)f=!#Xlmp3P)G{KG9b&ZfP?TwliTTtXV0^LPyFro$P;-!py1BY5 zk)5!ij%23op5kQUA#5jyZSQ;=l^1j0@8nSS@y$vD0tv zJkwofFPc8D^Aql}^Z-5BhdU4Olw}Y#t&x*DClhn1cBYbJwP{*{s7SI+LmOC;aC`Pd zr5WKm>uo7U&fVP>Co3_WI{|BM%5bbF$rf%_WMpy#Q6MH@EnrP>2u6bi@~AvDmdYW= zJA@cy{zKR>R3?qco$N*shUfsxhXWhIC;)pt+#k%0Sx(*_j!!vP?tY z9hC^k7qJF4WVI{UJq?<$xx~^&Dkk-{(u6#;AF)Rn^7J)(-;S`cre@LIOE|tu1YTA37Vc^GG7V4_V|~Hg;3>S~$Ux1Iw*n z?q98Eyj3nt(+fWjpFjUIggeMwH+^L|>7S<4k!)B>pFOzFWCM}r4c7d*>TWbok}k|h zyj5>2;GTCnxgo_&mNRdQuL~@qm7k5ii!P98$+N+C#s#&}WSLi$c=K?7VK{xRzIG1C zoyd5#UCmHn`M2kusU8C|YZKrV{;)oN!5#f~LN2W;V(?vYflT`*y!+j1H^?+jx@2zn zK0Qo&@X_|qp_L{x;(T4vn{*+CeslXqrs?tAVfDE6$Sw6aJ?ay099nX+&~sCh({N-o z9>)LW{3`%7hVj)+H6An#**=sB=n^#$t>iy(`t^@4;=CAH_a5iWIIb^}ZUh^;$g6i`!XM$$oi{@1m#MGT>|< zZf9#UOo2yXDm;!JGf?U=m;{fYagV{1=-Es(_6a0@J_G%I2&TcqC_NLsVg~v<9R$HZ zik1w55%&^}%cVq7FyJ1gjXdsT8jUydA}*HV1kwzb(MUU{7HDtOq;)Nk$8*6&U2R?d zR)J=f9&hojR3pb!PF(MekkiLCSmccWd7S4@MP37T z0`Wd4h#urrUFBNcShOYGXiN5_LSrFNvOAQk#H`eWGvl z=9hB1BlSk=u+B~K;otSS;&mHkNWae8la_>jxS!1!O*n5XHn4>EpvmsRq zw4Eeba^tXI$!(X7yFRnz%0z*P_Kc%hffhQ`<96eF*CR5aB=(WRcSI5oV$~K5C-y!V z9)XQKC`Q}}s)Y*C{30S%L*y(XxESvLs{yv&vXel4t?7%BYnjq7VHw4i9wua7|7`C#Fw`cF-nz zAn_F{zYgmJ-i=jSa3g5w`wng|sN{R^1(?->9%P2%5Ixmcr&w7nLq>{I+=1NEW6J0q z<#t#dHf40qXVg2W`IIZ8Sc}uIzW<#^AMgI_`6E7G6`e*n;BSLff@rqqgep!;9Lz7hA7PBEG4m z*6v4JyG3qqtKIdn_GMeQjR>r*+S-@e)~%>$eT&bk2y@SCA_*YW-Th-fpB`$zCt)&4 z<_t4u&Ybf*z36A=J9yRe2^VpG`0f)gtE!RIBgSvtU#6;I+i`x~pL_nOe%yEp=eO>T zIUZ)A>r}WD-?p0jz=f@0tS_5U{ZW|z6RmJs8d9Vm_t0^dpr*j%LwP(`6TG?YfNLI) zD*k}yaExxa@&Md$og&9zFlt4qV=7~dVX;4q_ zNL>w`uX+5|I=POG3jy_}?>?1Iy})l_c~wm)lB4>NUtMavRbM01J38`Sf*Qp^U;R;>?{Vo|2sk^E2CL9UYcZ7eA$eXssX!g)!uf=2J%T`{wU4t6 z=Wl=PHzSo_Nd5UTYkkg#ovJhw?MH$9;cJ&S|iZ&{n1Y@;ArnSR6L2ZCFpc| zo^;9*1j&Hoz)O0L6G%*WNeJfkf~UmRy68@HGknrLiOCD1a1nHpq6@HoIaHbx=IgfnA2&K07-cyLNV# z@bXpUe`N{L@0PgMcHxkFX5BV{i}}l*)L4;fD(=d~Y}uPC5=S6=adBHlWQxTDxrv&k z+5Vcd(N*_AE|)lf%Q0ui6M=|MRzf@|Otkad7T-DOfKO&b2hr>knxFUDoqR8pTTmfp zwID}y180&ss+}7OZU@q`mw7JBJxDOwqlo!i`kk8`;4JC|Y@TLmzcbjOr9GaQwO~pZ zQEyu@wA9c)b%Iv?2;MCp~$3FW+XIqWq_WnMX(HuO7*sDogTohc6vl)z?$4<)w#Biflm#wgwyOGq%PPPjtM94AOim*6~V=WBqLh zVE-KSB(XRsg}5jv$zMq73sF`;c7Z4-Qf{v@OmsoDTqZ-l3;yO)ks+rBh9G$=V6y|v zk`)EXBR%}1HJ+?8<`!(3=8Md?neSuu%ubrJ@;+AzMDP=c5l!6(70jK?Y~;JhtO$VL zfRi{7{XJ*J0hww9o5D0<|BCOy(SF7u3r?k@1H`;_**@H)k4aH%hA? zXr~Pw4}KgMXH4M9Rm=H?`kNQLCx?*b!JesJTD} z$@N2o8T2z0Nsw7z`zRSFIdN0aI=y&uGR`-sXNy#R2Wh_<^I=S9o!EsOp2oe`IX;bD zO+5S#FHd9fmN>N!?leQLo<@HX87C_Af~qJ=$|&)yA$8Ro>No#mQfQp__rB6k?*e(` zpl7>wV)-G{3#8uq`>Dq^o0ibHSz|s7{o@jkg~Y>ncF>7;ca^Lm_u+OPxpBrW(tBxh zW`42J&IYN@bsl=#$&RcKzZ)NKA4Fq}P1;~7FL3DCJ>Bn>I)T1+Rmr6>c8(6^Svc%u zKFX72k}jVNv9n&ZI<*09G?8qp-sdlbdD;8kQh%85V25ybmt(nJ6Mf&R+RJCX?D>&Z zQ85mMUeTU!=zG&^pfPlYeGyHAwxcw){KV^8{+4=fKJ=1F``N1HAqTXW!4tMv*Fh@1 z7ihb7Bv`w*Rj*!egp6=f0I6qgn1SO-e*D%r8Kw@h({k_A0NL~%lyH4EgwuVX+m!|r zp?d@d!tN&pA4j;!zIeHJi3L*_$HZQ&Yw_vc4_2=)2iUtFX`~N^iOe{pw zouD}9vteK;Aj_{>1_yw}Gjmpl`r?ggsnx#dgZ#A&{s+wokamd!i;2p$W=YFtwP7xE z2y;4f+D7V$4FUGhq=kK+d0I1pYoDq9e#Xqxv``I9&}?>tR1^ID7bm$5S+kXI9Aq;U zfB*NF>ZQKOe4!%1QB;fOL#@gCX%4g_Ylvyh4pcF=Wphle7{X-TCv%LPpZPu7XI?us zXv%F#Kack3pO?wj^GW-3Ze~8ON!K%~EuZt(%HsE1y#YF?9ow*bD|T&DzGd0n&HoE< zT^lNQE!@$-Bye2a%08wd^vk{E#=hsixrmNaV%&drdFj zVH5tEeof61o}^#`@NzENg|Z;sk z*uy-uOdbpeNfL2W7LP|4invb|FYuy>J6Y)jN#sSI%xfqa^t>RFZd;O`^wE+Gf~XTY z0mqOR4Wthj8I~yM(c(rOua~4>It2($j%JEXscm`OqJl2OJlHraIx0`{XFYTCnz*oC%d5~GV`>NE1ng|_*L(T~e3tFSfli^yc;*T{^{Ww+g7Ys|Q} z?DgF~d!Em@S9$%+mpxA)-#}K!V82VMj_IvzK64|fGJ2Y_`84w7X|Vb68!449pFmzu zslxWW{vK`#JvI0^+S{9tM&>_y>pVubU2D~TN}}ii%>KfIF>Ib-qg zj>fE|d>(f4QhwJN&XQYX95P@@eLpX?ZAj6Q(mQD8)kl?5Y0|g03gF#7hdgW=z zvI1lf(Z(!q&FREl<^LH3#bvX0mG|M1sYrDBTb4jv6sXd~Oy)o^>y*TUZ^R+piIIz< zkeuMNm?<_>MlOgHBV{MjESk%lJm;}vg#fugCE~sW$h&h_3`UroW@#)2-!4E8BLydz4?9lfCAc{^w9PTo%6jS zIi`;NpljznCVKwFV>7q2x^2X*oQmPG|Ma80EDDGPmRXpPi0Yk_B=Hd)qgArYjM2rPhW63l)0}XBc!E;pY+Uo6oE$u6u^o9+pyfX~i#Y4>2e$$}yz?7bY=NiZu;P6Sb1Y z6K1|Tfckf4Lx49lpUxr94X`lK0!=5eV79-m*#)GX*7bEEb!TBPbuLlXT+ol1!Ax#h zx6dGIBGKli9gA*j^OJ|WRc1oF{3j%1Q_VmJxLN|0yD+CQPlU80?cZTP+CI~Kl4FRN zHif9uwAz@7EgPLkHia(6C;2kES7^t!!OH{OP20E!X?{Vi*c)i1pQo#+CzL%)%O*_bTePJ`zy-~Bu-{%%Gi-`-DQl+IO zns7&>{1u~ONrQ}Ni8cCZ4m7eA`_ui}shQR;9S-UspEd&%?oL`B>~=xBwXt(y5;L7| zMVo_3%R8Nwdyyq>Ak^vUxk=Z<3ugL(Hf%pW8ERB=X6taPyH2Y{$KE(<1ecC{SDo60 z1F!o{vK~|LUqR_W+MgzF>Yf0Ko3vOK=UVU6=J1WGzlmN)x+ufA_igc7TbB}g2z{N^ z`8fYm{rN(G>!eHv9I5M|&3!WcrO-D3mHX=IV$?0lf4JsGZQVUUF}6{M$#%fDQJ`IdGv9uwE@i;R!hG z8wpv+sXyR#lfKK3tv!o->yhs+sHbVq7QlVV58=5SYv9-PZ;|8m7Q-7y`r4&x7daF|^E3$c6_%uh*M+p400MCIP9F zbP~r4oY8D?oE=vI`OvYnmn}-i9@Q)Yoe8EwwjnJqNW3BvG&%~A^8ZTcLFn?*Tq?9F7oCf zbu+7dI;`E|bdNKKReQmS9P~Mrrw%6ejvegz+yNtd=T|bTJj=2)xr-@Sj=R_^ze;f< z2j*3|vHkKEBHdS0fof6k)9!|*S~&Mc zUzR6XQmxGX3xMjO-s^!K$ONRfJc*O3(98imc+ttiXDk&*Pj)a#gn(utCz*lqvD&p4 zn3+yy0n$s1Y)J>xOBA7|5F!iqN#2Wv#gTP&Ro;tp7ezB;kh?UmKD$^mzV4Fd->_k2 zN2`}!eS(=xeC}#6(pDXUTwIoTBIHU_g`*+wAUVMnvOUn}v1x%y0e0Q~yk4`IsWdTR z`wC(z(~gz&R(lGwXNiPO>sey*N;>Sk8c7%JXIN-}rbuf`hBkEx6AEj1Fqma1bkSCV zwk(kO7DJyGy2|AebpE2^$2Pgdj1{m-6O*v>TwGF#1(c_dE0B*RU_FXn;L;a2a}hOy zx*$M-8p(`pri2A7=!1z4WCtOn+9|}qH-f3UfJbuJXlxGN?<%304ypkwwxw4#IA$St zxbhsc6rZE9&ng|T&J5&Em&2T_h@%CU!yc>@PZ0i}y?cR+s>&Y#e(qyt?%)U)8E`bp z3nEXoL9}2syyyg!mYBF7+jZLk2~ABYYcn6rcf_spF;mpk`)?z!juPF|}4#KgARsoBUe zT;6fbBHj&i-cnd zu<9X&qj@El`@5L|bjSKjmTG+=>%{%|v;JovNIFAeP87t{r*2Y620XuK&))?Ic``~j zs?ja+2ZQ^f^tqP4*Em4>)YGYP%uYQi|6tWv;0H*jS1&w%;loIo#M@W&K`DCHiEqjZ z;_A~`foxGabyuQ%)~X0huWX|Gop-~S)3A4q!E12rGJj*(;Q z)9+h;bkTs=vjz+6;q-WUKKknTNmm-l+&-V%uvR=xuGNk%hqt;;k>y#pi_3v&Jk6}6 z-uG$gLhGKib@k+bjjGm%y6W%3X;nSsaGg3j#gne@fzt)OxKvj?iB07&OM_ge0&sfJ zv138jN#vO{irFv8q)uBw6xb;%WuK$;(?t!doCX1xT|M){r8UkK-S9dY{;yNroy7uP zp4ry(iB6vMF|zO#-2ts`*8IGN$AE$K!E~@GjYZ6edh7wgYp9yM}}5k@(Z4V_WtBE7?!-qk=a9 zF_BCk*s~glwYcS4earC~@X|&0nZT|?fGFLtB&(x5P@txCW8*dLd0s=YtC*pS;oJBbbpvtChDx2ck8hBO_t|gD7dvnoH9;bAc|3x)_M}w}G{ZfD z+fv_wye#-ijx#xwde5(94{}cKNTI8*WB~;lVV-WkJ5>RPWO#DN*Qw7A*G>cy39@E? z=Sr27bx{C>kQhtRJ(K98Ch*qV+*mF4(&U#~VzgVU*?kUegyV6ZfrEJ%ZJLQM zyQ8%-r%7|0qP45afs4H^YH^sR&VtuRTDCM}n3Mo$oX+QS1J-KeSvA_Tsove(>6n&w zh=;an>HM%@)G;p3=j2VlfMSx`@%V86&7O2`7rKR)QMw@F=Lfa)Wi_rD(8i6k?>(Cc zXdSOv_aEM%r6C?@=4P}C#h5MW{%R?xEotM9~iVmUwbhxOy(A3d&|g<`$yc$V#?^J5K0 z-b5N1cIwp0&kxnm^7DiDd#s+l-PVNHA6iQ~1WlIerzyA9A1WKEWhFv@6Ki_K30QB} zLY-v`O>1iaTV1xW^V)9!_fH>xEFi8bSZL5(jhwU4u>4!VteW!{@r^eP%imC#)r;mr z3z@k6#6J7~iG5)Iu9rM6Dg?w59{C}30QPP3fGe6#Z15H5qWG?nuX`KVwJ&l*U`XHB z1HHYk@9W~_ZPXNK>{9V#qv`hE)zSnN^>l9`HZ1evn;N8$7XEzm~WAm9D8;z6a*c6wx%jyM3xuj zn>#e&n5(=n*$m=qp}z~kD*d1?tPt<2U8nTZLo1P{_y&d83|(O`#UCO*bEtTo6Pk6z zTMoH#7k18|Ln}D{Cy`Zk{y9hH^d4JP7m)LWm&>7lfEFAx)%7Pj)1wtVrzP#0%dKF!N@UM4`TtyV!z5_X?}E!iPRtg$Mv#EC2t zeYE^vdx0hp3>H5kJ)h{YGSyDaA+kgT$_sJGbh9ZADC~2)%%&Km^ZL%JG4o+S(Gv^( zp~dmgX4hC`K(lKMbVWNqp)RFXV2^i3J|ksgGoqpE(iLQ>6*-O=(_Tfw8i`p96v$9~ zoW^9y#1y0qb+&b64RJJaU~mni2ic$pQW^)k`f4VIcywuUhRSip#Az++VaI0@xu;i* z`%@g_a&X7$qqfE0&H0g7mh&c^9?1bR&FD`rEi(W)2c?_UF8KlA8jjQ8@c(uz7c?=E ze74iwX)NgysO--Tdl-5-xuTwL31DkS;umT!(Cq^f$5Y{>oG*;a#`UXO)Ce^)g@m7R zbUwP(1j=!nK8Ih=adeI+-tQciSi6(tgC9)zQdqheR}OgO%f>ea1Ib&RYdL$( zx`P}DfB5L6`GR;dS9}&&kG=KZD-w)dO zoj*jK)5g2iXjMx;@?}hSC(R^(*AO_(NkW@~#2-QyIB8o&Uj4p6n|}9?-%r)j8^8H# zf;RuhwqIH5S+=i)ZVIg=bkY4|vl7DzWIgv%6~N%iLP}uG5M`+mw~-uhy6IJges=Vy z*OqDNX0>}hh+$|wr^5<3y8kR$KgT5S5V`xAH8AWxP~5E=r7Krm_!GSO!Czohb?{Qa zGx&Qos-0(p-lVR$$$b&t_LDD}>AbQGB>o+5$BcgncL7U0sqlefq>3k=Ldk3DDYsUj z)TDOH*V3hr?|u{j5)fs~rl0OXClZvtq&75bEr~YoH=YJ`8x7k77T@aQoDSO?`WSed z`u1kq>o)x>^_`no)q$&jW#{?m+n<@Qh16=QZ#@h7zvP_`zSq{9`DzEg_6uEbi!P*g zSZ?8C#7*qofs=3IgxmB^8kOA6aI5RDBeghbciQaL_u=xb8slT1U+C?gf3*HeZ9dBX zC7sklA8&X2T~!ayhHDk?_9i##DTQo7f42!;8}az}x8H?&O2MnX+qH{=mUgQl4nWIt z9OBnowRE$3)(w6upo%$OX`e)G5?_kMsWcH{#Mrbn_NJPs z0+xp|NHcWZj+21L9*0&l<;6ZKE2u0~fdVWJIfb^4Cin%hu5M)z$jMk1P#rD-TgtbS zCze7bsnk}g-(iug$lcu{`j_Usi+ykMM&t%!|5m5m&_(Y}ga(=yg~e{v&u5V9^a5jk zDa@}@F9359!+PY25@j6;cx)A0#GCa6s=37cF`=58A&1bQ&Q5gl_}}Je>IIs zs2oZ>`Q0&jV=(@kFhwF^w%n+3y>_70TZEJ!ELL8kbaB~>6xp`TNCq%-!4EMT#v z>ojYru2%U_+b&&Ac@}TV*`+HlxAT0CLM$>hUzH8t8zx^msf_YZa|M-|T+hZ3r4i>bK<02#G6ZN!_GjUrF6; zG+u9u8m<->2Rc#OtsZsk=1Kaw@%10fr^yP#oK~U7!JYd|o=@&F9fqJ}xtN@06=t6-&nKPe zIS=ohC@W<8GW(ekfG!(QFQO+1I7S$wUVs^366~aMwfZMO*N-D$|5jis>rB4;5e1Z% z@?@O{JAg=@hCi_e9xb$v5To|+1mD^E-M**r$pH@Q_cZ2enfE63iW_F&@vGEtzh9)~ zlwTTc`4<2=ELpc*;jM;%zrE7QxJ|qB$$9J4N&rgnC$=3mP145C9I7AS$s(w@s~cQn zp>*t}5!&-#Mm>%`hsPH^5b%YTW>wr2l(bJ#yA)_?hyEyv0*=4U)LExdQ3qb0sgB@S zE&a?3C($!v`pxcqK#egb0#-@~$?!}+9E<>?KqmZ~ik~6cpbvvb;keOY2!8z_H5F!i zGQeXvB7_Y*1W=xf;nAZ(jy^v`Dg4lo7Z#_60@KmrfnI7+?2LuR+er!a`Kb9;ggX$oo$n2(zfJy z8=aPrW9!TljmU5tG26x)BZfz(4MEzVGJi0Fk4}X)M)DFi3P?8S1!ySL1+@&30TCbp zwx^de6|QJ>kBh9ND!#JhnDP~{9hXMj$)N2G9GnZUTu&oZfR-_B3`3eU6^~i-s7q3K zB>C#H9;RNM=nT95uv$Q5SrSBD(X{21C@hXOH#xj5UNKez`G-B2_yCc zgG31_LW{$Q^TR|dvQ&chw?Hk{3}Rl!N6=V{eauRvV4qQGiKtj*^zo6}8MPG=6`P-~ zb<|emY}`Dx*5UMMvu>X1q$=2rQID>?uL z;izExIp2Tt%$$%QD1uJG)Qm`Vi+*=-MrmnZ782K7dvtAt6NtXd!Ud9o#S5x73 zR$T93ogU%#Uccwe$? z*DJx1+XoNK#XVV!{&erMgltlc&|%*HiFzeFnWWDT>Q3i5Vpq_TDGFI0x9aamc9Qz< zqqZGfwtHCtt{?Z%-t(3n-~g^~o_sXg{1YFDmvhs;uO~FqVtplaudUh6*8YbJgE}!rkLKLFPF($6Z51!NJc)HLtS+ToLivJ`wg^>%Z0>W_Xx(?{^>HcebDW z)(o3Hd(VEYy&nGsE7!uv;xY@qbawX5AeSCoW?;kN!pce~Rtq?M4}In;TZVlOHttXO z*;Q!c@ofF`UHqo>Qv9!pE>|RO<4gBMCb|>>=P$I2`&|6H)v28XyTYm&hi|zr0{mFt z2upqFEC?*aFd0AmS~nH^&SGxIuc4C;0__Sre&S9-w-^gs|DR@n-{ZI(kyrS*wYDxj zF?@rW9fM71gom`}Zp0(p=S|qEGU9n(SmCX_f~<81&1rsUn`!gq&paJBU*1lAcAdO~ z8H=7>w{{)TdiJfg?|OT}Q$h2~ji*kcAMbmL==3m$n~H8icYe7Tb!qP7_Fvo|Ofd!HtGB+^flYk61$XFtAJL?BdK>&irm3m$C|U#=)C3~^ZsZ~yB9uB1J7%x7 zo2hmWt*uG-^Lt|#pbMTu(-%Bfgcd$m6ih9<%shCxXps(Giwejir9mnpMnQ7nr3NfVlz2 zQ_B+oJD3nBNX%SMXA|kg-jE>WwrygNhXDyv8r7U&_BP3!MqA;S!?*$Anx!K|w18@A zRAD~e)K`b0!(PquGS5qJJBd3Pl?{_$rRTpaO=ZGpO}t`yDr@3-8r@W>WpynY&rN^= z)N1Ft6daV4`X0qK$VEfw%jb2ud--O_4*mr8m)QEe)n2hbv3;P`#00C^UhR;uY z^(++n;C<>uUF|h67rAKKVgBheFfGUSP8r|o+JTLgbq)CPbSM<*S)L){?qpah;OIeh z>X8{>iNfXU)i5VX;}z;$eM3H2EEvea5qNiRtuwMC%+?DmtXs2=#**Og2R4}WaGqV< zX#YRpc`7C7cqvq}`~Ir+Ay0sPKaN;kap~KsxnW7s2qOxiF&pQs0+txVjyfynFiCm&G@H+DTuC_Jgq{P0AaTf#pffqmxEjhBB zJeT4&{>2e_7x1|8&M2WDIjV4_+um$HM;q5U;%a~|z#!bNH{QJdm==>F=WQ#=i@9)~ zGxgt3CtHVQgsVQdK!=vX{L;L!rw?dpTip*d7Cr{g2qAe+;J1Xu^X~r+czKV1Ll~_i z#(ng!iA@iZ|06+^2V)sk77T}n$cDDvz5*Jexi{ZdO>>y=TY0 z9XBgE?C!I<#C#k2a=y)cHn%e|kvS!v+G{TH<^;FN)cOfAMA_V%dQslrV}iVWZgn;> zal5HHhnTe8RGG84$El?4w&EODn^Q@zQ?37?rn;KxQqM(GLfRan45~^6h zL$GoMh4nsm3yrerj-%Dn3yGvDfzXOH_>xHV<-X!!xFoGvfrhMEp)|9gWd*dvDXa>Y z+OGMOXw!rxtGB((oc^*H6iDx$H1xRq-of`=xzCK|Dc1#&QX2+&#? zrcIeK=Mht0p-o9)Ldu-J%-L?C(Zogz`a*tT5~Psq!-&EJNG^^I7}bh` zo)$YE7w>HQj~sQuGK>T1r~a&4W|WW9^q}%%?RQM*!tz|9r+bCQM&lTY?|x#+S=K8W z-~ZER2bXu7ItKF{4mebzUV8E)ntt??kQF7qfUzh?t<$ek=fi#YVXCT>fD7Bj`>NqH zm+`n*?`(_6(c+Z0tMi{jJ_x&Kee}igpN-X8Ow`k^3n8q$r^7X~kCR{FB-K~2`Up6` zxgk#aQD*t0C*JQ8sk5@?j8Rv*_$64_fFAFDVyjXkB&;BFc8%TBhsV4xt-SZNgE#4* zWkO;+yM|tD2&`LQ*?@n$>C3j`v{kx|DTX0WE z<^g^lUslaG2eINLcxd0X*C+9Ha9FS$*vnC*#j5 z`~tD$weA&QRPcSwYa3Zyh8KIa*{t=APW(CiHLZcSsEP_WqOowvp{wnq#UNez&UYh0 zmyO3jP<@OZ0z+~AhwM5UuKn!|)vtl%LVso7gB%SDET6M|+Q|jxr4O=o_|Xabmt(Qz zz<(NFhrdSS%K0}`Nnm1a{B3m|=fE{qQRnOuUk-d6q4#!HfiJy%?R`l^~{v(%;f7G zm?zOy+qp|mdl}`nhFQV9zll>0)cAXvf1p~^hl~3v-=(>V8^vWYKZfyg>t^z@TP;}C z|In~Io)hkAkw1&wscH6BOlzjDB{QZlGpDews{N+0XSRORyw%TWVu}Uz|6>z-yTz~4 z=bjL6{k@&*-^R-#{~pY_J-}1Nd07+pS8*%KZm**8t*KmTVmT8uOWAVVy11Zu%PCfO zkj*FDrdDqwt&6=Bto;18hDf)iMH9TWwI*vzBbeM`Y$o7}O~erH>UDyXc(?Q}**?}kbPrrXwaHiFB5=fPteD~dtU zVQkV#(*xH5do+UKnn3>}R1E!m?CK)2IHfmn`MFqbgzG$Kn4S(Y>7Q-O9XMD5B1mwK#WrTSZ-!ZK*_atd&AbMskJFGr?XaooP?3 z*3@y0NjGUmz1nzBIJMOHOvfIJiXQV}FLm?TLULO;kHc`f4?qCEKXG2rT7ZuDFtYliv*ddXzzpN4b-$4O zUt5KyP3l=%^NnfOkqf7Qg*hXOrb9Hd=R!%1rM1Y{XnO5-DM#y(I)7r_*IK$xjcL%b zeBDoeN4tFEHTvNB?fwLo5&r+~^f0h^@x4gCDuv{-Xx(87`8gOe zVE|+S9St#+m__VO-hYU^>P_-ueaP!9^4BRiJbMbz_UnGM;*hn5#}thQZ>H6VG=My9 z2`>o(t8&D4^0eu@Nt6T$+t8auL6CGt1DRism61lBXcqm+qV8;ilsnYLFuCY$LbSAM zWpib2l%1Jt?`$zuaVIkeCU}_M8PXGA!MOA%H3ec3wJZVVF;nM_D;vx0hfXU@6>7Wn z+lK~c?t7lNy4{|Aj>6P;*BFnNMl4P}xyEq3G?e%zbqV*i)RU2hEkrwUGc#awTIl`2 zRZb!Ab77}dfZZ1l1q zXht%fkrpFN?BU_UOqdwc=mz3bZeiA|2Qnd!dOj0;WSF(^eBUPSLJyp;Mk~%&OFmIB zr{a8Nqaw_%IA1LJ_-abC_Y#Fh3$o%rH0XWH3bHI88j16m<@2&^nhUuW>WQof%U|@S zh7HJ$-4?e%FQ5i z0Ubz;Eex5R)#y{Pg%Wi-lo>P&+=|W2<4%II+05Oul|1S{XDX8mgh}uKYJmZ6p-~?+ zp{b?B$54RwPDm*Cc0(CzZSGuvUV?RF*?h1h3)Y#``@vd}{(7VFE%}<%)In50@`$v_s#nDWOx8+zjp};qGRXvCC=tZ@?Qt}~dzrW5EoZBZe z1J}XfcQvKYm<+5iJ6j)n<5?c;>!HsrVV(Q2&)roObvlZb#=;G?Q$t&RPF!mE`UNwO z)0+Qa<;MMr4_-HCbh@7Wo=(AbaF2b|Mc)606YElHZ=Anc!~?G6_y2NZJRe7L=g}*t z<7-&Etv?*Ew8l?l>riOF&_CY9>PA8RR*4_O=6C2VCGjo^>m0kCI&N|CK9dgpr9Lix zJ6F|%4ws)1pMkEZr(bl{np974wuNMiGUQ2t9TL|E~&l4=c$fDb0%jJkU_@IHEBH#(cNw3(J+287~wJ|nhf z8>>;K{avr$3w*n7sGS>tj`~ZcMRSr4X-y>Z2VUt0MNX`XT)pwgD44{?f>X@Cslbmb z1p@3^jQGCaUv3NW|H zxwKU=&`r#Ch+6)o;t=Y2w`pGfGTO&6X*@N9+L`)A*i+zslj@VI$Xj?k7adIe1l*nY zv6u6FeEl{C`WjW5&G?jyr ziN7b2>RnE;?+6-2-dk;(=BqAKoJUV=`SW1dPh`H07FD^Ga2zd2cN@hv6%q7ON2NUV z72e#o>E0IK#--_I)BZnfAESmEOpo7f zrGb26`?YPT^WO{A>w?Tlc4T}Wt`~t#4Wuh9e5sc&I{%c~Fg;=EzV%8o9qlJ$r|pt+ zx?Jmn%ye86a!p4v9YY1i|CNj3Iy>lxx)7W}>3QFEPDW@Zgh@Ml>uMuH6XEZ=?z*oD zp*ZM=WBc&dF{KL?>UZMWGPO6wGh1Tu)`Z$gy66RGcXj^Q_n8bQ#9f2HCx zBGkhzd{XnJdUh=O(}|60`i86hY`kPXNzY7o;FGZo*V7HVubo6n->QloKa%<~D9bgv zVo9BlvM2sK{ePWEaH{9ZP9e5;IIXDFk&q2gS4DcqGmOZvwC;)(Ssg>hM&wwgok0U3 zw@8&2tA_{=I=xoQFakr~7dS1?3xbAcG@OnRnLGY9ttK&pcWiF)ukD5S`prYq7QWHSZp8IVu{(yO zZCfF9yK(bE+P0st=bQ7cAJlfcN$mli)An#uD4Fjm2f%u=^HGdZ#>#DoG;g;!n#ra{VP#g4lOwT% zupOeZ`3$PyX-F$`ybQ7q0y!#b%VCH(PPmL^tX+s^#*CGwSg3{IW-41rMV_Ko#-W$S z+^X#D2URC%{=)(LdovE`IWi;r_~y>~c~EEb@>3TQLy!Z~bvL_R4=^S``L3Zk=4MaX z3LPTnC0y9oJGw+7>5EN~H#y{h`i7TB1dz`{dtu3dV~-3N`#faM`Tbm(y)$V%g0r`N zm@(j)u~4u*ckAmJ1E$wOr#ippF5IduCO9MgIYaDK?FfUi;f$eZi&#j@Q*y}JJ)(}* zZOmnZsK!hEeOinXTu!%m!;cJ@K*KpGQl+W2cd ztkv{c${V=cCk-78`ytPU$|YqziwnZOR@1Y49oy!x)A$R+cZaT$lsY8F^@D6L(UC4p z=;@DZYgsiu zN7eOO)Iy1pq|P0#HV{0}u!_0$-1GCM0!NP1sBlt)|3iacZy(H5d!1_~b1?u}=E_b_y8V{B#u38?y87yhr z2)EK^a-f1$5mJS`;-S$~zO|?=Jti}}N-Y|HOPicZ6k8k=)TU+krd*~a6;EP`x0V(K za6zR&?r<%uZ!39l8jV++xY`CzS}j4ps!5UY;LOPQa34dd;}r{3Q;1H*=E#EW#9v2y zyBtgM$MP|MQXB`CjLC3o@KOuPibyp>Yol`1L7YrwWH@%IiVUN47)NfAr+1oCO|TwT zk@Gc8QJd)2;Hi*Ut{6*=@^Qj#91qU-knEpgEJSUKQ!Svz7UY9cmRqB@=HHh0vdl-L z#HT8z5ksYtG_rd_<&rcGlvRV;a#oq#5q$ej&hxUMwc(1P#QYkTI)b)UxgANLqrsL^ z13{D-DAVJ5JA-8PxDzHV(#IpE>T~?^>v8Idp*T8muX>G`T2#A1ou5;6ag{p1IOg(R zeEYAY{r0L&8|${kSn16YX~*m0Qs>Xe_D@#p#%A?D{h(UeKEKbo{m3{Lek#7-^f@Yw zgvZ?u)E|3+G-#0NyGxxfBP-qX8AFb5L1wx^j~z@3M@ndux8LH9D4{XYkt=>hYI@P6 zjyZS<_&^6|ofglBEt;8H_nk2b6IWXG?6{~}JqIvE#q2ZR0gQttIiHI2)hThz35J;cYL zb%gh^ebw}5KYc;kNB`TW>JOU8;7w-4NQ0nm$^xSslGmXy=3yophF?iHvsr)*-(#4=NiYN3d4d6!~Cna${poS4EC<`d$Shq;gC zH*&fVZP=oRxpLc9Vp@46b;EYmtNYihPA9&o_#8H64>f*I#rEf_|2AFPQ<3sqb&1w( ztr(iCXgz>+U|+4$pnBrBJgT=~50{whE#a0WhfD1BnUUazOn=M9!zH^uO~uxf?D;fx zuwq6VF7{Mhhh3!@K^%cKXP|P$Sj%EA0w4ZZaWO;UFT{$apd^Z|qyq?&Z!p=(zD>e+ zF=>=@3YC|rLYwktK?*>jVFtSpg`G*9j8bMA975N-F|rLOfvD?5B)JWAm~~W(htb5a zi72K;tJ_fOh|m)#X53V3O{jzIGH&Wr>gA-G&<3_k{*|N}V}pL*soKCYW0|KNDm|TuZw@cS~Chn>AG_SWX9(Pfv5J7Jr^&y82{T_6^b#~*c3gV8BCEW#bU zW80$fJYGMK7TmMl_7G*a21U`=lU@cANmpg@BwReh#Tdw7dh~luA>w@ZTk<4ddMHTk zux8YO*_IofAe{RZS=_@=Pl;tzUyf-Cja@ffFY9TdyK6aJVSUm3zkS7BsmK2mb-XD!54 zcyImHXZI{&_K~#pgShD4h>opZHoM_lt(E4Z*NTF_39<4}&KUQmaos_BnLx$e68C-a z9$ltj;e`)Etp0HJ@o$di+x4RJpZ&WoN-NPq(7c}deP8^QmY)Py7q(Lh9k05f`2lBA zDjg5|QgfU$ns#$XbG1VMsjkzo{c|-v1~j`)Lm&JXWaEdyR(hi2Tt5`2bM&)}>xj%t zp(LaqE_*q%4T#3Pd}@annPU1}BI(C>#&!~u&%+pu3!ggwWsMRSe&OS$FRB;Qa@*Lo z7vHZgf$(JLqn+2rCQPY=`{57%`D1Rvl{%>NlG}CJEh!gHxxI6bn$9|;3%4JTU`3A| zlEUqWOi;(S=A&PZp&$v$sdEw9iPJRR827z9{a%FuFGD+TJiF1f26dwIpWb@)J=Bqw zaUb8Q>7>@h$nBbUwG%`FV>Y=p| zy2jH+MTQf2RtG`jH6kvMiS0y=;W&fHX?U(3%j-BYiVqpQT1UIo^Ev@9dJnPTVJF%Z z58p{Ml2|iU0E-pZ5Uq#Jf1?iEDh;Mu2U~p{%YzxjvDm4G{KL<0HD~lS|$1q+IXTVXFs!=IDEfp@#rOMn})w) z1P5ZDT)noDIK4BqsPozxkE|em2$G`AhFS=v3=vg)j!iaSrHV{1n3Jed!=PLAskTy}H}ScyHYI(>BT zChW!Ob0RKbHxfsMG;S=yMueQ%Kn(UU`31uzKIqKiYiW!6 z7#lK{$}u8{qQn@9vsR`xd7?O2Vm7>mYg zP%(<s>V^!CJB_5Wxm=|(GkTi z4Suwbt~w@qlkw5SFt>TpYmAR3fMsrbxrO8VC_V1&Z~eT$HJRpxCwBh)Zc*OzFoq7k zX|N|33D7@FMyxs6N@G*;uI>z{bcd2dzDjewUj^6FYp$cSTxVV(Cm{4-{T0(t#h4mNl2`>im6mj$bPO&O`3M z?rLgk;ORAg*q-(g4QuIoiYAA2FO-xaEnQtvLpKx5KX|6&3xy6^$eEcMu+{9K<5h3i zb@8OxPUiZY6JwuSj`oKijAV8AQmkkMxz8x zzGS|P(;iWyF^if_kQFHr#DfGhUP*|9CYd!R&f-QB-HfqO<2nf@qJz#vV;Eyri5KpA zMSW`%{!ncb%`^d8O&n9YC_YT60Gz--dcm$s-JKcx$K5ZeN+2 zGMk(gDKAm4kR6$F$<(^%yv4(4fl<_~_o#)`qC_g`sF1b9)8LL|Jl*6n&ckxX>R|~L z-kykJTS{G0paPe`)BmgFRUs*Rnc}UUrRrOCN*hk2{-7D{>BR_YU(%cB?Z*NKB^ED5?-`iA?ObAnz8-SkW)LIBXpY1Va!I!T zpcFE`*1#@0WK`?Md&?063y71Jk@uhapwfxS<+Wb!^wjC)VOj>W-1d-^+7Ni!l6|H7 z*=zrGRo~_dT9X5iy^w_qNx9McyQ~f^x12AW`&?@Ro-a0!fH6M1^9BwWibje<@lEyn zJh&WZTyn?!gxZypIHM^Z(7Euo?L9UX(6Wc0)zf)e?4#n*hiE<8-7VV3Trf9qyB6n6 z!foa8*1FOZl#AXjiW^b8d#%lcT95uFDF+ITK{o*Wrkm6#RJMh;Xx;!OL0f)HjYe(T zo#2=B51S^!uQ7m??0DP;G^WEiFbQPg8btIH8W;X?{DsySg-3fxhS}1Q;0cfhe?J66aH3J|k_GqOGcsxagQGF&`vAP<+atWNMTvnC(20j z1}FR4k<7`y;}6u#Ut)!hs+qqEX|EZ$%6cMkynQuw2lng7iLcMz5x&ZLCh_;PcSIn! z6F=KNi~8b@M^{Owk;SDgzKtw)Q0q>={XW#E#W&u6F|IiM!s$1PrXw5QC~`o5!j>Y} zNpYq2pBj&^lLnW{cV2{!EOik59JwxQ)=9}`cUOa0vy?lorVN`w94I@A>>f8Q2DvpAT2|z!Xt57fqS~;NG^f~}QJ`y)#VHkQ<6LF}H+SwJ?ph69 zl?I)6Y}SYWS+J`Ny6u~SUFGxE5U+gs{8lJb;v;qvT%eWvBB%irh;Ntx8F?@bb|PEOS=LsSFg}=CObgsew?( zTIfNmx4>nPOMsMmiDF=(WFS@$l?sE^R}{mPEruxUS*T46t2k?T)SvjT{9yH zVfR@>vB{PsBmb6D1uR&Y0Jz)w`tpV9~HXL(~~$uES~3W6UwWy}AyUyJQ{Ig$)6ueSLnfpA)m{ zBpmZ<6w~}sFZ`NW2dVI-Qp=>tMHXp0;s&qFUcW%Og)X ztoGF60IkUElPWk+X%2sTF;_S4o4DlnHJ7ykTksEz`Q#c=zW9 znm?Uz_{W|NG~c>dGX6({LSFyhzcl=)m9Z&0t5Ygm;>2;!>QraR3fw32rTkOdoC4Xl zPw&0BNp_NbVgL5#dL@XQ@A-k3k`xPBzNfbLEG3A+S^s=PWHMO6;B6aqJ*)(fj}G@~ zJqzeFtDs(H0ZZz4?Wg!)5T@Y&>pT-VTYGRAe(v@gT5M_RQ3PZ13DoZtkbNGF3kF!! zr!B8-%jIpTv|(4PYyZsLpBw4_ zZ>2k_hdsP}gsOkY`gEXoubqx+xvlr9^pN#Vve$K|t9tLp;JYEk@Fy9?D`!?^YG=U4 zbq&vIl^fv~`k&@UQM(zr zjgRw7`X&9prb+N?1Yo40ARfelp&$v57C#guf?@azwaiM!-{axWLtr!*t~VI|L+g!z z%Ll?Z5%{qN6Kmu-z23*b8;q>K*<`{amg-rSH~OL0SAHyOf-%RMeT^(5`ugxbzMPpi z(Uygt_aKo@@`=8O(4Ru^WJJig78RmRDHB67pv$3S;zFQhp)c%!R+fd@hXnf)3eZx^ceSh3eQneQ#WKdFkue&-(uJ z72>Pd53%D1d^m@=ZO$t%K__gRGanl>8+v*Cgz#COPDS>g?C$vP{eLrI1~kasjMmJf z4%75U2KJAGW)sIj4RNM)YO0win{DaX63NaRtVB~MENnx?O(PQ6@rAHO(5?W-GG0Jb zST_Z#S)y8@OR!6!DdUh;VoJ4jO)+-Ln&N<}Ol)vfW*V}4YdY2}!^&9QB{^VO_q0r1 zU5ol4m)Ty<*E!tPX-?HFy4N0>(LuTyMN{m=Y4%5=gQBpp#L38Y3+$7V?{P5n5cSOB zwX+bW@~E5%nj#%SHzLyXi1;=L;llO z;M>CFkM3II=w+f=eMBvaWN{6w5_EDDCpjb(v#Lcg7;w=6$cr}(9Yoi^-u%s?@AJu+ z4^8m@YS)^{+Zn4CH>$pi_24jVSM!MLdbBv^@}7b8bOQL-K}jRmFuiz&ky3r)12#i&{^BMUYNV4znNT5%x1ZL`+4~hwc`G)c1cQL zofWpusd%ZKubG`S&O=+~Fsk9cR1AMfQB@UJJ1Fe8GK^n9F{2t47{5*8?-XtB9ZtQ; zXzO!o1dQ+E<#f)URX7GX#_LSm5)^sX0qRgZW1}rfS83AfZ!z$vtYaAuHK?=o7f zuu)D|%;WfF6zfzy%0G~N;V=@ zay|wf!|GY10e}+v2@?e~>TS5*a9)dpD=licbkB!>eqCax? z`QE1VYiVhf)Sc&hQhS)vcceWPkNgyCJk(+>ls)vRt~S1y_%d<>@-3)OZ8nyxbwCT& zL%9}}Wn8VS$*f_O0Jo6htL(x0dY4?$C*%c5>7#1l$t9TucIBpJy=3w8V9wm}{s@}r>E z6e#a5j|5iuXouRCTR9>;+gLQWJI9H3CTR(GoU?q%jG&J6_RaQ9Bm!avNDSr5fJFd3 zL)kLGXabies?kf9Rx7e?WxHJ|t1|O7UDntHq_3yG1~(@*5Eo$QXyz=CGYy8!DcNzd zC>TVd2^#{nHbB8Ds8tq-8A$1F!EEEC7)%A8V0C_7SiL1;YxqK;XZCh8GwD zi_C@(kj3sQ*v&{Ev+w3`&>uS$t9y5h^_Q8z^&vk#Gn+WMCv9mqmxcK{eT1BOQ&0jrajP}r@pZdo@+Dqei@zkirNn$}+q zIe*QveQ1uH-_>?y2VAMPC89x*8QS0-PqsZ>UXMNeRXTlvaj+@meH2^5Ie_XSgO7m`uMhb(?W`?d4sitzI76`q5wK-Hl z@uYpX-!YrX^0`avKQPmAy_P?BWJ0P!<~@n8zhSAStpF@dKNgjU7W)1h!B!`UH-Gfk z$%0mM54Xv3ft)tq-Tdk0O8R*l)w|82v<1flE?@Syk!oMCBqHhy8@eq5)Sl_gQimeo zCO>1p{_aglB%g8bDRaFflTSAJ!@zJE81aTElOwZBjn}Q={+K=F= z&wqGFro}6ZhSq=T1av&l;FEuFmNIz4@z-DVo2bxJolyf6uoS#Vw%c7-x!mYKUD^P5 z7=F!L>d8DnC(L~A-vle@P1doWy0V_MRzt7Tj7Dt0+qr0r_?5Oiy|zbpEp9@6A$c;* z?jOFjyr3;_M)lk_2g#PGVG0n*_Fo(xJRB$ro=4MqtHG$18s%ox?9^&}n$+-oE$)uy zSO8?3UuwLxP;1q2SB+`b)_LNq*dAJ(eCDS>Esvic7?lL*z;?xxEmyS&z4>i zARkLoh!vVky(}hfp`N`@f7n1gu#UP*leFL%b&WWY+H;@<0!Ur^m?CcOPg`6<5 zxxD1tG^BO2y|htjZScKmn;o6CFT4 zM-xQBK}aQZG65r#fC`MxXCjR7vFwVUjDyNBg+XKhSr8T!6&i>n2uQ#z;xVDYY*i> z^N7LSw5!fQ!OfIzs9B-9?KhO~p-3g?ZOp006|7in7_A14$_FY6hJVVIFG^_nfPK(3 zvn7M&=S_=nv-}(DPfufG7%P6}LvgI|7dY(NDb&D+E6x60Z%5rW@fn=gysgm;>{OjCK|Mcl!;s0@fQ-;xqS;KKWt>Iu4ZYd-!h@-ISxc(}gt}_I$Hxe#G zk4J+LUa;{}Fdr;ggZPl35J3pyL-|m zns4O9>u946Ec6oZ)9}}0!#)ic&^Iir#=coaVneU#?n}hFo;rH-_tfN<908hsM_oNQ z(3q~!>Io0(X}P6~QVx1F~VZP;P<)aU?XdpAN(b>5N%srUz3Y{B{)YA;wHL9D|{ z1*KwunM5l+pVxClV_!#Wb1;e{2}+!IrL%TJO-kHu=uaL;`5h-OpIiM=8jcmYDCx)t z#`kyO09Ql4wN!@!O+ooRXBwU|KogF*HSIrBU2LkhA!lP{Gw|VSX8nn)XJ-JtKgy3i zX<5+>X62&%mf-_I`WjX;$v6Khb=aj=Cg;i#x4LE?FfNibPaBP5=75x=a+-*iuJDQSL{8!I#2YNrY{71UzWkh(^#?P^33 zG#$Hzx)qudUj)CaldZO%Z=t%6Q?IR{)b!>)P9}%Q$$mgKLGh}2XaxRkVswP3Txj_K?xB#SN&IvpM zu=huDU6oMx3%`j_9hyMpZ=i;H1_LHOog%n3*^L*;2bfLW(VOsPcA}Rm=hc1GV<>uE zxsZ1(!rViV8bOr1dK6j8<*kCo3Y-)jAreKegBb_4idBQ5PNLOm^;Q*QwaVf+eu>O6 zE0L95TvZ$$MvMuotVRkl)`i^#byh*Em4x|KHQcWK#HRf9h4VMoaAzk&*VcfuldDe7 z-wZ8Y23@0I=dM#uQ6CHNE#6hMbj=MtNtEr7Qm+mS`cGIMj0n>g96AvbmL z1!_9b%x1&A*fA^C_1V$_30g64Jc zQFDnSx>}B$AEbT!1V4`XLU%_6Y4e;5XQ`3A40W*tcQiRS(QlcTWV7( zathZZ5qDvy5;KwTR|p@*=}b<8_lGcUJJfa)L$IY{2rSKP=QuD(ibAS`Bs1WM8dZnq zRj2MB$4q7C8+p|@(czjd;<~MpxS+A&^GLg6No?>~mxBzSzxUIq)wJ6mIDQ#CJ2s2l zbwneglr4YnK%bfY`j9?jCH5cw^gyAG%cqw*8WxNmLfXeWi~}V@IWsOVl>{BwR#MVu z1cSC&Mvi|{#3eZSTB2zzy;O~8G#ueilagK8U}tVL z4W0Jxr-M$HockJ=W1Bl%SI4H3;QQOY{Ps+y;>AzSIo#fdHdz9}=*R7#aW>~o4I8{e zB(c)k4BMiXC&^0p967r(maf03|F!q4s>%F?t;W8ERWhltY%`8`?9xbFhlk(0+%J_U zja|71Q=F1U`nBhMc6e10Ap5mx*Ph4s>*NPoTx;JYZu%WwUTz$A(|r_-_xckbw{Y&54*eLf2O7D4%*s4ra^yUAbh{X@2v* zA5OD;czaBRu93WcEPl3LNya%$IN)5Zr;=mE8Rs>&{=kbZFX>j=C$LXkJ=?wphUl8s zgxgRzY%`yvn*{FjwosNoe)-h18X#i~3hK|iuF+ouSB$d@fl0)lG1q11QoxatOK?XY zFR(5rpY4bt=^&gI?mN?UyG+9)$9F0b<=*A;Dp0hLTZ?SRT5H|!Ct&$N!}#(E_c^nZV0kw0K3T-(5GAOB%#Z&yR%_`wN&@KFStRkmb7A@wL!lkl@%+|h1+jnQ3BBe&A1}*%)&%R<~_s$(-w)( zL=Noqqr{pplMMi7*-&UGP%Ao>sScAxR4c-39KjYbpE{)?rp6IsSvRF3dO5UlN=4jq zhYjkDE8}b?s@OP1vqM4S6mVU6fEBxX%1KJJM9@=-_!uqmsz0Wwxl3vs6~43YFbx|6 zJ%xqaA0sgL1!_Sm&}A`h;Hn!Kx-41-u3A2HX(SW`$RjHQwO2+0W`axR?UD&3B+7gh zv=A$T*_{Hvz^{s|{dp`9As1Ldj>09f^r4L1yfYY+Y za+z3)8lwHGUCalf267y7KA)t4+|hEj4cf>Ygk-)J!=I0BB3}F#; zN^Fta==~B*{OO-e~^ujgcf@O?$qO{D9;%U zfW3zJ?p-Elf_JzjLmimaj=aY+*V`n zLYB`wiu#X{vQUT7V6gnfj&B$EqbV6j;OqGC@ytDVeidtnE}w|np-Eq~?9VT(L<8kf z{=?5LPp~SM(YWnd!*6KKJ4b&G=+1Bcud_2)e#^n;MwTzJwW9Hi_~5Sp@bq**%Q?@^ zh&cI)Jpi&f}wp!}m7FV+D%zfVa_B#N1f&)0&?=05=1DAZ;&p*CzC{1c{I>}B+K z_jdZnPPfl9Nk7&1Pljve;7Ia6gO5BD10O*hqSnRJUAg-pq1~mt9;5c(??HF?m z2MpwRWSz5Yd^E8HE0ryb1{bE(Ny`^L3_XEV&*x3IRzrVDO_QkHbgp_DbCM^mZaP;p zd6EyCzsHvp;BKE%=K(eOJE1D5QFr=4ovJe(Sb(f0Rs_hY-da%Gi>Tv)hGQuzpfeVu z3IhF+i8d{>CT5e+T?KEsyOEXzpsL71q!MX42{MuWPkM5%XLhQx61fvQ-R~#RKURX1%>9YVR&k>@Ce#IxL7@uR3f8|I6ohQTru*Gh zW5w!z2L$Rsra@gyCsfi0W35DM7d=kJBn(iCJu;wbU7hZcb(1g}bl20xNTiB<9?a5v za{(0Wctv;yL_@gX`<| zoeR6L&$|T2x%aF)za~tfS281+vrD8Nsm18uE`kKyHuS<+-+Ok6MEbte@x=l=tux_` zL)u<#H4dq~AR~VGUZo5#FR|V+E-fV!*Coz+SxMPzCzsv@*)7AW=yO-TlJW&>SQ>CC zDR>vqa6qCHSCXEqTteE*p8L6V(=OmBMfuQ<2yxe^Wc`B|Vv5~#?!z&s;#SDdt8`H2 zSDO22GaBmv9(!Z=TA6kY*mB5dbaP}UHB*w#+8Mw6A*4kv^x(j35$*lWMaiT$X7=X; zqGT=sZ?n}HaIKj}mLJ}9#o?y&GFDFAcb}WpO^MCp<(VX3{lZ@#%y*Ieo-+;Kx$h$D z4>@~UcGEzjGhea4R+_9ey>)LHtU(M8YwDW&Kv#V!MEbEj&&O^J*sP^cso~(hDAE9^ql$X zk+;}(P{Qv)>{X5oxDPbV?bigneqGRVzg5@Q?uKhYoo=oI%E@kS8K}~TlE&p1A-%|@ znzhpc54Uu^)$1TuI0~}4vOt57a#(hdwj~If0~IQ!gyjZ-E#XKTwk&rl@&2jmmZ87K zzC84ksmND{<{s5Tq0eOP)_5Xt+eGZ zr4>>5uqhNMhgd{~kAHMSTd}JssVM&0~;YH^-ZIW)MpitPo@&bASZps*<5F0jUBN zu#Q%B`n8agou3b(USS9=rr@_aJSdcsM06?xkP_4>0~DfdgA1ZErH1R@MOI4<@4j0X z=sCa7)xmhbW*>HXwOK=2rc35#tV@!cpTX+=9$7e_>M09QpelmA&*Q1LD5mm#f?96@ zVh%CG?-UCpV`sP_xuQkyi~{N%*n2XZcN9p>(&XaFPG>A~@#G;xV(($zTbjHOX}q_R zI;}D}64~)sWm+n-!%?glWPzQ%AgWPOeL>0Kjf)yKC41szB6lDuD3Y?LfK^z$+1^JPV`-WeO7sO4$+5?m<&LE?a z3Km_Q%67l+T%?QzB)ZlX!9TDzqO98bDM)i2QV#H-4W(yvmib^Zc8vL;DL~5@a|70a z(|K0Lo;SUvw59n8U-EfXrE?|rIrd!y?`jcu-tVjM2S=UXV%rzb8emgDE6y1BK&#e}`LPJ6R{H*C1fe$JsZ=^yhOJH~G5FfsiNhnpF-HUQsG%p8HPX3;t!U?oIk1T(5L~J@Nh$kO@`TefBkWEJ!UFeD2 z2~Ik;+mvS;62VE|7pq=6unU|t4>oaw)E%6(&hf^*rp4&-OTO{ehQ?{EDhxfZ52&Eh zgE-;s&fQR)?DN3-<|t6hj6yFWb7TP;`QZOZ23jV7LqLqDhM6h$`; z;;*slHRep-VL&2dh;^f%)^Ns#u5(UH@}ZmwS!v1R`zD|@ReF4OIRWT#n0brgb(9Or zqTglrB6M>hzia8@(-YAdLgKg7#9zbf93Rd<-Iv!_+D_ZU&`X$?oDX+3`TMfs{BUdW zGg?wJfSdf@M&IY>`SP1TIrc2dagpD3`^Mz1=yI^o@1BH~xk&ugEl2Z!<(bRx?7R(F zqnIU?KHLS7q{VHU67X24B=g4`PyF2TU-0dkL%c*|t00rwP+{8IarqUhhPWWa+E9f{ zn|+x&uh3tr;^eY>39|i(2(jCbv`DCRs8X7uo*?M?+pckx%Un4F$!hHFX9$xhF!Vn{|d;P8=t}OOTX3W=Vjsjethu5qo^}R>4>K;%Re!nxam|F^)0R# z=-jroUY_eO&w=Y>g8crySnR1!-doCCPyFbgt$OmKm$-jnuEIWy#3|?gC~Or3>J3{? zm8l?CwJub#6jOdo^13(4tAfl3TN&g?zpDeyW?DyvkqLFhks{L?>>t`NnVDo2Th|h- zLe(W?JDFL53P=dj8EhNpt4YeF8n}7>^H&UTUWk>}l`<2k^!mI~OBXFC*Lmpzu7|49 zfiJiT%skce8c7e;6e2rM+LE6~EWMk2|DJV2u7PA{RcViN!m^R%y}iir-9{a|tGm{I z^P-N8M}_D1E%4H}>?6&I=R815blN9=tgx(9uexbsb=d!|Y|UFAJ@ zXjK-AA8Y>d(VEJ55}$E*j6-IxzSAGr^NPaCbSiT9WGk#bZ}hgF@rsMq)4aa5*FKk* zzUmkE>G@$5dwX}!it44ZeBoWM9$BseEmIRU1)V6g_NQdv-jSfQlkH3`Z&=I6ylnD) zJqs)@8~N_0`i;DN>W$Bm_VYFgkM-|-19~HO;`q4gE?s!}$Pe1rv(fH*aonRMd;qK% zqFGDOc)Zc~#Vla^=F{x{alh15R4{KFwxN%=r9Z6W|Ud`dD>C6QHBttGe`?A>t-hS)k7Rt7>ZTm zh4+O7ZzrrL&)dls?+LJuS&!Z0$;*kh4P3a#Q;mHx)D>94@6w(gZ%#TO1?=yZUWe=- zta~-gd8)4oDbCo~SN0UF79U2I1o}2H3>k;L?XTS4af=I9S0KCmnL7@d(mNWvgZlA~ zq@?I);^)@vNK%k0HvO5dYE3n>6x)GmR%=vboLS96UMu@8pM;!3%n$N5HQzA>{MKNH zVtS*I8lO3^cEdwCt5DDp9I6Oe~(sf zFO@BEP0`BEvLs94iEhfy4|-c>5~s#dX9qY~+4aHfE;CR3PTBS0>}9h~7rBtn&01gN zy6f2NUBsivzZALRUzxotchxLce9G)yJ<5om20QW79{OBoTuL@kCQc^m^chGXLW?)I zt-$nTqn9r1t)ku2h9x(b=slm??IpJ`r~R=5vLEqVy92Af5a5GlTvMy&AQ#&mA`%wa z713TQlRJu89gr0UJ&gf)%iy%nEcX6r3I?#?4Nd@i`vYtYXVxOQ~Ru z%PHkri1t!zsKfnwta1IYC81iVbEEzCC*Bs<-(bz0d$B{J4OVFiR^cLf>WOS_(7RdtqKW^g@7}mqPde|g z3HEC2`UH>9_2ys+WpKm6(~+Vn|Sh!nJ=GtOKcin4q6I$Ssqr> zz8BOgx_tZ5Shvb1t{1iMRA6nHW{%yR2H`Y*!gu5Xbc|#9!Co4$c2=79T@e^)bynrH zk8g!ix}7<;UN`Z|tl0y!x1gGi3lHe{z`<~`9iw*M->>t5l9UuE7sw}6(dPwzZkPvb z0*eyK&j+y7kqM*T*k(dUiXPkXo8y=98nvl&x2*-}OeW>iq3_5`deR!|ExZ(bRIM0~ zjsQ8HxUCd=deCtgY9pTkHh%r1qdKSYy35sXb#(D{9w-ym@_h6|4_(s-#hvtf?N#}5 zN$V@{K97YH0KMnXb8Ps|LwIb=pEe*(8{wxGm;YaTHT<^1uYErJr}=Y*U;BGpyOQb8x8_aQPAso3sUAOX+dBY~hWT||*x4L6b&s0xEQMO5Jguv?Gjp)t^q^iyL(Z#Fe8{bS4=Sfp zt8=Qc1>T(M4F{F|*t5j?9cK@^_7~JOE%Cd?b)cZ}6!t@E!3Z}t30e5Xl0v0mL?g4d z@cAbTmE$A4RHIt>{L(_@2R(9ep?xPc?MuBn;E7=4{FW4^eW6$5E0DYOa(sD-n#Eg%spsh}s6S09+At5zH_kEh}}hU-FO>m>~bM4?`zz6t9rcS9DM%5kue&GWHgFh;*$(5}K;77TBX+nQJ&_%Ey4`-CS~r0kzCBpoLbp3%$%663 z1(sWN9=BTw)~Q%5R)Gku=~c3+u3)RNHtHgqrx7V)x4Ql6o=x?8vNGF^6p$`mMXGSP zvKDI#)L7w8`Kxk0syb{f6>9Ark!Gk>j3N`{BniA& z1&d!rC2$5vE0Y7gIMgd8>1H*?Td%AbM66mdXb^Vgir(pJOf9l+dU@Nf_?zv%^rtP^ zo=V&O>2ZyUcCFmzpKq#1^)SeclF+~l=VHxs2zn;*(Z>Y9a} zoYciBdEU<n3sEHM1JrS|nHGyoga83TbqdANvfiNP*pQ`2h3E}72AkfxG~HEbbn0kV8Zc=M zqQ+kQONV|i>g=#OQXpW|b{D4!d89uXXx-E_7i}voXtD62O6THf)>5=o3$53jw9c;B zth}75yEiR&3TbyX$9~}LwBGcyk4&*&XAmVau$3w|W!PCA7KWyjfF@wfm4;l~~*M#wc`XNmEEwciQQ2<&a}ocgFOHqmDGo zh7P`OOPy?vB-{tlsnSxXJKv1#?o>_Wm~7aYe$dJ4Umq-vO!0z;tn;9%Pw}drGIAZC zjhNvDIyTr#@7Z#^Yz(j>>(}pkReBsYd{L9HviA5-KlQJ#RCW(2yrVf)HAj+vs(N(i zX1$(%(3IIceqM{1!^_nS+I|s?G<`j`{~5;D@oBLdkDu03nt6P>TYDKj97x=8_)tfF zD>7)iiXnoQEmh=-*(k9|TK71$`*9FyN&CS1Zx*BFbWE(=gRi2az{(5jDxj3Mc`qBi zZwxQ1n~`(=IzFjY*~kr}S<`&z=sP4qT-`#Nc4$9kg`9^&*fAKw3fj0iT(Mnsm(t#r z#mtgWX_+tg#f5E23o2JHECp&caW3OKHcXHk2VmcKyqxty|7rMh7x{ zdRYzixoyGjVm2RT9t(0A^SQGcmu&aR{1caDCl^zp=Y!sFDwQ_jKw2)T(9VR0uZ1lP zHk`YFOZNXY9rbvKn*=&RsnainD79`Rb6gu{X9inK=f~knwR9dFLyOS5v_i(vnA5s- z%&JiDW2OYF1RIt>d+f;V%FZ*XJx#%~If_Fa5J8{w8<-cR<7KMTk_3>;@%(})|5INA zZh8ebYdwp=!tyW?T{iPRbIn@31{Ru6Xx8>=;1bA6b9(g~0E%@U-DW2NTq1c+-Cq%( z1YX#T<7c$J&7gLnbwpAZ-c21oJJPk0_kpWgtGkQ$q8jqG{1j{M1%KTbixOr5+2*&W zjgO#g+6)|j`^%Jryg`DdT~ma|RK@XmITFfH(l@||+(&RbCvrf~YRNvpQ=_1e`n?sO z_I~CU}A9#wUmeNS5#W|um-ggrhQSFnfVxe5Naxx8HKR#e?2xZ$oM$N zZufp)OZk3(HhcE$+0Qj=t-TiR6)Oq+8~nQqGSVreAFVVr5#~sSzukj4jYbeS+~`V! zN6g`Q@*jTD=FbKaNQ%e#-PKY zNyq7M7hLcM9eEiZMF+=Z6dr-Q?gFptO`Vse$ek&+6HaM?s6qGy>_om3Wm(p%nuJWM z{&B1hB8WKdU4wMknks4oSdC4L6|inr)hfJGjbvi)W2;J=aZMNni~J5dJG8v_vEt#SHUc4V88*uCwIwx;goZILM2icavh z^j7Hv-+*Qq|8~F08H9YL^rwA=}|{ysoaW10!-|5&gvN1TZS8uKu$MsD|W^=4vOpCHV zduNrCTy-|>JU{t4_S#0pJ@FECT9$w?-g2c z$Kx3yeQnRViXOd;YMSIuh6G)pB`;|vw=;Qg_EwL96J)clC9)Bh0`ATk&BIKIbm~1nTw}S2LGxww@7T6(%~=v+vP{M!-_R0#=G2f zU)MGsd&=dmt;O-W_rud=-w@mnJQACGYh`m7*(TN|w_avtm5#N?%jNSKWL2Xs{#q!r z)w0eD4I*%fWglxsfDYp}^FUV@fiBuw5KRtbu7nj%a;H zc@J;*XRaW+nf2HtFpinIjF*#*Xl?2;K4+H^m834^`CUf2B((%A01xn%T~4`V>;Vgy zLtTswrq%>^WA@yObr6fbaCGfe2<`wEQtw>2cmXxQ1im~Mo8wq9ci}w-a1l5hd~NQ+ zA=8WU9OvgQ9ELrMEzWhEeG(LM(b<{4!=`Jok<+l>&y1h;v>u!iKW#2p?}*Q6Q$Y2$ z_>3p1QPjAonP9aomY9O55_q46Xb&Qac9ER5qU{Qihc~#>$#Dx`iE*E3D7BrOhY}YC z$9t*{?2S_H)k}Kp6WD@2<1` zwP*6U=woO53um6!tUGoREabs{!UnKnTEARy?S^UnTwwl&-e%YOeClRwgxR$bdyCoC z&j1df_O&3F-N08zTV$fqB3Ik3s-_fT+5(9Kg|ttw^~^>gtr|O9NIf7SULF*b38FSd zP`uJu(QyEIXv3n8iftA#MJnXSP?@W+t=2Qd;$*P6lmNFPd{zk*Cjj_%>KMmMB!F+CCpRQX5n%*=lZMMvd17 z$#}#^Z>ISN<)_yHaE1 zy{b_X?9b7k{L)RW-Ib`tB$s=K5f(!;-~vqDVnWxpt=o8i166>QnM9|j{A8CL~O zclih^D&MuJaYo6dNQj;Ev-EeV{Y9;QJI<}flgfiD5Xxuc*PUIUzLryt!1Ap+x<2(~ z>h!s>2ezs4L+kOlfFfB=Kyw&mIq9~2w%=#l)b`rTSKALkOtw!8DGziz=z5-j^^{1w z{)6w}bIGJ2{Z99uVzn7x#?sTP)Th^ShlcM_<1Uwv>eX1**j#Enc9#;0*g!(F(+=Y2 zVafJivZVV##L5pdO1{L;EtA6NrLSDX)1&Ay&<9rtkow{kYmZM*Uz;5gfh&SYIpj~u z*(`OswdtZ>jm2gT*ZYxel`S0k5U~Q&%^!U+MU7>l0q;*cJs!^CGEZ`VlH-ldlP#Q2 zKy6)7{jVf%^+h*ZZ%HlA@;0L0&GwJ>xK~d%x?eTd@V9DD-EqGPzmdOJ`n}ql|5n@a z|N3^nS=YI1oe$T0zBDRL&4}F#mM%MdP>ol<*#(c`=D619`6K<2{y(RQ@G}bWwvlKU zlHdo|@Fk;EGzN`CBhWqQA@~^%)9!(3xW;b`sreg%MngOdjf1Iokuh_44Xybjm2_-q z8=lnW>FMtpPQZU7HGJ@!fkYfH;JQB}F9>+Z8`4*UhQFD42b&k|UYtVCe?e8A$;^_x zD{;xCL@m=d`SmOZG9>#B#hQ~h4Sjt)Gc*$k#0DhX2ciZPbl;{?uge#}?VrZU&3y6r z?VrZW&8Fh4_jeNqZz1j*T)F#Bc{}(9)3ST6yvcNtxX2$Ym^+VX%+mN1AHlwBF+PfY zZ)`N^d-1&_P~$sgSyC9NZD-t{u#1!8Vl-SBk>fI_EtaqilNU?3U?adjSPqLCA`lv2 z0O8U)0I8x*4QJx3IBrKnL|2MBQU1>l2ATwkUgNQSJQRs$Ni^V5&6&1B$!dt9T4Q*t zhch}Fu9_B0j7W>!n?j7k&WV@}j>q0oZ5VHTYVzz`T;Tr6vjbJD3?mKHWVA2c5twL5 zmiIYqft)E>E|!?7wjoqIxGN{OMquiOa0^`6q*m9L&3oQW= z9BAe}8svH*p#RRt zc#tEyWzLRufIGaH#FXL@5yg|d0+xH2ld#$=G>{-vXui5* zsPbdx;Td8-M6|S7`e;x}6n4fHN>P@-wmBzAh_Vbq?q7ohJGMa->|?D=@!D33cC4c) zz>bnclvxyLN0KOG^TE_24e`DXj>iBsK+3djs}!w&weUg4-iX@Uf8coNa%Itfm8d`>^L!l8T~SVv_}%@+dVl*Qk{@hRdbjk7rM=b;|6CU`OFm7qlAoXR zZMYzDKjZj^mXl2y)@S!ypP&3Lds5vj9M34!uFZBIBVVE9z`C8zI7HTS+-^$3 zhLz{LG6HWck?v2ezy0d~emhSCv`x zbESU#<1*#KDbk2i4v5~N&a-N3uv<~8>TvwVo^+RP5 zslR$u_FsROt2&V^CqzuX%}slL&emQ^NOqNw*texl$XehcV`FdrD11uwt0AOZ%A^=I zhVC>Uovruzpa{{5zpsC6{72?F4H265gI~B)&Ic^GU zEvNiX)3v_%cU14Ga4lI~r8??dN6lUgWp5M8O6%VD;ufo?mDg#h=xG_VqJulpjXA`N ziA)LoKFMo&0Ov*R%`votR#o=?-EPqC9pydsVY0_hP=txe77%uw)>=JvGhN;^Ttjqq zWiMVU?eMak((Bar@5(x8x3P}gV^zC)Dt0ia*Nqvr|z8m=yz?Yi}r z5mn2jl5Wr)H_0L2{PGe)!Q@kI+G#nC&|orf%DLum=BRxP-EpkxMfHrYto~&ReVQGi z$7kVZ)$BGLZ>@=gJVFU+&;AP;r-Y8M@b3Pahao0)Tr1Z6G=YA9Lumc>FX0|V$DF&+ z67mcjf#e=qQQ7q&xXNX8zP0{Hf25n6aA9o%;%r0U%u0g0EiSXV8;wDu$vDnq$tcgG zNcq)Bh(^GaA!sNW5gNCA9}PbVa8DkEc(cyONAJUPJa5(;%sw3Mi2;{e;Rfq|f?0!m z8|4H)KVRPDEBI(QAC15nd0#Txv(d;-FRoL0p;g?5hHF&|>ZrUP)N`E0AFJsC8o_vr zzpd5quJhu9ndAO!Ge*43{8}|Heq3LNu>!jRyPA5GTK4VgTgSaCMLVg3sIJBWaN;(i zP4(HvT@3{fQg^rMc(yUOq58q{8+5(&Y-1s~R+^YDVmK1x6L6)r@e0a%zpqDF@nR5v#Gu zsD^hUjSaVIa*`T@HaRA}6Nv3Z?Y#cvQLn*YMNtq9s-`eb6Qm0=nbM6Bof$LT7!eBg z{X5umiywA;&n?TrTgLZ%YkA)p#yhBe?nom(JP3TH?+gbqI>x&x*79QFpz`7{6Bt`w z#F-pcu#)4w8k*t&b&k-79i?SXth<(Zs`g4ViJ#|X9y$$vmG{)4GsJO+&eVc01@C3< zI$i}96Vvx$ozo?3g>!hT_Z3-Gr81`^r4}K{DT6YIpS1&Jyj#6^11WP!sKxs9dRqr$ z+u1GD(-2iZP+SxmqMHi(8;rWh7^X=zj_MQdsU{v_?VuhMG+p3&0&*SIwi91}KpRmP zWs|~*rIJGj+Cbi$T7fFS%S#>Z90B=JB|nGT?Zp$SwH_YBCOz-iK`fAVtgOlrMifXx zRyyTtDYiG4L#ZR2R1=)9f)^1J&L*k|)`}c&wWb=X*C81u>m=Xg05mC%EaDZ zk1|WZr|WI9wztb){2%u21}=&^ZvgmjUUqkOS=d!rSYd@>K>_n+u`+x~MnJ^W1m9E7 zRH!TS<=sE(X@nA|FRwuPUDyZ zvP|oe^4@D+E%UT)=z6#)0$DqOgj zY=8C>30yQ5M2m7Fpw;QLDhUc${bc^cck3OXZgNl(P+>Bv9w*1w#;w-oFMD8D9>}z? zI_q_FJjisM@6e+$DDO`1v7C7b-#?P>uT@Kjexmj7w6&bjYiZxBmLqMYGzGW2h~yZk zn6z&k32cq`Z`{XQK#ixrd_mJh(2lDfF}NCo^zFa@@f6%9LiWpq?PgpZy`aZuxR4N|QO}_nI=#TM0%tVn4LaP2h;nK=9ycy_Ua{{z ziET<$xm|0pJ|tS$g|v${tVGSqKnkwvu^IMw;&gk0O&Hk8hc=C!)#iqObUJaeeflOd za-@BFia8dUi;NUDWaZ83w zut7BenOyFf;;i0j6+PH25P44|RgPrQDNEE7B~cGS!VL>pyvtaU6W78aUE6C+9a<+P z;IFQWuf&0wvRvjGDLF&G!(~1tCBJJxo}u>bXeu(T-S<>?1#2f3K#&!w$*L&@vi)eg zOiDqiYFV({eX6sQkO^gm*_N`(hLo~V1;`guIP4Qd^D|Gpl>+1Q&Cis)lOo=kZ;tBV zeCmhu%@G|O*vXaVh_ZJUi_0s`!*;!MF|BJ)sqXLE+xMp}Bi127GdUaT(#%8|pR2EE z78ZzC8ws&-id`NGCG5s2AjdEzT)R?`)g3L_g!I>8PYm+sh5TVKcVZy&oxz;nrCQT~ z4NyS`l%Mf$B)r+Mzqg7+q5Fd_2#;0IGj!%}d^i(NGvne`0u1ANR9|@s?ql|i#%|J2^5LpSX+Yt`g#rh#) zBz4#*tlUwcreU+~UHRYT-BPBiL!|Cs{%z78H$5y?JoL>Z0}V?A%NJTFM!9Ky+GXWn zQTlDMBkxpMLAR)7ed=>ilKSygBKno?R3Rl-PQ}r1=5bT zc731EMwyvCIBgEx#20*R!1rSW-zySIyOg>2d3sN>8Jo|D zJV<_=ete$cz%sSZcxWIQ2c{zVP@R&*n1$HAI6ZaCg>`ARY_iO(S1nGjryK3V9u1&s~#`k)B{!ItGU?&^p)vX~% zUGo~r{EdI?-Qe1MuSi}y?u)V7zuvFzJK5i=)=w7edk+`YZ6&k3q@~C0`TRNmUN6ay zjQ!xkbAE3Rl3xGDxmge{(lKpJARW5Vw%2tphR=j>C!NnHr=w-ad=i_=Mla;kfA@_D z&(l~?(|>0YA%-rKxAW{8$oG-?segA_N$(IKb)f+~)&@^+?CkXgDj1SqJ~@40KDo-^ z_1s(koOZ+Tdsa8~LishavC4Ds{-oQmBtCqk*6JaL9nAnZNZRt`(1R$g-W$NqW}3DPECrsP{hsEDudm}DMLJHd z%X&2A3lIP8x;aRhKmHsRumTc}FQxAC&JhI72G#0zw+n7!8LmSmN+e!iXF05l_n4%f zpQRf*!aGj5z$SpCIwDBElMzH6aU_aY6QH zdx|m0-X=$K3_p(@WO4}8`Ttd&kF{eL67#w9g2SG{-+{E-GhW-xTrgKvY338X$fZR0 zYfFt6mU-8>H+oafA?uO**J#Sv!TVPQc|uNmVwLQ{maKv-ACb-S&6U#_tQ!`=Drc5l z7-S7H7kLUf0SZ-rh0K;G5;KVNoSDc~FdLQg+Vym4IFX~0#w!mxK-4H4*S3i%9A0^V zk8R=>4X-@S$JTR;230m))!x{ns`+ekZ@G|{I(G!+>-}`LE459TNDoY=uO7p~-Bc-)N_G0GszV9(&MtVlqzO^>%#RZBevu zmr(&WMwCgNM5_|1FeXuL-x{beXn*5r&RQ|iz|i`Yu)rD5TDgSu%KPnJ%RR;ymG1~UQIvgP53K%9~>tYHq@N{ z8=FekzsIHH!iSJYVivGUDh#(~ko9?MpV$~sF5`Fu(9qoTe3)8C5_7SK&_9oM<*R%| zKPi&l+7-%%C+r@S%#$~LbGPxHK~fe;M_oQskFE$A04aW+u|=I`yWo9L+bygzZDx-d!mBu(;1sBJ^^UE8R_>w3kBHJ$iTPytd!MuR$^koh|M9!T7?+){|9K^%)#c76eb4Qe4^&7bQWwDUnQ*zepfoc(Gtm2YBt=VezD4Y!(dRTJnN#klk zweW)EUqjNR18=JJdyJ&r+NccRBroHk>lv<-_*LZ9p@9G|K{wJUI`Wf1l%Iy4fZ~|H z{m~CSYU#S!m&>w_j9n;7IrInFzgmq9|K0nty42sU*R-ybkhn@QBOdJ7>}q5LR=`S) znk8-aKxQ>=BaUs{mJ{kGjwYUeAL)S4kdI@}zQ35*gq-7m&#@063z1`~`><*6U+n1U z%X{{kk;Y5ZP+}mh=cPR#5(9hog%P)}uwcL0{(KUAn{4~$UDeWOuu+Y~l&JTxCymG_ z6W}XjRCY(hvt=y9Wdo7b)I+!vW@D{R5Q(@u6$|Y`km^qQCl>gH4nGX9!6EXRS?15 z+aubD4xeg$yDpeRyaf^yu@N23i2y#);h#*crP_1yu)IBIghZ8sjF5yJX@mnJrJNjT zBypNFG8Q8JIny$T(zJ|Gu@F@!*)vAPsahcXAU34kDlA7e5Unhy$xvA=j@iior-~!m z5v?@pXJ;#FvL;5EB8cJC30L#wnymS4hDE?j$brc9by)*l<_K^S0i6CUS0`&+W&uPj zkCZeEeIn6yU4rD2=OQI(usl~1AP1QvB|{Dj_Np$c4RV?$JJ?){&OOug$PvLBRYT0R zv#+JI-LS{Za)T4>VWnod+6h(*mc{b&n?!VxYZo*_vFIvmECs%X$aGX@_{uBGAa#`t z=u+enhLsGI$HNFicN>(aLMG7_Bx{2TtO;48$)o*lgUiaz0a@)6GvaWpP3Gyfn^$a% z+>MTA3Jo0gz+jQ&PtuQwPqpiOkRwK<1eufgIbd5^HbF&?%i{~o7HZ*kVbgESwK zyGy?sQt7ojZ)f-#=%L21G7NH|TKuf?F;RQb)*!EaphDP$uGb@Qnp0wMPf(KQkwYT3X|b+0ygBf12r{ar zDE_N0pbn-8Z?R#?c3!dAI!Q}MU5>yb-h4Q1Z9R>{!>U{8rk0P`)2@y54#!%~H0bM>W;)UdJ`V zzMIEX@AGQAUOPwrbItg8Sqvw-0)%}{GIzly1^E!{a8}%-= z6x&19t}1B4k7FX+$txT;SK5zyoz?Eo_{X+|IGN2qQmbV_i9jCJnCPr!ln8gc`CM`cH&BHOc zCc>R$tm0TyaL7b|orqF*;_-Bo}mA}rZ)2UPLO1a(2@J>cioAAx2{6s4;j<-r(*sPh(=XS7PyY=-9 z%B6)JhJ}R|AP%fZXsSq zCN=5n&%8nOca)dTyfGvtsSf#@A;zTrymb0ylhKK+d)Z_nR+vl!pW>y;iZGMwDF%q; z3|Py;Oie^fY%>x{LREFK%`1Xrbg>65S2f}w4xNmwr6H90TACl_y{dwy(4{w;v6JwU zsGN<>`7Vk8b7jshi4xo=XQuhP@GGn<*fGS5@|a;n?>{OdPYGlC%4u%vX6zzjKY1F` zG^QU+6Rj&vAv&s22QytrK?k3ux}J^}bm9@@aI?-y9qIfy)fI`|nd;&PY4RhSJ8v$e z4n4~+40Z@sa_;Q&5uc6pn0D|IFR?_la;n0T<$HOl=H35i?_R*7s`dqd|M%WA!wd{C zfDiD9&LEoj$UzVvscg_p%}mp*PCf=RwbDfMEy4x`iOTmeHA~b^FUve;WgX4&QE6W( zd6Z03!F(Q3QA9)@`>yq0YY)sYsO7!)yZ8IfM)>__yJlw3e$85IueG*WQ_LCw^5zWU z}6lOuND`9|_4nZ^M?&1_wXG2FkMb1Y;kleABN;+2wlQ)l| zu7b^JFl2G=D#%l%Axm>#g}h2BWNB`8jkly=beq%&{h*EwJYC^MC$)eY(x8!p+L);5 zkjn<#<>*jUsmE+jjV=?>zQegq6So2s5y$QTxRBki+1P)Y zi7ycS!D>uu)`}V6awE4b>g#4}53Tj;7uhzDXpV{ zpb}JdF;gu`!#3uL*D*%Vn?@tPX=4UQC)=5zL&wY=WxhYQv# zY6sTGZ*GUP+tjkaR7}(4$UoKFPHZDwWQ+wX164hsvgAj zv-^d{W?DL8$)jOqsDWfv)9}68MRiFliSLPVRFkgi48S-oEb1Y(Y!{9(cC@786;&FA zpZ8kz;W_HK{aEDNf4<;lwZrZ}_P){$g>Q*~JOVf9y+s~X%^ z%D=|fDXKa;3#8VVKBZ^j=UV+_s0@a8)e*l7V2;E-oO2T4b12&7q_OSh#T+mz`0bQD z>-P6KOgojF0M zqM0$6JH%aONNcXKwg8%Yu<}-vHFtT6YebTrSQjlNXcnM;nn}56pyu<|`o!}?;1~}h zS$@>)p^i(6ikfgw)<0Q2tZ!&pca3+}n&UFotE=6$tqyJAA+DcwnoHf?;Nhi1e?=?u zo@F|j$K_`&TyWFD{B_JI^u(A^xWE23=6gK0n?^49V_GxO2G;qgPI%XNZ(7-YS0ntl z>M>;sY{a>5>+xZs5={^)fs5-!7K+>j&AnXbowdkb1rM#kiCos_-ySS!;{McSsT6x( zX57Uen4v!knsHR)kD$p$3>(0YKdyK;C*0W#Zq@`=m6{dFTwt|m;&xeJ)9k|S?q+5k zx4U`1qUsjp{ROWBW(^MgiQkF^@~_*jLtY{6KLsXLKM#r%Zn5;@OehA7kKHJE1@Z)Z z?hA{8AAo}Nqcq-o`gRdG6l{+qsBP#yO%)m+ynH^Hl!OatJSRT?bAT4BX*^?uX){1i z+^*|C`DG+PcU*?QZ*6%>8!>U_lNYv-t^N!?Q2(uH<8@uFGR`LR@fiEpRob`Ea)ZW^ zrJ;T##`g`bsw8;?JAVIOufAD9Vw@jP-AV_n3- z(BC%rw=MY+ih&N~e>y`a=muTLAvO zwD~&;ee^yi+Unh85>0x8Xb^q%K4zn&*Xe0Z7J00{+v3%oWQHJvEZ5fIVF3(s5Q7R} zXmV`}EyI$@i=b9d`_?v}8hwpuXAZItfXV1Un7o7-I}nnW*jHGn%VL*WrVRu~aBK#1 ztI~itKKNaw!ILQHh|9GN`+MkHqe$CtazV7EGX+fn1($R?DSv*~^gh+f$5}OT z^mkHD*7QXqQFCOZot8oZ+7T0}Q|&Jkd$yaJOpRv>HBQr9Vd+Fd>rawy@ z%k4uPLNxS;^ugV)4L0ZkaVixX_x)7a(-!m^#7jPFj zo%_F+x>Eanzbu-#o2l#}2Ejq@DdNFp4MDBZM6FQv_%Y|9vpt+iT!g0kQj>{+OQ?$I z8`KaS^gf_LdfKN!G?JBEOQ@}tZzStIZq~6N7>$ct!gNURMU@(}xjBlP{dX&!V1|;A zxLb*a8BS&hYQKZeGYhzj1LDYsN*+ zzc+!|m^gvhkT{;~unjHqt*wdSq06~jHSM%WPqc7@+Vlk_JoNLR2%;(UA09@#yOO)Q z#uj}co7j+QBubhxF^35mwuT|7py|&v`G@pI%|SYtK+X_mvR~X?kqbui5o>X{q)yw3OT9rfuY8(ifXwQj7cob1Mqh9rb}7e0>%{x z_&RCAuRGNMRzEUqyZDaE&q=u-T^^CfFN9aC$J10b5c6{{y>|2iHPU#I%`Zx8#m_dY z*Btq)gSQh>#AC99;<}pMKj<@X>M;Gkt{$39Vw|7W zl)OGP!|}AHOu5uv8{zrQ<>p^WPSk;Env?h93;Oo@>%+BiZcC~Q<^bg3`Z;hZ^eV8d zGCcET)mq>KYJIY&=s9x6$2HgQkb%5Et8i`P9m0%xq?3g$qqRY*3Hv_zmVZ zsUv8Lf5uR*@efKbW=ajE|^!b+pNy#CpXP+LorSA{#e zntP17_*gnKpP8Fq$lRNB7ajEp_v9FEB-7E7IoifdWX+ZDN71_mcZEjiKyDy3!V|5( z%i#M}=Uujc_#2twMkCv=nq;GvCafN-uCLZ7E3aAncdI2=C(+oXmSkw{x6%SicBmyh z_Rn+OtLCO^uF_(q(Y0QxRDjQ|R1c-P(l=@MkQ&J5m#H`A*0dE1kjQ)-Co9e3*F#Hx zsq(?{wCm?Fmeh`d!iK|w-^&k72i{I@Zmg-Z7S9@JiqYbSPFq4ClI59ZJzn~mHoswI zah6tgJY61r6U=OXpKCAOrlnEzWik{u$LA{IL02rQCfZyD`%^x>?SbatG~tuSt;l~* zYfzz>OuNWh)P@oK&-DLvqBl4g4WjiW7zZywGAWNv!oSHdp3IpDQ{feu12bV7iKdeI zGs*lHNy@RLBr_dSU@}QFfuzAkSoCIy1~%Hfgu~41bp}1Q(b7?LIKZi3FbIN3ZTgPsl~VG?xY^#qc+GZ^kUJLj6@J1W+%NXJQ|Dn!YplNeoF zi6~H=mT8`*`?(}JJ01 z(S{g~Rx05;x;uOWE1ltAQExcIw-Ezw$nI_((0p^ZB$2wfTT(_dVqUidh1e*s+b*SN z?tr+wj{B9=+~H`7b!1##i$%&zYigX6+0iL2Qj(!(guC$(fOe(=Dxg*nUUMm@0HJ$qI*q)_xAUoiY^m+ zghcm>7F)?wn-~c_f^CV^uEDmxXrq>WZ5cWc8nt|ysH?I4Oxr@x2`k#q6c$>D9hl3B zBnu`i4@^PVFkxlDb~M{p^JC%lFdba*{TSA8o4SM=#do>$z3L!ZG)=S+Iv?-Q;vipE zOsHR|(Q_)^r$EyliR+8=h@BHNxMJ}jVq!;Hlj>WeGS3OU1M~uTGf*$pc4(jvRTvr=NZcpH`Vf_U!d9O}#0yNg=;4P{ za>#usZGE2_Ma&VQX?y95v+iyw{K4I8+~OaU+OA)gU64P?z{Y4-^e3EZdHh>6p4Yj0 zpO*g`{*UIlWx4=tqtho}*I2z$g7eGNwpB@=6r84UP*ppOLb7_X@NPHN({$5;dn?v4~-=EPkM}5e)gT~9U z%)@qc6|lo%?nkx}sv7tXzL$7d)|T_pgKfeN!bx8?|FS%)+*VHGw>KOazUcM&n320u zb#8WGm=)jmYSrP{etp>m;Wz(w`Nxc8jsj^$s68LeZSI?)f4drF|sw0_x*{q4> zh)<8KOIsLEFFC=;k8i9~Z|=lp(5az1JmvKpis-8;da>Bp8{cV?$yV&Kc ziG4>d8q)(C$!&@0VXf_FG3}Wl%r6^rn=?Px4Cnf5PPEd`r`LRJqMiBtWHe7akPifa@S?`XELo4d!|bnX&V_<$M24RN{HySa<^2+aM| znDxw8GF+}=TCl688;9nibZD?PTWAx}0A^1Q<2~%^X*Xt6M}ZrJ%jxMl zcZGFRG(&K^uS>@EQR(ZFvCnyWx`#@APUa@KIZt8NkLn2S=77+L+gqrmF9@v*FWIqQth6OWLmvQ*Z=xYD@H=R4f6wSuHAkE z!dRV9YDDqZ5RT26;MpzKTqqC1ufkVH-^>Fa5qG90xAjJ?o%G!3@NHmlVm@m7QU4d< za5WzHvj$gpggmwnp1UoTkxV##?Vh>awoDsWyzAK$!B7yt79XgzMjv+x)_$6wU)Fyb zbrN7T?juW-BToYKXZ617Q3c??*t-|FD9XKY;J=xj-JOL6W??}<#Nnc%qAp@ZM!8%x zDl+hvcCi)BJSX1{ntAL7vp|ZM6fc!!odcGpM@x@cr_4I*H7YDJ^Ohx`k(nu`<(++h z&t;YcG3%V(^ZEZjpEE|^hhcVhcb=Jfo_Ve;Eh|{s1D^_y(a%rEE$0PUvbP6*RheGL zn&Eq={v@E;O<8)l>b1_JG1ufG;bm_&)M1#`ncn;QfjE7eSKrxR`y-$@Vl^a$L@d8yA1fnIqDx>$*i7E z`0w%`TS!KG3W%M_{5yGcjME{Q;Euw7q&H$N?U9(vXHU$by%cY!Jrsx2zYL)>`s4#? zvqj3Q1cOP!kVtD4C4-TyM#;#flEGv!lkzLUU|@Y1O-9^MFp;59Ng)>*Fjc_SM%JB? z^iw3ITL!aiFbc9nhCda}7F;WsO{9G53SWqx@^UMk5YS=}w-Yg>#m<*o_e;j&HLL{D z+WW(bQCDC-Bam9M!*-uW;(Dr6={I7L5lYbA72!fjHoCU6TX!jQMkV?)S~pIyQxEIf z?LTrGsFK{!)cMuA!-;Z3A@gWq?5lOJpst&Ufk&O`uhuOiK7l4P*CYpigsQ8k->R!7 zQeoAf(9?~?9Ovor+^Ix-zAN(i?ukGP)J=nTKjnTbq9c7S+06BTg-nx7)gobm*4hek zi$fJEzdh>ew@ZL4dX+`vXN5+a7)j1{bhlDf-6}QFodlALDxh)6Xc_UdBw>1sWBi@# za*s*=Lbr#md#+1Bd%I_;!Wiptv`TPUhxK*`R9Vp1XZ9!F!;HD-_1P%I-|1S3A?kNl@H3eBYI}ZYh2_y@!RjqmP@|<_l}v*d3|1FYb_rbY z(?rVD==JZUN~Aq$Al2j3;HS(qwo-zph*>dcokwg(w_K;8PCwnmO{i%sw}4pLqKhh+ z>SFTzG*E%qDbHg=n=WzB3V)SYrQ(pEwpc|u zB>Neo>rfgjYJn|gEr|2f23t%Mh-(~;VG6T@a+Z6J`yHCr*twN7zAIPlzIQ;QN=uF2 z{Pf%LeN;9t`{>uY#U;c$=&fSnjD+r~l1h8}6)S=7y`w68Bq{rg?;h?;OFtxUjQh;l zK)QbNWaDc={Ps~4XWej6t883n<0|{U7?kfsR{EX&^%-$bMip9D+NLcg= znirY|()S8E@?IZ4k9cup4Vn?pvD^ z4O=V{-M;pRl%`G~)7~79jQw_v8EByq9hJ^& z74xk0O1g7HVr)!!DeWy;=G=AbqF|O*4%!{wVQW(@Z4uYuLa5nVUPpKHvp4Y4u+wlC z3Fp=XzmN?zli7FQQ*`)CcKsFgYdG%+rmzEy=GR?(~xxw32kooc7Qs3)X1)qvN;zFERFMUe*sUfg7 zN24W91HS$`+_8@B>CM`6jS6r08`!+3R7qhy{g%F-IJ!w@GeBCr){>^1Lg?pAuiv|< zu12O!O8$J$4{MzQYaOB)k9j=L^P1c6pe>#dndUpzRv$X-nI~n_q;iu#DaF3JWK^p)3lJ_UK7R08nzoS}Mq5+HFPG{>ZAcWC3o1TAi2e1x2 zaOA?FvvhcM8mG9EKo(!;z0J*Z7({)Mc-Fa<;;+(0#=YT+|Eh`9Jkp03|I3Syr{?>M zS0Xiym_W?VPoU;z^h6^axnr0Uxlh#h919Rr*y0V`C~hb2OIZ?F3)8EE3T5A+)PqytNOHZll@gIZNzw2TdSxE zbwm*o8merG)cX9Zm?xoe4d3KpE+66!eUqmFF_$`lD7UhfTAI64OA;ZcbnpV*65@=} zC_s*RM2VP&8b_2E(gif4#TWs~jS{6_T5{n&grZtgU12mzEzBEBgw;)X-mJlUf;S3YvO2quJ>D zf|Khp5dVVa?iV2T7p$RH2iEMzhc{ubu3UpDTSv=2dCo{`&K$h5!h*Qg=X2&HU9Jr+ zM+I~yH7aK%w@Up5gFEHKQNx{as)Tl_i&L#2^hV<_zTZl$OJP=0*AZE~r3metifVGw zCP-CiI(uW?=ZheW4Lf?t+p$=0Js#97mcdCjNcG?kBVT}y?8I8Oe&2l%l}BG&9M&rx zEC!kmuG|=V2a%Q|C>P>!Cf>7nB_s0ksZV`t;5D3umB-J?cGi zUGqOMJd%WqdYpd;!*n!?Gv2Q+k$Wduy8QIhY+SFB@Lg~2`YQ{O8o<4egEN@E_PYxq z(|BWKm_8)_c3_2e@L10N^`On6cgGi(?z@|mk+Ngh#fzVozJa^viS57!kHz#?Zsrs2 zLFG#0SLALAbj;;|9G2d%-KGNC_K_8EdnZe0ciC(}y;Z5#z0F zKl@9N91=c$sncV6__O2DBr{2CbdpcdF)?ZQhfCeg1Ao*$2zH}bCwW^{aMle?9H_ zgKtrz4!(5)y*}#T&(u!n(>|A9fA4+NlzZM9|;gb8!NzLO{udsS-7RCDHnnU{zhj3}S?C zE;aGm!B1u6s;=Z~KOv4we(URP8M%&etEv5_PzO`@5I0`teqz6k>vvLLq}uH-tlv2_ zXAn0thB!oS&o|M6R))$2kqUFMvj5GUeXR{IM1GD2>;Cvc%MHBH&xqD&m53tSBoA9OIPx{^W%yRT@B>Y5Om zi&nZOhT{2%j^k$Id3tk9IX4Pb6S*%xm0^Aw=p9Jeqe7zm4P1&+iuO)lx&|P z&@%2T=;rO#vR7>AAglI@%{g6n3sc)NNJ8_pL%CEyOZ<#Hlna-++NPjF$+0+8cB7Gz zFQXHQ7G@PXft!QISxUtmjOREW?{U3ObPCq9>-WC|%Tin{Vb>yKw>%7N*5nO)tVejq zJ=zP-tc9`Ml=o}x12Qfi*cvVSykBZ*Y6jhB_{Bt1VIIq)jMx|( z>)`p79Y@V43fUkeFmTV_=L&fqrJ`uxaJ}rk*wAG_opT~BJ9}>7&QVUyL)Tx|XkOrC z9}S+F6R=0)BfF1!E2^``^D)-uy``8pr5|+q9g#J_XAt_?t6t<;EZpZ0qrkwnd3sXB zPD~r=Tg%=AGG;z4{BS2lYzK*r2sQ8Vq+KAfH=Z%9@pe-BO2S*}zkX29gP!+(Sp>3` z)*csI4!sYNbQ6%gDyhqLk?`yXzs(0;`1J6fI`q;j8v?xzrF!_!_jGcA%HC_hS6@5> zDtqJbi>e7KS+CSJ+bxInJZSEY=xA`V@qCNo_io@tb8zIsfoY&Epuc48`|?@PKBLET z`1`_3z{?GXZZf{8_k{fHxT%SE8im~_lYRuqq%(ZqUK1D1=Dr~N+54=%{rKktm+5)X zzpm_y`Be5qS<k5BK@OO4idCzrH>EFzB;KgGwTr9=KWK zJJ;%A((GzE7}T2}69&@S!`o@S;b8i2D2DPNpVlP~hMQpktxp^V+4OIN;a0v~J_w>g zBr_k9_U~po^r_KI*3gA!yvSIlq?S+?jiP{gG?7#-()vS_fmI=rnnpn~u<=d>iI0zJ z6b-=w8G^uUHdt_$<=g+MWe%)r=8b(t*%4p4%10I5n9rQ?M(T!!>C#5x6Sa4|NeM z&@y5Px&Ym5c9n(7Qz|xxxXOmeQ$E`qQpasVU5BXA#M-hEcXl&;7=q4Y)}X_P zA6IC@cA_87*QO9R&9C6jpR#k)m;?3mqoyoiKDiD(IX~)umb&9&n$SvjTw3A$s9sbX zQFTyfswstn&+b%UI*8>&83ih!D#&rDO(o;t%RU7@F8;sYre42@Ae3LZek$CGHZJlh zV?ysVFA|9^^ML>h^@!KJBsX7(z8%G^19Rpu5q$k-D0j?DHZu5lu%W_i18= zO0O*1&e16!)*y=^EIFSYT9R_4L7E$*k^7KlP?GlZbEL_v@pXc@+~ z!iBctJxXd3=mc_9=N04nfS?9I&#BS@gF1^?L+rs7r)HxyLMvT9-Qv`(H64g|Zq*`O zTiwv1#b=#p2seo7)U|Ad)_Qy{a%NLsbY^dAQA44&#d3I2ft}Pa7*RV@hH_%L4ApI% zK-5|}wL(iG7F}-l78f#I3*n|kR297*P3cX2j+g?jc`3=%IVnjJKDKj3m6@Ommn%yU zM#Kv)ER|^F_JU9}m1%9UJ2eayQ4zYUVzD4&{JBuzlK3nH=45!1dk>3eJ-&VMK5MMK z)+jjXm0f?15*Kx~2{t&zeniIFOai9bco?#BCSKb33Goy0$Xxb+=dD^(_nFs^}Xx< z#8N)Z9KR`bEbHBR$-B4MU}M{KJl8?qZY`iq=ZX@0^}oqnK+3c= z)GLa%RQ&K;<%i(u?0u&VKi3!UhwQ@gcEQYslRk?-+2_LBdOOa?ZmwHz1&!|ivD}lX zR^G;AY?YcgN7m@}j}DGWt&!O_XS{o#vL#E88z<#&GARJjTRb^>2R|8)LthJ z1v~h6AMn-1a7Q<`{q)+*PKgD@(NOK`;j7LX}ZK{K3+5RQ1GP`jd z3I3s?`c-udd)tzfvmdC1ELS`Hy>DV&{QNm_>F{G7{@n4zjrDJN=CHi$&Aaw3_V9e* zBjeBYaq`br9DXj{$w$ZFOFQW$*)`cG8H&X1Z>8+ydWeQfc`NB@Y;MPu)Bsd!QANSu z=zC3~TwXi4EOUyHxiqAkL-@_CD!-P-aD=L$T&|l+9R@+kM>mJJfgJs(FEon`~_)m_XJ2l z7k7^%LS&q-0Hoo8qALhsAYu%OP8L&by<&|1PK(Mf<9I*G-k0V%iE6_EXSo5Rj~n0c zm2(dF6Jq06&f}QhXT}*@DW)((Q_NktiH&=KDCr*NZruyxLsLwbDecw9i#|o8bhe}` zH$Fb4BnVB2ca#JH(N3I&E`1u#u1bx!uX|e7ty_a`cv@~)lUiVZdnQ#v3)ZA&mc2bQ zvf#ax%;{&JM{U`}`1h1tZVeh0f1^_KQQ=;0ZIsx`Jf_R1O$=A6KXT^Tzz$4_O6vQo z%bDdUIp*auE9-2L-HJ6{hM;@ZrDs29jo53kM*SZ&0E0k$zY)+1t!FYbft#8Pa}58p zR_jZ3XnljFIf2~Sw>#XEgQfD>*$x4fsR2Y)7!qKTXAf#6%pMdcj6i4V4v7~i}upYN+ypdNp-b2QI8 zJ`*+K^~67Fp6;pWW11%pl~5Hm=}y%)wKxpKYtb;On+caIv{GoJ&4~t3^H7;-M={0& zBnx$xWJw{GGu3jiIGove-ODv}D-in;7i--ww?sM4#_iu8A(z zt1#m8joNhf2vux9mJU5x;govjn*a!8ubuSB#biCa{u4_hSO(Fuj#JIy7r;D|{w4gP zIvw&^I-9f8x)`^ob(wp9yf_&Ku-DF=`teXmU}<8pJtkeRPyOhK@(@I^E8^X~T_->% zg%;Kny!^whf0XzQ1hcZBzke7s4){!ukKEt11~O@rAxLZ7u|Tg+1@AFmU8(b{ zfN(vW_D$phunM%y%HaLVt*`&|SbY=7?8VBZBSv6@cVK#b`dVNEeL&s^2_5yatovU) zvrONn7~%(jGM;8FG&t!2#YMwpc5YZ}3u5aNeCsucaO!1W7H_Bl!}Rz+Jt<^}UdA=* zt*)Ih%=0s(1r`gg*bp-YJmYAu$TQy1OW>SIkJSUu1#|@`Yr}M^S$smDo$~p`4Wqy* zRg&z0xuDxTo)vx#@L8|79Xd4;c)4i9 zxzB$F9${K=b*3IJd{kPcPk2!rWq6k~%_QNk&vbi4FMpf#$o|#(HieG`tkTQY&U+(^ z0Jgi>_a)WWdPKT@rG;g!opco+=BD~&S5VkftyIG1wP%GAMvI;+?4oX9YXi8mm=UuA z$v3Jnm3O3?nYHHfDDL&dAt*T+MwrXfh@;V9e?xrIK{ks5b!A6yE@=$-kOio{QSt!P zI|&Ngb%j(&YD~LbZXWdr(~Odn*Qo1Z3LeSH1fPn(TFd0q?FoMV#zksZg%<`Z8Ewp` zDn2JsZOWs+(d)Tv6d>Lt6TgG5LeJbQ3%^d0&fyJqpQ0`urU>21H0l0GTx8&yO+S(k zxM+sy6uHsQ;nsX=xf`%)n`1OSl+x+Zv*s`xBEp*@#!xS7ZNbH5lPE5Zmf&7>m#*4 zzc^$+@F6+R;q$(po=h&Zy@n?PJx!HM@kZK_2FT1X#};Flrir)g3?gqzYqUSXJeVFX zSbF*u;N!^Lwcblk1Dg2Fd-OP&<(THXdL6gSC6P|TPh5B5AD}0A-Ujl2`gtC?KfaG1 zUa{eyWAyNVuj9xJ74&;Oo*hYM37|QVSKhdEpT7Q7^R6clQZEIzOI^r&(!9r6ZwP67 zl*f)wN3spgG*mp9xC?k=s0j;tb<@M@nXUnP7`&IrF>|tTxG!8B{UfIJtX!zryytyA zJUuU-%sj2Zf0uuGAya+d45FHfnds{v9j?byW*}t24UmQh|0Y~_3;w$q*Jk5S24rIR zCfwp?+;RZ^)*rnAe+))RG8&AePR~rb2#N+-lE^fOX2~cT0|NsMhCsSLFff4rCK*g7 z107Y~C>o3wk-W-iz3S)v*O%4>Arfz?Es-2VIjP}gTESKciXdoJ$pO_Rt{46mbAcGm5 zm8{)`zCi7Q%GJ!A>d~Kd5#Kjdqt}S9LDq$E)L-HkJFjGLGm6^5{4P2qMKozI~Tu~RO?1sfl zB7MT;{+6W@f5=lFQzc4Q)a`;Q5bSZ!xs;P=_dREcySsb+jqtN7jflgV8+Hgn~~~yNdoEp<1NNoLyu% zX0nvkeM}s%wfiMywn6X4pqO}h(?L_v21NT>?K zNbTIUfWj~OTNZgL+pj#;#hpfs^HUoJ*+kDU*iOwxt;5jB?QtQ)rq!bLA_-izcX{MUE!QERa1zR3KEmWC0K26R;XSZ*_?D3Ik85%_lL<8E_ z764R%>7rV=!UAGXT}@a(#>=}_6Lte$`hE^;(Qvtdf`OeclAwi3nGZNw{zWrcGD1{Z zgapNM;!WN0)4Mj z&G8pTE8XaO-Lv+1+;)vMQmk4XF#2cy*|gX%vKu|@v#s3t{g|nIeNobv?^t?CVnNziX*|#SSk9S#5W+@Te=N6iDu(F@ zQBz0DYxVYDTIW97APD#|j59z`g@!QEzO7DL)+b`^F(cZ?Gs~FkFsNYFT8-MHhn)x60YK!_i`NheG$-vX}2WNZ9NLw_G z7+ckYL@~YXK0B{&q#k~HvNS{wU+^Z75j|&`J87wIGO>}e=zv)UI#j$_pvq=J#tq2MM9E^p z9U5^9fizgBTak_ExLagYEwXDevkz^wE((IlESdv;kHaJKoRn?=AMA~*27ogF?g*6qx!@hPDLoHZfRJZcc}Mo&$UooTVpn^yIR zc1*DEh(uSTQEoIY9Gyhm7Bzp8w$bNspSFeh#7(vZ`PzmSGi(d;v<+4F5`hV@!QI+- z-Ct$cBB(aO&n51cs2w*^r6|;Z+E8-@B-=9nqL^c005t{%C>if7W~-l0RMyqd*INnB zzv%)q9!x}13omP(xk2=n-lB!w;%UPw5@Eu>omHT_%ZaV9aj~BzP_k*UYwX!lv|Jr?7N4v<<&e?zvP2Y`s+g0i z@Y%jxqJl;=5iMc5%S?i(87*O5&=RA}wT4|2VIdlbA~Dn=W}^LuSVA+yts>RlqJ88o zs3h9Y-V%|i*hPg2%Gui^3Zm^&wF4DeG;&E4wW$1>Hhc{?C@~-PQMP(ow13o7$#xRE``MA`$aV%Q_D{O2qn&|~ z_Q6abLSQruR#8JV1pAvsj2{gd(O^~Mqah;zpY>2@u%89gMCW*PE+l%!cl7C*D_rg% zs>3r#0M7?Pif6l@+uBvpzCpJVvszovEF+dtZCW`xCd&rppc^TT$@Djd+esR;S)i&7 zK`HGoFw3YBYAu7hZ+d==H08;OUAoo$s3X^`$=#aZSE!sDtmI+e>(hhSnVM)V;_8W{9=>WrMgIX&cx62J2+Sy z>Mu@yKY73;V;u>L-hJ8)2KLnNPTD^AIn8z1(%L{f(cxjR08K@>8{tbugw z2oVZs@xfcQ(Tz3y$>ox_o3|gow%pwu+pTj2`o;1-urIOBfu~4V3yR!q)mWa{;631$ zH1{?VPH%_`ORr-cB#YGO{#MpR8^*lSGeKg-IdIV%T{Ml4v+>4`kMFPM1s>MsLy~M} z#Uw{BHk?c1k2aFGt57{dpkqP2|7G-12OrDpA3OVetAIq~BEZ{dP$sZAojdi|=XyWU zfxCNkaKN~}B)sN>^Wz*%EYH7j-#347ux^;5=;{&7msadQI{;Ey21uB27$-BSAV`bweyt}7yf=6RdiA4!r z`+MfFvc7)bMcX`)?0t(ncD=!4Wz!E9CEEIXcJ=bKQ zR&-2TOHq}$siRdL7LG<)ReQvk(hM81o+_aO(ZmtNpvuG%hf0n4LG?s)e$dIp5e-XP z3_01Q#k zfn1Oveu_*wnU-mpBlgS)aaYrX!vkayPs9V1hdxjA=@Wdr-wuMXvZx>^WDO95B6wg> zqM{*rb@udhCIMD=-ETjdFZ`-BaBF#$c6Xb7F5VIf`Q??K$BW7YQOUBeAb|%aEgk-DSX@ays8f1`Q zu*!`p>J3(ai1uD8q_klI_KRJGfbnM>c3Ke-QEYZQq+LY^rd+MihBzNG?=A<}6qB0} z$K-3dWE0qhxmnkW_#CD=|G5RaR;$BoykLQDzg1^87PRPYu%<%lbu$6xqT!&>Jm~Tq z#1z8c#8Z~07Ue7&30^H7T9oqu9_l;h5Vg--NV9Xoaj-GpsO!(n^Sy z>0e3!h+rJ14UEEsT|fd^&hJCEf6jng+c^A}4AZr7z~O`3p=K_jhtjPu9Wa(#5HHb} z8z8d_^~sb81`aU?(ypc+QCIjRB&yAh$r?hZwHS-Ys1zZwXgt@1A?9nzr3D zFv0E_oLsU6@lF{iv@4ui3c1h@Zr(=u7UiNl0a!Q*Q3n=s)(B-d^x~}iA~_DRZjl^s zHE>oNqQz{r$(YL-$3Ui~n0I0(n)i&60i{mOHpC)GSZ-C9Fb;#fZTuIn+esGz#{)<1 z58r9VUm^MZRr_BH>&W{`i>uBn59>*%GVWN`vM^m;JlM>r{QLB9_dGBKQLk)d!PNs-lW^vV&$n`8`|Rw zKN_jrJ~|7`m(hMtprx>28_q=mdaX&ldy_}(JQP&8^5_sP}k>0C~s!jv0TcWbcyC z*l2wmfb+@m>EXy z=l*;O&I|V88~1tl2Td#t*NdL_l6!T$=YpS@+uwZjS@uSa=+;A@?C886R`+(~U&>VUCt$YhF;qNI!X`uu;RhXr|esX{D^D44)~% zFH5;k$^4TKJ7sua8YuG^cM!Uc{koA9@kNsP8=n$M6r`un4^ z<{7_15S#Ws1Th(Ar06qu(P$kURwhho-f!ufT+3&GOg0Io%Yr9&GxxpCU^<{3;i=ws^z}SEY47RnKyG}2SN{6# zr_6n-cVshj$Mxp31?zLixuf3$ZHSc#(Eg&MKtB982JaU-2JbX_KHWQ%{JQ`YU>W*D z`;QhV5){f{HKrsd>5UenJ~dSrXEnuh2BXpRi*?HOeps?a#@w-IeiXk{xabV|7GYaI z+(-C4$J?FEF$T-;tdV|&)pB_MRQebUcT~L%9;JJ_B6caENS{# zylN$R&$4I#9cM|hNAv*=x0VxbDIx7^;Tcjck-YOu3K}?X&c4vmPh*(bY*G>6Y$6zuAN1q)|O_U?DkoMd!6~vJM;0 z`|e8Hn*fOW4^3azviE13hZS65(33%Tckk#P%fdK(BbIsx?_!ACGc-g(_lUn}WGUmt8D?nl?0xE@&c;1}3?dPl=C z8HbJjvRj7iX6qMA{a;LD?!{Awyu;irg~PTncP~s2bmMRQEV%ruGA7seqEFd0J`2tr z|MrI${yBi&HX4q@&IhBxILHEU5#Hq;jmh%xp6=t|c?3H?1h-Aopy#uaMIdT9OeTT5n0N1Z^Kbblj4BaCzII zhq^442iN!I6NH~Jj$r&0u^Vz})xiyfdpC4HtC<)_fN4y z-cZq5X5aY9;v32^ADn6KoC-FsCH!y7qpJzuwmm-6{0-uxm}QWOgtZBn!%Gx?dmPb) zSizW$_%f&>w3X)eVO@l4`Y=8>lagb!C46hM#m8|ruG41IBd$jTHm(p7%^Pii5U5DX z%J%b$T>X(B6yqc~MQ!PqR>LGtwzY89g)_N(ZFf(yu7m7cQbxF{torawZWm^on&Py> zZI)dpVzC?Z{lh0PHy=KcH1)(v$XAV1yM|)kjM%Xjb6ZE=M8u~d16@O#5HIO6pM3gr z%ngXSU1jT^{yfKl_+Ovr6z3j?Jd(4SF$XfgFFSHhmc5dHlrZmT&XbJ#*0Q3!qq(n` zTD{{hJem7S@<$3sK^9?N7NLc((DJvjqs9=LIEC4e7n-<>A-7*>;4ao#E&4nIXH^I+ zfRF=*7(Cn0G3hdfoAQ$2`5D6vh{lZJO9?Y~llq}O(>OS@EkC6$(=gK7 zmYrC~8D?4A_y{d3?&A|(m<~wOcE}|`!n+Z{K1a(5h5EnRswu6GgMz@}|{<^H+nG2*Gs<+rf&R_dN|e0ZO(oevQx!O$n^?~V{)~^xNOd*KeQURXK;wLYmjZTnGkhq0!Dy| zp1UZ7^+6BIJ#_$@81oP_R5U{N=7K+@kaedu&!3#dUctNRp7=3isr$#?*4uxZvIVaw zPu$!75c{}D^N{vG(k-aKpzi&P_4HE`^-ulnDb`hNKk|)l6s?pp*WtK@E^$rX35HIf zAG~Q9*IN3fOym_iMrHk;zP#I<+WIFhg)B|B{N}4k>>GSfJoCd1^f3;Yw)wM1GpW28 zwEnr!_9Z@d;|B#t8tc9wztZc?2aR<{@e{?mXHMl<>0bD6e|FNhvz_F)Y*)w1cDjx? z{N%wq!(rmSZT$Y%!(s9}$94aEQM)YD_2Z78(qWRZ+}}L1K&HQWY??Nt2+;lGuibd; z3HE$bYRni54JiJ(j;|%P05)TsXc-(*_Oj~iY5g52B!=74lN$$?lQc-u(HGb=$I?BA z9tQ1XG1}fXdJw3ahtsg&vW_x9_sdM|IS2>uL+g;cHhgLXAU{I{0q@vx$~t^6T8|*^ znd`sHX6`+my*IOte(v=hFQcz;;qrR#&`JRC2id_>FCCf1*6rJW_&&tk)Bn`*IG_(u z@16hcbO0{Zk$mO-$e#T@`QlD^F8L9rJmhdObmQ=IZ!n{GweW>s+j-#1{@VoTu#bLGnd@gXwW<-P)qHi{g#91!Rb_bDe zs76QQiUi2i1gM?ite7w{qDMn(N4;MXXNx}G|;o*Fhq@3z>~4MDG(5SVgv82DJw@; zMH+|4A@TKM6OZ!8VZj7G807Ki&yCnW$&Wn=*i*s#ZuNV4{HTnaU*UK2J{}hoN{Peg z;yr@1!te8=VRIZ7iApj0Zh~p5^0>;yMl3{OPzsdGNh0r2;zAzh1P|XZN6%6~L@@VA zk{TsZ6@x`lMBn@g)uqm2_bo!mBh*XcEjS5-V#t*%Br>HxB#8pP5!Pst64XrP6Fp*3 z;OJdf1bu>)dU&@VsDfcZpJ3BOKe>I$YJn0ggG#5vg7v!uXHAfY1t7VUGk9T+H#Ely z3zhfH=4cI#ma_K2(L!R{5`Qq{1sY*#$Rm1{+dzer1m5KleF9363Cn%6Jv@pJz0NX0 z3B1GOr#LeYqH)S$%*g5zM;P#b_5mslr98JMj80^sObO)lmG9$51N z?yDt!-aIS4XtCf6hNLEEO@rI-_tg9SbDZVuqOo+!MQsBGP+7KN{e_EIx2*nxDCtLq zR_sPCBfznQd;DS`h?*}lFU0g)XaP$|r{ z&~~B{;WN?w91=rLGnJxTGNLA$Bz6r+aEU=@F>L7uDk>3f;;#uQt;-rMQWBgQL#}R3 zgEabLzt1K30;DI->QAXepEF`Ty)7K zXv!`|5LK#1^dBK|C5P!6nJRzDDwQTq3C$UBj*P_Hh^scT?UQ&i;N`Ge;=MenSSUku zE`p*dt9F$7VWVqM3E*T7_WvBsBNS9ef-p%WOd^p?FN*|1H@nQ+$TtM_w0wv!V&K>i zcQWslLU^WO)ZAH;c$C;lc?)~E1I5OsWRl^!L^E>fu&|421I-n&Q zQTgZiC63-FMGEg!5LP8XtCb?Z8X7({1naASEr2Nos}&UjOfa05!7&h-x+FzuLw--6 z)FL4n%W>?kM5(G_p8F)AMijho=-Y@+Nr_T4!4aaDRs1Q?{EE&gwrTCk&UfYhUU2g2T>2u(H|^(k2qUk z#YeqSJ)c^pS^!E`sUk~2Ml21u@egjXM}V{4h$l$ao=^c)h;VeH%r{Wlp_^~?D`^SM z35w22UXuKCnMF~{ltiM_D`{V6!tU8_Qkk(vY!DQUU*ZEIv+%?hW#LsKP0LklR5djz zqKa;=RH&-JsA#K-r#T(YT1l)A1qEoxy-K;6sdj?1Cg@_fsH#!$)iinQ{T?>Qt_lQU z#BP?MYMAZN9M&F*Pq{DXj#mpoNomB@ZXp;zHo@(zs#Q+%qfUb_DlEhst{}5nE%_Uu zIe>;WGHXXAQVl1|0Y0*bixM=AZ$PKBdrG~|xrG|d|@-9J-`{Qr;t<99ut-kt69`t18TqhCdbV#4^zlk6rHEoR4# zMhuvJ+G*f~AtNn5rE|J$ihiNTgc0LzmPRw?lzyv9ixC5djFV)?!Guwi4>kXFZ{2Bf z|ErPx#tfP;QVKAi)caiexlRLzpzl3Ka(VY|mrw4mCV%w1v@=}>YF*d~QuJfbnd&Fg z1*0a?UG6>-4W@K%x(^&ZaNHGBjcgEe(%f%VCyo2`Q|7FqPIWPNS?HW`pIx1sFmO=8 zMU3vL=N6?1CLv0htMww{b_S2AKR#!UF6@p*HbR_TJXx=M}WFU4wAx$u@4MU@&8 zh7OvH0zHXm8Y@`Nnda>-xDeCeRkB_;@|qS$J-S|pC&rD|VzZ<4jZG)@G`ghND={gQ zdBF|l=@Rp`j+Ty(7SBD#4DEvK#`T>PZ8_T|=DbFavBv5}YRs|jV_II+mn)pcp&orI zxMN2Sn=o+nq{$OH4IDlhquqfSTy$_{^yCRc`d>G6kaX31Xp3Na$FOHd_EQ3vU7WCt zEqe|f!wr?RhCPQ)7=lycB|bFO4zcGfy%)J;q@z~et{Ye|XyD{AjoMK_GB}Fhanzl| zCnj(fx^C#$YbOsJd;Q4%y@!tN-+rjR)^^>^1w*6`(f)0jbr^`sVS+@#AU)Q#@C~N< zb5A4B1!uexV&uJo$x}v3`#3~WL^~KhaKiAB`hlz>X$K=@=}7b7$ngV*%LVPdPdZ4m^gXD?4ZCX(6>964dw$e{&8F1&Q5 zHWf5(>=56Dm)Z|4m@;(I$iV|Ub{DmH_QF+z$Bi8tdy-~r#!ehJw)@bjlgw_Z!9Vg3 z2D!11s8P?r(L=8qJ8ay9F#`)ac1P@}tHwxU>^SpTEi-jS-!0Z1&8z4{x8@GEHDbD; ztAw%jI1IJNO+tgAU(^aTO7jGiMsu2IB3)5O#EMYIanQK2=AdaAx% zX&^uBz>fovbbicsA8^O5|eYZpkE-D9+Q1yPFKF5 z3W~Xy5t~!^yj0h{$Eo_zq@%X#^X{_$r+?aPQM80#BEQ`rHi_SoDsSVj&Di8?Nav$; zOdh5qttC(9>&g6FoauQvpT=L>bMl{uvhzy`iTu}-%F!Qn*Y6kql;`6V`IGMKzFbe? z&*3@w?+$5UB6rOC*5ef2{qpP{zp2db$Jx$CW8Ihg#jzM3WXCF}0Sx?hgNU5@pw`BL0XvRpUva}vi3`TKO#oS(!>esfszyAe)v zdWl|1<;Y0Kq*CwGu9a3E#UJI_o$`A8Njk)Fd`k(G_sQZoejR+>VG37*CI35AC8@=u z!xS&c9L}=JqeCx`Hol(3=N+c!Y2+M$oENkinkR-W8IfKQ55l5djr_@i`8<#J=>D|7ym_=~f+AFs!E@z15`?v`F29qhj|dU=dDxfjR&OuQh! zi$CH`$K}f?XNG=CsrQvu7VVtp>|EBI>_^F24%?|Hh2ftlh2eCR(oo`5+QQS(*yoI} zlg-fcLNdEg?qwjh$o>e~ zXkTP8`Pr`7hmOu1hjGA0=`={)^+o z$WQbur{^1UemBB-&g5>2<$6g!$+PRIdM%^nQ?(#iN{RbbKx<^@*gJ z#Nm0i(ms+qmGpWugWWyOaea#O?om_RI62OfIBb%ailRqNX`8B-6}n!*cFa^3jl5FM z{@@Bb{!(r$hHkHLBOIb{?l*I~qIR4^1chr=p5-epgj<3t{$*A}%&Sut4=lGI5 zEoD*q#}qCjMbB|r{D=K<#*{7ze0(}erTb*GyybcNIrVnW+-{ZE(^={|iI>w{)+PPR zaeUg?|K~ZLBweFi7R~XJ!09N@iT}kv(jLpP{1sApUeY0vuOHFNqPc%pj&+Ro-yDzD zvgowbc_savmb%6Iv;DvLE3F=I^51!NaINL!PoUfRINs8KkXpKkLzJlZ-|YNcBD-TA zA5`PNcbUQUfP-}s^>L9{c|L=!^n>VF+7P*J=sGO^N;A19wQ_>qKPQ{U_c?6laaDrt zK-BEM)8yYoJ^vSReI|b|H__yeDm*T*_P;7x#y@s`K2f*izl!|4q)R(nd%m7vx?kLh z*ZYMwTdcpFmiTb$tyJ;(+o`9M({%lORKhL&baB^VI_crYsQXU^Y=x__N~zd4+Ci@Q!sJeTxKusmn|l~xvI3?ySqNlQsH z8QU0hDpYr!i<-wQ33{6+ZLvHjV|1sW3cjif04?}ndli)KlHDtd44WIPlI@N@0{L((tUA!-NybrsIH%ip5ih|?wnk5;&PIz&{ixGimQQo|B|LFFPa^GC9krEIyI$TF zd%xih-CY!wetClF`SW@_in}(`^G05z_=~%s&M3$3So=w5Oyef~<3Uk#-Ic7zu(>Q7 z%BM~7VCPyz{BwqN<2XM#EO|dwPhUF!dsOBsB!8A;|DNagH`moh_{&?4&FNRt&u;1O zTYsgMMX86ZbMMip)Mw_ow&Q&McvRXExlihUNelC_^l8pSGdLwq@EFrt7R_^Zl84T6 z-{?g2q-Bgr&q>}+;8Jo_pSv@ML+Y)wJWmtV%dE7olr|@$hdED3nMmU2Bp%9fcusIx zlu(~$e;j8k?T)!#J!_daI>!D#%X#@sROVr%?@Ru!YpcutApaCalPvDieHHn+1WP>1 z-0nY78O7U7&&w}KuZzujQ2HO|xva$LWzp>aM7=JS^pvq;In#No`{y~_;!d(Y)~EZ< zMJ2zI|I;jGF)zljcS{l>1PsVXoxPP9Z&(KI8BY~f*Zo03cWgJnH-Ob~#b$7Pq^8H!tuDQRT zrdt{J&~@qWXXxY1H1@xXubao6#&{#c+_~$?nOxts0+~@kW{{KC0>AlktqX z?8rDm{MClTTiuez9c=lg<2+kOjt>bpJ>Qi6&HeN`${W|Qf6fC zA(J)j`dp2ydr+K7pGEpsXSklsV0Y5=JYt^XslsU%w9()7ZO38FzbeBWlGQL94`_-MxJb^?9piP zbCD7s)hu~S;yaVwtI7V7KEB*<_`9O%zFaPgM!MQe?q}$8WM+R$xcs)p$`)cjJznW#t{ghS~t8kju<~YgaII6<7BCj`O*p6^I z9N@fug6(0>!xWZk9G8-(9enKK>y0@ry7Kwv`dr1qXzcx&ybh7c`tf{h=le2khm@^u z+sF0{=LPi_rZAR2!~U0EiX10$8tmb4#@k|bjPM`eGPTbXA2RM0eVK=C$?;dwwksMN zo;G@2V;(m)=lhK`bn$(MIUWwOyG_}Dr`SCyi^n)#%;OeW_mT8!%;Br9r>D$!Q+shB zTGIULL5>e|Sr>P!^Z6_e*ZJu8rg&<}?S2)$p3l#<)9Z=@?9Y8B|5xO6Nn>}s9L_XO zf2s5A98Z4RdDHW~^nTVEe$L79N6%;J`RfGx_l(KkMtYnn^|+*;m-9tQ*GnslSsXX{ z9Jh_xuUULtljB1C;^1Q`GYR^A(r2)7TGMewjtdvZk(=YPH{TcJ`xx;Ieg$ z&r_ar@_ku+zAopP+Isu6kLw7^V|DfRnSRoTsAk*GdCI~5r?hIw`ZYPN)A+tDJ?}}H z9yR5qR-BeuoE8oBvPgZ`OxBlpZ)2&4bNN2WyA|1;mfXJ7WcQ_yDtR@-GH;uq=XJUs z*6TVMOGqD<+&vsEzP^_{nrA7C91N7vG>%`HSKVidCn<}Pzr38D9XTc>ezVvbd0y&1 zawn{}&u6%7O5gh!*X8E%UT^MuN?VY|$C7_@_54adsl&4@;k4F4t}@mzqXlueR}hl}z!GVcA1ih37ZK-DG`@ zm%>w3?KjspW?Sbg(uzIK&~+$06*zuU_Ov(m3eEMzTPTpJ+dcA)|AZdTi*>h&;F9N11VQB z4{Fo>5pQ~~yzX*5>zrhF%=abg;gvm8vcFE&#?EtJmD&Z_BO7Nkm)jJZb>33yOIepR z@41!vekr%2n`9~Par#L)#{LFpg zILlh2)a%AxX>vDJ-?ML?S2yx8{Z2&9d%KPLHjdqq>*hUB7uGKq*B`Lfzt-QsDT~Jb zcv)AI{afZWewovkJQ=U&SsPo)6S6Nbf#Xv4x|-Ma<1A&tC?oVsxS%YW*GDA}6zS`z zvIZgkHm|oOl%OLDalFSg-f~}pURFi7$W#{3S>h*E-|u7H-)1d~l6OVN9A9!ilgna) zJ~pzx?;)`$@oUb5(pO8+bF0nty!_JjzD`MH(Oj1rdm&^$sl5MUE{lnJd>dsj)_tQa z%Kfsgo@#Pe`ij;)3Q2lhL%$zn7mizO28}%A%C5Bt7lT z`-+TxJLY{y$D`)`Nk+de&SZ^ux@13$>}{2GO4;9k%+&rS>h4J1ro4QL=gMR+s?22+ z@j7f0kE8$5*Mns*Y68c-xJT=q#=8?TCq;RDU-VaH&qT#v<~4pg=FRiAr#O5?ydGKoO9BSPjL9tZ00&sQsY!q_URN~ z-)C^%Pq5@sV-Ky=;j-?0lKTVaIUdThzol%Ep6q_I<}Y#ooE|Td4^MGEF_$T0{AO-f zGdUe39)F9P^OIOvCpY#AeL&gYW9;!uFrAmRW7&sP-g4b2 ziwUOd@_tsF-Y%Zx`tFpaEXwZR-ES|rhEEci9;#f!OC@CxC zepN1u=c3{tYhEUIPDW+UM*6a{e@F6S>18op&->=~J4r7?Qn%6ZX|6jYKc(n-SJG4Z zuI9Zq);$JN7HztJk8?he_FURU*>7tui?UuIdn67D^QIDy z2cy+Y;gEQYx8y(T{)t43yJgKM80lF0zPHlfNjASfBw>|2YqPYAHj8yw^5%tQlCEd! zX=2X%4n1ugC0KLX8@kpt0DH{U*f=)tg)sVAX8$>KcckBNko#5UJZU^9_ZRUPq#Em+ z=fdQ?!?M0>-N$C(Vbamz6}lPLVxK=J%M4evP~@cD~fIXw6&J z{9?EGSIT4+eLq{8<$iNrFYmS+x;E2u)^st#FLjl9ZKk4ro%GH`CEuC-n_#IstlwF% zzJrly=?9kdb6EUi{gqZ0rTt3dI5753ieGIU$CS4Fxwm#GD)o!BNAeCuyy^LPJrAUD z+{k_*SgWxpg%`m9^^75b91M-EZX(m zM<+OZwfTDSW${#0%7*MEGWW$~-`$?5q(|}XqS5}C+eO*QYoxQxjqZ-d#*ggJH`ew^ zx29g_NgZYN|6bE|xxc1frGLF*o-eN-+f4qE zd3^DQv0sLM67Q)O^pRwrhdErSyw5`1&$87r>B{}$j>M0wHOYE&vc7hf!0t*JH2X__ z4t+dlo~M=-H|zV|#`<}@$=^wOdQx~R@jfBrT}boXX*oT#&TdjR((LKlGKlx^p>Z#F&e$o?z}SDfx& z^E#`ni%WQA&w(7vuRQxZe4TeZmGA$@aqL-1WJ@K4l;&`0fU`dE>g0)fok~lk;^YL_y-vM_(}K2vQsaB!iQBjbt)C^^w=nt81heHD z^n%R9mw+w5`3+yAgleM^3s`&=#BwD`&dwH6%2UOU1MJ_3kGt+_*!ECHBk`s9n=f51 zI1}s5!0K5sZ03^3M;V2J7QynKgRJntMK|TlgzFqFi3R%YyY-f0>Cc<27*sc_OL=-& z7!kO0F}m-QtsRm*H&f^rRd4d>wdK_2i!JwWtfa=VEGE5_Bc4;gi6`#* zpI;B?31mZO`EVIcH|-UrimyT~hPRy0vvV*C6vNe#%~*vJX$|hu#hHsXAWO5_6A_`E z)*Esco4M~So5!CS(4O;-uY+!C^0qF+wCsqU08abbQ?-*L;Lbkf`$}GqV*iqtslwTV z!6)$=+ludfkje#;VW7?6Qftpwkc{ZJ_K6xU#%*Iyb7n2}C!R)a&(#dVq?%243Xn-P zLyCFND>SN$%xd1Oo#F6vEbyr6>+d;_*ci^KeJ?cFo|t-NMB-TjEtc)t{OOFi`r0Y*-r&Qzp(cm-9$hJw%-IS0iGwe3FJQ$6pNy~*)-yHpcOh?Qy52e! z;3b=9^+c`Aa`teqFYlU7#HKy>;2q|_fDZB@sQJ_(Z!fM#<2&M9&kMuJHSnxndZKK? zpfPq!qqP$WijU%)ih8u?Bhc6h-qUiecnKdK{Kd3{kC7{+ujRq@sf~sA^HNW#d5h{{ zbzAnT+)nLgfX;eMy3~uV1-0$IB|PwA{786r-YXWfo#N&XUlDxep?mY>~`m?sF~-DoNKpS6J$aRC|^wm3%o=hz0oQA&2&W4N-o!z)yuuM{jQY!50Hl`?YFrFvW!Ox=-c-+=Y_4J zRNSxF&wCY%O_h<`=w~E9lRKdV({A27;GKs@#ug+{CoTHyx7M@{_^2%!z8>sVTe8@a z3)+lIJZUy~=vek8%>!RbJP*1B#(BqhIWrIvTOhHFo9Oy?Is0a}ERYc42_L$e~eRDM%IhZ_kOc@;!QkptbTk|M-h99MaI+8p5IEk^AWzt z@}U zt)5GBAuwo>Ip6vihmJ9SYg=vbsGv;_RVkKu1u)1{Z~qg?Kc&aQ{r*<6Xlj zugPy7Z?+Y@Efnsy)j!r)x|qm(xx#1;gLw%f!us4c?7TZI8b}@k|1=l%e0t@5Bx5g^>^y|xnwv2k1IqQ`mjQG6|(%r+bgJNe+|5`?7)KA`6SEq5KmcW7R~CTq_Kl+8+qb0Q4_03;NPm4 z_m+7NQ3Wp5mT(r|Ii?cDD1KmnGwNfl)Fl!^>)Z)t1d4D0gws*A(7tJ^%KZi}>}iexopG zD+_ZVV0`HJezQWP0Iiib5&g1CXQQ})qrLX+p$Ov^HnV`EO)>e7hLJ2syo`ejXxad4 zkjq)*?%9R)`q1fG-MvK|_x|W!Cu~drr|c$ge88b6^<5kbxN)B|tH7lp3D%G+jneoE zy62=yLHRloAb`wQS*8$a%S@L^HRr3aj%6q}Y**!2w7nGf3MJReun7{M3zwNf$t|y< zqZQXkQ@T$&lJ9@L8>xJzI{sCIIfBCI5PfG;m2{80Gy85j8u>* zN{Mjae5QD4=fgy$p7Xc(I6$ny* zUcpGgcy0uzK)Eo3p(6-$lFm>v6ohF+m0+O5irob`R0YywAS8xB!qpf6jta2*@kkr4#;iMM3y>UXGEiMwv_OSY)tpI)OF^fToy~zYv7q zg(_e`6dvh>pu15jeiw%*WR)R+uVHwVV@&9c`%)-soYW8#e}fcM1T#p=TDlN?<`NlJ z4k(8zrYcKU;7JC&PbY9yp1>9d$s*FIN;7lC5d>0G3f!PFBZi0E1;I@fNN%V~@Ywn6 zyneNk6Dt;Mj7X*H3=u^TPMMP85`dCFYSR9$8K5N1L<=P-fSGWHKr@sQ)S&8DzZwGB zC_RHD5g{zi7jr0H>X@(mr1UqLL42Z1kN6q7Z)%4dPzX5~@fT?iXP{~r(pe-l~ z78$yOfW+f2k^9pa0|^v5%ptqQ`jQm59bkI_J}vG^(r6048aga3JA#EHP<{a3F*V48WD~(v5^o(zB7`oRm#a z#Q;%o7vTE+lNhfMPXwqdkd3@N^fdwm$W!%WlqL;VA!s0Iv0_1Q5%pBb&y-C0Ii2w51iU<&fMF&;;{xM4 z!ALr-;0FjK>4-8!h(IzLt3ViX7|}A5fIoM}qeC|eruqadWB zq4+H*W$7BJK%)){LSd{*xW4n5VUqb+FuoUhxpa*j5=x37oRkQ~Ux5mhS_i+sPl8bb zbfgn5=1`)CC)wD@acJl{%wW(GA{C$&#D^f9C=J2WtwhvMS{w_<3&qf&J*h!@0P7wV{bT$Blme3mNKig-bmpWF$FojeMk#d#q5z6y ze5hjbcxZs!9vvnWFThKN%LZD3k)$tz0ue~cw*~$qQ^GxGrTkloDMY&`(mD zk`f4!1JmHHu27+CT1k zvQRQ*QY0ruDNzV1A4skXpy+VX%G6k4;JNQ5fgluw{u2U3aXCGJN}3D{gm8dqas5!* z|LN92I_nX{E2 zu&M-o1U$G%WrCm%>ByA^J_HB$k8%D-sFjG+`*iCn z5W$QjF*~1|qnyCP5rnjUeWc-Ud*yxb6U~NixP!R$`B@u$3;XOT~-=K(K!6pGMP-2vfU~P&6pcl&Nug(+um;kQ2nIGbk&#D|1^!ios^dVVM7+wx~9K%D^im0bK zq^$-L%n-ywhIoun7Ki#GAk=Z8J5iGY2pX(Y2o?b$kBitL|3Kv)jvwXa!4jdTR3Nwx zN{2yGGNcpOKB)T94pCLBK$yYwxTci|#`}L`fTL9P#}CP6fdm&F9&B{bCL)zOkaAF& z@MrVw(g{CS#4wX#@ZT9ghY8CR?26!K@(g`}fY8kX2@hgO&@}g%Q1rN{e@S(auHenm z7lsFn#9jRZ#Kg!qj<5p4pF?COWf?G%I*=>{N;sdxgi}-Y0c(>hh1x+0r@$mQHDZtu zLuD=$lBqOz>+f*#gTo-qvnmk2ClNc|A2{3}<2iVVF+<70+9ZC;)+i_PeFW%BAed_4 zpB%;n?rj^9Ke_jvcclKtJ4a(ZYMAEth7qTR0ICE(z-dBfXgs#Eo zi0$B{eZhE~vdKdZ0FI}@00Ci`RVDzBQK5feF$P4n4J8~qm~ve|kwby5n!LzHgL7(R zK|oGhs`@EPQyme{pt1v4jAQ|LluPJGE-Q^cbA1g20|r7af>}eZ+$YDtNgdMRjFnIY zrjx-(XkqxB?Lyt|OJLvtLlpvx4%K&Z-FN?!T!)Fz$c>!T10$)lLZ=V}c2h=Ng0cvh zctdj|H3|Y4A-;`Bck=&5Vn0^LO2pmCUnIu%o5a2Y;!(wI=&90$kdpgnF>ne)Wr9@< z1A2dwlZ^ql))0??P<-##N<@3Z-!Z^huyhTO-FOMLM&bY^T>f9;38EX>Qa;W`f&0bi zpoTyM{zl(-jbqs0{~+Y$LKLFGWvnVmiYKRD@%f|J_< z{Y0hdhzM%pOo0JW4kOaK0>PxIf8ziqTjc|8XX1`1_yj2NTLjtF^nm||5K&zgN?-_j z{yX!OG>TuM#*P9tP{pME>ECfKG@U?ENsqMyGJuf)t&nsCfwnXp|IaBvby+D%0J?(m z5cPD207?~t8-fhm75ozskKlq8=mG8`6=*nyg8WItf6W2tE3qfAL0cV)k&*`8OC;E| z;CTe()Sb{BduRG1=mC-ZFZBExY#81UdKCjAPf#H!?x>Q>GYF|3Xst`3m~h&}XQwLx z@>C8)*O`7%57Ylr4^*~vA&B`tH3m*z2qlo^(BS-rnI3%j4n2&{DiJ7wvy%L8?26s}z@u{iTn;&Uv=KB(iGq-wK|t8=gzuzGIw6>T z@SPG>p0eL5X+2KWtQNJc!_&ys}GN8I@{*LUtzpyQ+fKnbV8j5urHRaDm_ z;wmY0`x_MK93Q#T_y9qLtDI0pU2oiun#Tsq+h(^1H#!1dt&AeEo! zlScV(BSlf+9H4^4KOlriBbErsX&OK#Y3n-ysnb@~=Ra zLxLL}Vv1_`&OTDXAfOZqPWM)sKodiTPHJ@e#TldmrP;xNN!g$9Lt%qRWn>I7{~ZcK zd63TMeVgN*@}E%9K#I=2uY{t+c>$SGVibai`qPJ$zA6NT$zc2|UY3!HAY`Kl0>ZNg zh0|xK67KG(0@g3w4B4?i`LT?@K_fN-8wJvhHEd;~vfEDQq7%HtZ@GI57 zgUS*6Bm`N4k>r6Cnh`6(|pU@CfwJPL_vnqtfSp~v=z{ey{ ze*&sNx zkHB_RlI~|H%AcW%eushx9q_SU{7ybU=?U-$J(1&nfG6!w@N_2{C@3k0hvH|dK@|cQ zf*KngYKcOA3H(Y*RAk_2fKo{QciQ-ip16ME#hIT#R!NEdgNK2vC^!SV3PJpS1pefX zs@Zx_N0#|Dwtq;hUuKN-$c%;m!;Br}O8XX=16ZXRnXmslkP&SW7Zgr9t3r5iB%p|c z`&T4}oH$6Ay!XFij47@pS9|L@Ma?hn;rq!wh~wD*U}F5W9aYIUOr62q2m+%i4ep2( zwd0-#E4R0Z8 zKm;kaIGFR_WFmzBApO)Eq8dBGrypwU2%peUICo$84&bM29+Z~RHlejs%H%sP;2Bz>~nDB0f{E-2m2_G z%F0t>i4qk`VE-D759MXV&I~angd8;3T;jxnLfg{`f3PC(r-l+E`Kh6V(|;r*bLKv& zOz=Z+V~azo5s(HOeX*P@yS&C=JFN$55bEoGG6N;iZ1jkK#}IK`{Qq zkNqTLja-W%rV$S8e`q5IDEyQqk%fPnC?Z4sa+H7hM4}6%q9C4E9rFIe8vRs(L{s;} zkb&ub1L#c@(WUqC|D8!Ic`czeEE+_XbnV6T(0{UDkJ7XoWR;C zdwe%_KTT9Po(_7xbdBO?uAl9yIhIVyPwc7*`M*F}2;TDu^c1K#slL-9QT{Fb2Q3oY zY8UJk0zX11!f73r-8cx#)b7J_v7pq{tLFjtKO`Uj+KMIe_t$N?ABkL4rA;1ezzx1RI^xBfo?F zbYwM01bXT(0{uSNpAGwgu{)tVS!1`I*)U=F7G8Rs0Wb52R}epx2U8LJH$_G?o&TZk zh*agog`~uj2S5qOsezC`aq(}CjPf6j?8qp7Ax?08GAU#51OiDLf&h^Usra3jrpKxf zERKcX)pck_Dnj86M3F}>5%ybB;{TGAYh;9=VB*|#y#5bj`ClV-4f?|d{sW8~Nr(;E z=_G10B5hDLFyZES0l!5X306Cp7E#Y|NP|@-@DoMnpRuk%2@*N z+6`vHwkym2Hf?`XQXzQSBl={;@`PT(7zW?|sX14u3gyHZI7t-J;S}EK@RL6w$`?og z9BH>-qYU{ME<0BH9boS(O_rj+YqEbaNMU%r7|LJjPMPF~4E(L`9^d_??pCNw%QgR1 zAaSFVXns-|QQhqZ6LsRRLGrEt@{>Pw;!fxQuI>+46Lb=cqz?orKndJGS;LQAn#5NH zLPz9RqM&^L4mkrbLx9Qn=Q)gMN2glJ7mzgyEf zqBSj=kq&Yz|3PJ?->D2oq_Wi?tT;ksMej)>YwVo-z~ml=KaXI;Mg{|pjAByoUqOu5xq%yT`hRI00=HI)6O1OEkysSbb~19oe>`0rlpho%YItdu^w zkVnLoBPI9;0{u&@6dZ}*=x=)@@W1|!Kz)JfU-0wqP~03Cl;P{OM!a;%X#T^|T%ba8 zG-^YcF-Y?5bi$>ZK}Y`XMhp|~I`8q3AJ;6gf67xc;%C3pzh1)oPEh}Sz4A|5%+gbY zg1koib26)kMuv^2L1=q`gW-^9g-4mk2eU_8BPt)z&hzRfY9`tyVy0EJ1jk4M$jZ*i zE?A)GqX(?)Q&myrK%*yM%+7-2xq#^BZ9fN17scmt)x+%5>WX8P+`Fb$b|kyl(eR;= z@_A>t2tJK!&Aha5jbXPeYhx!pe@~6uhLMo*EtQVRrp%Y8Y0%%vJ|?FUh!mC^<3BISS4-) zYiI||MblDp4OX2w-m?AHyL`T?`>kK0DK}`SyM={XPEu?zwZ4&sT6V;?v)n5z;6<}2 z9NDeu_OQBr&BML_aHN^#g|zF{ifmiF?eyjW=f3gHrRp=JE%Vu?+!dp`NS1XuY)yz` zi-_?Xr~XepdUE!&n>AcXhPG4VhxBKprq^peajRW(D`n>1md>)lgY(9h-NFDbpq^G+ z#vUp-+%2}SW!@mu9}-?_$gh6Qu49GkoK8vxt)oRH?}$_ z5+h6f@WyU6o`VyK+Ti0K_ie~q(5U>TmWjmZ>O<2P#hIs*3JT)Cr+*^e2>uoAb=EE#EC2GzXg+?9k)oCx4KgS02g+zeQ0d(Ct8>pDMKkyU zF0#_J!VlkmIBX9-VfeOaaLr=Se?kYrb=It+tI%|-dg^o!gEx*e4OOi=^|1e;hnqT6 zu^4Z4{Y~i%i9^0a)vz&Un#T%6*!w zMuh0z_Ex~tZL%!Bs6zR((1zu3hSfb$d}a;ez0J294j}b%*%xwt;0;I(0x&#S+~8!q zDbu4KrAHT0tJwMA0Z%{gst$rxqRk1xL%a>{pt;w|^$4l2R+MF8uBRfT zPG(?*P&8lqUWwb>y811wI<;r3MBpNtEO|XF$@Ru=Z8iisi=h`@^ zy>mIMKIfEfW458w7c>l)MP5&w@sZ&qg^NKes8%m!ntWm2)L-1(^A{IU{UR*RMI9Dt zxN7eE1faJv2x9S*~D! zIf&-!-QvreC2G;ucThqG-8C+LxkWn^D!@F=PZt`S7T*cg>9EQiQ_a)!lg$aZH@L>| zQFJ;{J#KJeE9|;d$b(qanS@((oPz0AC|zIqn!0LH+We$X%L6mR9J8rrXM;}I$AP30 zjH4&c8+#NBy>H%J5^=ut)zbE)`guI%E(2Rn{-_Hk(Dm@3yf{Cl;=(cdR@3C z5-K&lK`F?prembTBlh@)`kJn9Wmo=m)nosw_0PE@qRmv5LQMiQoDd@0H-eUhOCP6B zFGV@$JZAUZyk613t(0I)&zuo4$KY(j`Govg1crk9ldbW7TQ;F@RKZ{^G zT)eixH`HtkYL;z0yujphCOHjoJkd>=YE<98UMRi3x*Fp;D>V|J{l-{{=S+gyA^1!N z;}(Bz2)EoOY& zPveB&Be|(RvR89FNIiXhWA1Q8s=w<-@~Oe-es`1jtEz(h-IqqZGxMVwGU}f__AUZ= zBzANAoQXRl-DDwj_3lh<_%jByQ`+So!?u@FkL_<4iVA^UJM!bX^{68N-2Aler10%K<6k%~ePu>94f0qqI(th%s5bT7|3l33pso4dRgUTcn!+|#~ zJL!wPC{kx>o!e5M3r5SIzj!fm>`bnWN)s!_`O0I`(5^0;=ch6%U(^Vgsx)=iKWB`f z7YnF=l9t8le_SHnG^l$jLs~hPp7qMPrfaa;z(lpP~J<};%Q@kOGyHU$sJSqZ@qeNIX)@#a$Y!J3*L+DzMi@ECh(;O zJ$Ty(MpkxGyUGvuVAf&ot4-vc^ox^jmvuut$hU}Yva$Ix!%7OO(!Ls>*>P{q)RIpSrf<)61gg`cgBnGB0NMs|CDINQUyPev+FR6)ruMOKto_6R)}>hSXP zaM#BLHM4Ii1NRYYnU3)-9bB}BbY<$_?tG9?b=8ea`ZV4jOt?wxtA6_#Lq0cUF8O?IFSIz87D2K&B+$xgdSI|>S`F0)u&nw<$W_#%)m4CeDbyY#|4idNY28#(LX zE;W|xg-N?QGN}G8EA>__r7uEpAd1|l3@B%f^4$(JsFXH4nep0c8@l~csygqE%ypFq zd3br0(^vM`F1vyUxr`_ej62@lLq=sq+7}_c&_RKc+sshqon&M)+YKTg;<#u-t1;@}>Y@p#{xB91 zZjsy)<8y8Ypa`+=KmIa{Pfw+PN{nAEV*4cHjT}Iv?$c=YyV`6E(uLh=gC5=2+HPw- z)qF5}#v|ZDMOa*x5rG?S@)GF8E_((PKPp0{^OK3lq>nU;4+s8S3qH$)Tfee z;yKS+!(^@UgCM={v(uS;tg@WFqMpxZch_ZEdWO|3u1GX;50_1EQ$0(0wf*|oM3zU-y+_XDiHU9H^CIu>fzW_Vnw>&rXh$CYV-UuE=`N3H;>frJY>Dzoi;-wD{-wB zO^v%*)VyB&M7;IEZE^CtbGKhic)ujQvDU~ud;RS5Pco`hnF$fJ?Vz!H=kDqCLi86c z;y+AeU%T>oR66E;RWysTb%fgIly-Qq%G{%YGBCPcQs_J5eX0C> zgv*(g$Z;`#8R17y9@1;*wn)pyy?h^v#goC)BE|y6n2O3iUKmUS)2WI(#L@#5_y`oC zEKHjbpQl9Z4DN{C0viePs3GRJR%nfti_%qr@a~G<-5Q^n@hkCy9P-8-Te zuBN%i)^Ya@#C(+H|+Xg~603)r=-#V|DXI?FIdi>mjMJyb*-PUGA8h|(PoV)-0%lq&r zlIpqyTByP0c|oy<*;*}^J*iJ`#i4X5Dpxl*CvG^s5h%U1M1Nr6McwNDAmh!H)D08H zmK>P+huMqnRzA1q2M1ifiUCFSbHe=bZxq#()%7yocwCXtXKX2BO?t0dPtuetsidKq z!fM7CFxTl&u)xa|5?kL~ThqeB(KQ7NM`GP$rIc%;`fkd7laXDSi+#*z;j)ZQe>l() z=eQOratoE&d-CGt_?Gqq_K@SL<}}p`O@#|k(*zw0hrq3e3!#9o#$(e|Dz)}uzR%0m z_-EG*#XsZUOy!6>cF(IJh3!h;bxHBMz2ZkLT(>+!H>1oCpFUxg^vHCKKZ*d#B*`=vyF>s16P^RO))aFlJ{yjlS= zIVGu5u=@}&al*F!G;7iq@Rn7b%gmFp!9f!=24OkhJh;#-FC!hE)tTyIRi>WU1ABLj^!mddsNB}SI81l-iDLiz z;>%&BPbJWWagoc-RAhltVzHED56o>E_F}S`6-Yr}FMK_o);%s{Q-oQJ6w!Skp?xPd zR1v2+IO*v_^*oCw2oFs zN7Zs|CzxjVONOX(Cc)f>Aj953AH@P96 zk|EG8?4X^H1bI}iyz|xAlVDK4RzjF}Y%*KHC#(?aR`7}ga$mceT5wW??CveNWz4u~ zn0;C^p=116$1qY;22}cBcNAt$HEYyDB)P@M}oNgm3<#i0xM0|#Vwat z6!SBz`*_5|t^L8h!*2$bg9Ybn_9+;VRD=#Vi`R#Ph${SH>Nv8=*UxC-8>IJiZ|o95 zviIxV9=tqH;7s;QE}YQtd9_x?0Y$?5s;x`Ih+Rt#TgW`Q65#>N5Da0wwWTKK_Yn{7 zO~PPr3li22mD0x`v`%T(`};UcRil$d;!H7c;W|yvLu*U5wexb7;$iO}DETe=nhfJk z6MySpe`0jQUaf@dn`hK)OII6CyX)!{oEPVm<|n=Z@msyhs<3OkO4#vFn!uQ*Eycmb z6miV>aU4K8`Q5>#X&Z_&YHfZCUwAc!b+VS3%J zG~rTBAuEK0jY~VA0p{1@OFX#E`OnLWB>CgK}10%8$Y^LoI-HwN?<7_ zZY9#0+-cDo{wM~$#V~xL*J%j;jpx+(`B$j@j@anz#Ar~`t(M}A{lwi^Go@%;#S(n6 z%T%okP7tcu9fr6ScX0Lb^eqeM3ri;SMhV~o(wE~*i!iREg|y?&mPF8HSqu$ z?ZK~&E$$-S51ub9$e8;2Bv~ptUhe&|EQBP|Aex;m39HeBD$azdRY={0zy_$9Kmzmi zpT}1$v}4ld@DLN8ggM0yXZyA%73b#f>RQK6po$A{3`-BrNv*!aPaza_D<6&7Y`L+SHk?wG^PgUD|;1$rY zFSD_5(qMWfY`Y5t6i*NEKMAKaOVj@pWo%ybf@7`l{iij@UV{{-TA)JIBzYQaYOlFX zvQXvf?UDx)VLcCt531(swauH+@@vVTDcVQ(yHrHi2#(J9Tg^El9~cUbuC2Rx)Dwmj z+8Dt;b+Ay`v^#jVPl8_H&*-+Sz6@`59)qXT6%YBX&~z6}hv{l^IP|n}?^6r50%Yd2 zI-g3m%{vsPlf}LEQ5inuUyfHYGYK@1TqI3Xe>28h80Rss$L$}9dpUg`S5R>vm?SyP z?D45=&0)@b3d`P>Vk{r}GGU_x_Ou_2O7L6~wxYX|bb*lJm2q%)^?hzut-1ROy_g6mO<-5j^oLPwRpf|4J3iWr-=Xa76ew$7AmEn)htovB)$_}j2tw|fcWaJ5gY zS&$5-HeNF|(yfi!$5|g_izc${p>tld#ax5>zU6)z!^sn>afCcEZ;jzQ5C;|| zj}f%4q*L=Pt0do~{5|!9Od7*cg-z?wsvbqAQ)Ecf%8p$DhgHbR*8`Z4p zmoL8+iz|eCXTwrPQgzCQv9>~7VhU`!11UiLhXx@X{TmGVxwqKwTw6rnv@5jlm@A2c z+sWmaYAEJ>oVH`Br=*eSPi)_4X69d7v$lb23@z3?yNz<*pJG96? zFXwcKY(qY^z0Q5W^J8wi7!-A8&m2+R{T?^-n8$xRzaiu(`eMp(mFY(Yy0F zzQZhlt7*5^qHV;aU#HrL%0#E`!`@}9tpuf9`*O&YrWt#tCS>(?o2SrWWZOo_#dt;; zyCh+gG8dn@#x}RWY;1-_xvaU}S|+Bt^DM+lMiAMzDEIa-P3gvPvWI2wYf-58NY#^R zn^W;(3&t=CxvdMJ(iH6tNsmNWywcv?;jzaSvxG3I9JW>`ZGBb2NFH5o6nw+Z%8tt} z^V8G>ByE$xuVJWD|8B)WL-?#oWl;D^`>FK}6&OWiYmxE2=uaO*URbZa-*K3*l{K#l zPczZ*-1dcS$<&=-Dw)uFYwT5REJRp{$`<_Amap{A-{rn+KdVQya8g-g{;Kw>%0^;u zyuE>-p?zAcf6uFteAzMm_B<7IddX@(#($KiEvx3yg{0Za=rKA)b-c-57A$_*QBSgX zhN!;}xb(^gUcPGcG#h<84L@gqsWJ!`N_wNV7z<0Y2kJ`AmEig3g+{#!^~2iB#Gvvc z4hQP$Y3R=e)k6m_^mp_LGFBxEI^LU~L^qKkcJXBgge>PmD6K;F0dodC1{)Xud0bHO zGe~%OLOlR#Ihd_Zpwv=&T2UI7F;kjifcMeE&DnmL(UVR4v}j%#JkpVU7qS1T-;!=1 z)+`>lNZiMxvq<98ZTaqN!*3_fwcX8!J^QrKVTjj8-k2*O2s|dBz#cIsULa` z+?RDZw%xl4H(>O#BSgbAK@RzcW;3^)tPXhY72D4&S;wJ2W(2pfMR|@x?bSP;<<)DC zT;B-~Gitl5IGycj!CJ=DQQN23=eBbfPyMArw`F_n+^Ea(VP}x7)Ro;by#eDigM~dt z!4$*?C;-pb7k5T`ln5wdC6{%onUk6$zAu*)&KAYh-;YHR*5&wko5kE&-& zAfLR=)+-w}oFtlw_1wL0Wm0OFH=W&^KF~H`d=u@sZI&H}zNf5Tg=6*=PAbVQhK&#O z#C-CA25%ybMYGLvPpj>jzgz$2qdEM={7!w3^L6qk$(n=X4uHd-L1Z+B2|r`#vX;+q@=| zXKQSQMS#Xz4%2k*bt9u5Uy*7yw|aB&4=E2zp6Zou#?G|KYF$h}+}}`Y8}Rqc-_%}@ z!nXmgV!PuEShmBwXV>H;_2pNwL7P@83@m9;Jn!+hDmSd!?n096=UXi8Aj zY~sY0)6((nnaOKp{^m;^9Fu3yz+-3)4`Cm$28m;f+TLMXF4`a}MYo06<#XaZt9c&kBL~f=Z!lRlsclxaj zlrspg$5TJW52j#0ci!#eUf6>`v5WUq+o)>Z>Q{~SrY_}&r^IO$vVdYH29EXbqAP^+ z2jSzb0SmX=ShczHv^S)KI+wSd_DK5Sswn>{Y8Zul@5eTz!Elv7WZ=xkuG>ktb+vwN zIXr&a$wDDdZAbnVPM3ANT}bRa^Nj!Ar@M`kva;xHI z#|2j>ey*<9zRq;RH7#CQ>yGbdtO{Mf)}c9zxGW7F%Q~H$ zt64F$;j~1?-@>P=>z}e&hnZ098XB9P#->INQ$qC zcE)BD3MediE=9~8Kn(T^ZIc$;<|Q27jcE^$84vf#@aQX9HT5n99&o$CAFfimI?dgH zl}Noz*$PI*)HTMYrg--3XTKffg}5m7wobjNOIQkR8{xUwhoRDyT`0@Fy>TkT^NRHI zd8!l0Rn=AZ6wOulOc(cfAqlM|iDe_J15F>*VPj-|m)9ugQ;8`Z2R8>RyUwh_Q>~2K zgYEWLdtz-kYeY4h)UbVW@ecki$5_NdwRDu;`FiA40Q7U}i?EtHixPIXwmongmdk~F z9II-$CnG>N#cyM`TYME1(`kkUAaYYlP7T++s( zJJHx(-N4(25%bKC9)lI{f3aIqR7i8Wr@rsEq}Eo=u6Oh9Fv{21qNi&@BDtlPqi@Ss z5wgu;r9Yrc#Rq8=Zc`6T@K4U-UE=C;)biBgfOYOL_PV81uWvkT zt6-ho#bqRn#Lc7g6iqaSmo!Y)_`)m2g4^xBy`><5UilSrGlXSRExUk(y=Frqd*G#l1R)V1x3z}z_=v)^ErTqJCxI6vhf z0Xmkku@uxqWJZ_P-8RNHtj6$-Ue{bmyqZZz9-3A-sa*QjT*Rqj-#GNBZN5;k4?oyW zWv)eDLc6p*-=2lFgG#nOoAUfnRW2;y8}I1-i&0GM+5)4WZ_U-hBUhqLwZ>-z$MvWX zaaC@H%(f7@f{Yz+oR(FMtV18(F(Wa$v@G5Rzxl#k!fBrH23vEz6!X^peP)e&r_=7o z6s4z_yV~at`rTpek7834B3Jm`zABpBl-v-932L;Sa>c)zQOm%Y0b8~VUzrJ_Tev-2 z6pV}x@-^Z$Q`yzFLtcF{TmE`6Pi$VdV{%N{#8HUn*1L_i*C3l@-A~eREzy3zVIwKM znk{=7p^CbmoWP-%S{tykG+4?&f_8?tA*8?iHOvJNbX_0SoTc?B+(0+I<@S>dxxV{crb8%o)*T+luv7d;wb)dO0K z$+M4q#%Hy>ZGU}Z565d&vZ5c4uJGb++OmI3xS6<{4a*gNaUrSZL-wX2`nZ@7N0HV> z{3%Ef_Os0`^^Mp-2}Si0ZT`q24uM{8%N{ui^F@3V43Nd6SB`DDvj(ab(#p(tv$&p@ zPy(*MvcAqB0r!~nw2~`Nr^z=~u!+3AIiPk2D@WOVD&lZQ)Ha%xA!EZ(-!?&bjXSTv zPecT0eZDATfBv(zO{z~6DATYvbx_d6jUviRPJ~@`rp%%ELQ+LxRvXjP{!Os_j^-6B zj>7Z}tumRu38{P9Ej^Bg!>Z`L{A5uXIzhA8d4&98V>6L!w+`v`i#I{?- zL9i-74v)Fr)ehvyZnwPOG}g5g?`q33N7w-gnY3umq~J|d;*i)0CZ# zepqShLy#(7easmS^NEzw34jC*poA(iuP*qYOKiA3=*H8^1#i!!TpW3J9=BV2)uDgm zl_a~Gl|%MH@8Ig41*_ys)>J8Jb+1+q&HQU4R$d)^?UcD$-bn+~>fF^^Q*?jU$$ILg z*{6+^c#WCI$sMKJ6?a+NT72YkAqkaXzUrNsJ`y}tugk9)q)H6Qi@Ls&dkV-g6E0Xz z--t=;9JJBedC45Nmg2B@kB7-4!y-VwFXcr77r)o*?RPVu>Mac!dF{BEG9kAY?8@G` zSg7{~w~c5c{M|ecJ1}DxN7|CSrX{WNMIqrM`w!sym7_f)HghQu!DZ|>EnM;Is5ng% zWwfhp$8LOw$dD$k2B##P)F&RjG}S5Lh#EK$w#}~AlUwFip37t|X8pQX-JrD$^$_Zj z*Xt~aQ*!m{zPo;Ct{ShY3EfY~AVms|LMRFs?u_4pqa;XIuu_I^ILzIdo%er6R5n^6=!g7e{#(c5MdO=2@U+a-Llx zz-V~g0xoFc#Zy>pAeMK1Ig`$=ckhu<*{d=p9ilkiy56A0I0Ia#c2hsT(^29>2SB)$)v5Tb0@b?tN2~vHU*WpnN2`k8)2!%MzIQ^ ziTjY+k;}=_t(*-hQv#2-Ynv#Tb@(CtRXZr|)YF#aLdrZZZimXU3MMH8%|C^YT$__| z5!gp6W?bo4GdE`%SCtg$${&ODY^S&m2EJLwzHS)eV{_S$?v+5)Kek5y_;MH9_#U>Z;FWQkwFjD_2Kj2)O0wD z3ZZew(PDkPTM?JqmY5&vu*Y^cXXf04&6bsU%Z1W2a>XLUndny8ni#X@?Izf&yXn_$ z6?0N9!wKLPOPOSMwafJXQFI=TQ21{gZ-`1LzLI%mmRZ>j7m_5Dk?oXZmXLYwE~#Xb zopDJ*_9onsy@{NC#&P!HxIKRT{)f-=e4gk1JkR?T16qBCH$j+@+mf06+l^p#_ z+-}aXdjo~3ZXpClmRI$OxKp~$_k*Mwi$27Lf;%jT=<`UpDhBm&b)ly6>PxvOU!Hh5 zzFZzl$Xw~2LiCowZVA|;ix5ck!{QCoightGw&T+RZhu0;;T&nG8l;H9cD0@t?z8m5 zLq<(O9W1XlW!>a6WXhWIN|A)#*6=_)Tw~O6*F9INH2+&j2tq4-x7_uP=`9gWGj$9v z`UR%?{@J@s-fVUh-sLdXdARy_W*%ky(hxln0)0-r_9ZG4ojy|OW8P3DG4t1{ZzSVj z(pk$ar!9%DzIy$Gx4>{BDSI-P;OZNL_QF37o!xn?Wi2*mdW;j6DG3+7Z^`tgRvUb% zU61}$qw0k!_E|lnV!o>pz*ku+WeE@EJ&v7F5C5k9r2fWVTE{gN-JgwL)|<6-?;Jx5 z_6sM$7|a8Ty8JdD-w?qjE4nUGe~RLkH=wnb5?WgCKc7itX}q*rtO-CA5MQ5EP?^i9 z`{Cz;qZPASh_G3lW%g`yDzw)#yeW%%y1oHyLO27l84GzWRPSqS$}SxlY=s*0l$Lh`LCkGd7{D z0LS%pRi7q5q2b3odNqlm##I!V6@))g&FHxlxcC+3wkOP&W}0nC(2JfEvuvn=XVnG;Pt}-%eLjW1lC`Ehq6<$RPZ^>eYZ))9m?k^YsWdyT)!LTeCXLw z<+TDY(Bqb>y7KdlP)5KctC(D%<=il9wptARkDE49TGHk}-jmTfT$fbg#Ra+!xH2=MfZL=UxrJ5kR7_TSQpZHtz+1tSUw-c;gjsyUx|=$-c13gzGS9bL5Dw=e+Nr1K*8=D+kG+&eCw zEDeKtl^gv7UpISyOrk}b1)?SqwZV_gZ&BDPaT@)(brN;e!;ZwRU(qiG z+GjpB(^_*QC%~I zpQ$ieP~ZysMs`icRGNjucxkh-U@QKq!f@>R6K|vCJcCt#n)~1lUG7&!Oq|cpQUA;4 zg<;RPJY{*9F|9l+hF>^-(k>qlHV)YwOvJ59-Ad_kUkE|ii;b0v5j# zmu3|HnJSJjKZi9WB?Rz{YlSRMjZUVeeaNtYde5*dRP%@^^!W*9#^h|BuOyVcZN*o~ z%j6ft6RI<)YcZ4RINO`q@~;t_F+_X@l|G`3`rfB0r-*sq-(B1Dz7ADe7$C&fRep2f zed)5R#dNkOWf8f{C(M5quM~DOO-dGK2`b$-9p&qRxo6JRRjd{U=GMm+!@sN)y_R|j zvzcL97c+{fYi?HXhF`gVR_((08%E-us#FSz>1`{8CRzaJs#^Y(v~CCvG!}WVa=usA zYHpS}-=XRLY5C)qd$3)cV-8Q+S}jATK}&a4v1UrY%>OV-kZ)T3PuS7U*3>qRA-6-% zghRDal{a&JoQ<}6`>0PBMYu`wTY!;9OP~f^EVr?u6HWcRu>Ej*KQz1LdiM02m>N&d zf10PZ+m|qLsG-=g0J11>$1w=htEYxQS1*)FFlau5bi1HaZAQtuc!QYA`SMA`mI-4p zb&<=%*`-U@Euc4}z%SbM>M;gIF`k*cBsp2K?&zi7@R(K~rd>|LSxMwh#;YW}7M;Dj z+vi?~a2$Xc2J{}7hE-l`RKN>+-X~x;L+i{{`pu4mh(}^r)~PU_c3s^( z;=#0sZbg+uGXyM9Q`?e~i;3N_g!W(NzS{By9r{_|kKf|sEmF~L5v+v}o?H_xTHIEe zX0)mYj4BdNoTzm+Ua zbeNws^x7`IJm==)!i*!-4q_Y{rt_kJ~fKUo<%KI5(X z6=v3(rm}axxOiSk!*I1S)h_J@T%=&Nc~$0-ZdJ<2R$*P9D#p0i+$~9ANV26y2!NJ^ zG{%+8l|dpT#I0!Bvnl!PkBrtYE!jVbjC!#*u90w1Y$-(w8FQ-xY<%&&T)LjR<%)hPu? zx9KAmw)w+QJ!XWeeu-uZE8>5~E zl=k}TS$`mp73_Ju>Z1-L+IS1$9jxwYR&RZ1E{UaKTGCYg%6Rg$fvDmA%NBdZldggX znUTutf8s(lT-AncdqmQ2q3nLXkarU_wY%peE!U7_`|;(L#YJ{a*#g1g;z7r)@zfvk z5;p=fjg;3dGMeRG#RhHvp%-Bo3@uc&{PQ+Rmx?=X8qp**k3!#IaE>_Yrb@4?-96^s zmO~_do9eprrwi7;(JS?LJT7n9pL4_ZSx%=EtM~h;yg}5H=SZ7EnCW_`Q=T{9Lp7!% zHCtgrIrt{Vi}9F-sPX-ybVmSzn(O+OJAF>bNJ83v1o4eE2F`BUy>fU29A%b8kLc*} z1<&7l_H0iX{(|V^;GadPfv_T58#Bb(kzweI)OCSs((z~{Qg|a?N8J`p0JwwNz*rA2 zQH-)7WzqW?NiGQ2qEc;+Q3%@Pi6BMiX3j?ah57Q+mPoOv6ceJi8!IsQqlno|2K3JU zr>`{XA@3U!>@#Ir zU-7woXYcGvj(TgahOfxp8jv$+hp&0sb)AOyr8)5#)w4Q-Elg1h*3-Ekz1~-x;R|$W z5__oj_LiNJxal8fChMKCAYOzBCjQH%VMSfKzBt#omN-Ub6T`-~(wTgg*0I8kEmDG~ z6R?+qc91q2mCcGVAS1QIo!g;G{_mgA-yOO?3W71?NbNQ48Ue8(JUf)WK`t5QYii-> zmkqmnVwV(WMo6fkKzoAO$gza~E4xDaOpJ1wIlhnemnu+}LYWTcnGqNw$<#>^GNoXi zLRX+M_`wv8a(dcl%2)bR zVCR8LLOVJ0FUxAhR*h>}P%|u%b=BXaT;Smq^cAqk>?`{B8T0SI{$mVCu2m%5Bs4Cs zLTv5cnP0FJn~Tg%Q!}M~>g)Wbd>d1{v@a6k?>wu}r*StiCF$TpdPkK#_-A$GQN?*w zQ#T|pg$v|7HmXr(Ne(?@Llq>YZm=%1=I-|X6(N6boEg=*f?BBBzY=}A`c zI+i&Cy~uc76|vR%saPkt9}!fAjO&MKC+IK=ew(*eAY-L_e6?r#wY~aCJ8kdZ{DCle zH3xXN`^jwrWX0L$kre0!WK9CWZ&@SgO&G@9rRZ}MI9us1#7LF7G61%WeUw*YvT^B` zK-^IT$LdlQJF0|yMM|d1xkwkc1DBk zw2K4s6j>(geqkWuns;^?YkLPVU@luDJ9?bZ$`Oz1C%rz=_N-|`m6;*0zG|}#RePg< zx?cO{BpX;{ID;zwC^)kJ(vIha)6}M##(A#XP*}nzK>6y~w){GQ>=jY1=8vbrcxs zQSzxW*|_O}Ps0r@89`Ujf?(I&aMr2aAhjxIe2LNCe4X*bMtYGTi~DrjaznZWA1Q(F z)c1`ZxC{Jo!ovI7b)m4KC-h^l?n-LthuC@i5ignIw!d|Ly74^Bk4wakBX;p5uHjF$ z(x3z*vh6qip)4|=ZI-V?aenOA-9@It;wlxRD)YSRlxEnUi?EUl+7*M%Uq!SWPfE)g zCODpvE?sNWJaNyvFt^ow%h8i7I=uD_2s|eX{HaEf4I}h%B%>QwD?KYC@u2XbVXbPa z-_(aZ{aS7J4-5vK7#^^o{_S=J*Nz^ajyTU=n%_}>z|o+_>QeisIPVKqw3VeM?cVoC za@){@3v~^2-GIe!Bfb)>%tA**2F-3@$j?aNYm|TAf}wEoaf-PjCJ@s96<*p>t@Z%oa_6I1f4UaXm0y~08^Os%Y|IpB*a;w7 zwB^vWmGE>&d^hnT{CD%P=LoBzoiW{6FF-)GY4|V!09&RVaSi9(Rk0;Pye(zA&kAmn z4`*?cNfN!16;b;KUTvXpaLEh{ii3t1v({Kd4qSu(q!a&R{n&}zl^9BS{1MQG zJd(nmN!uXA+MrFtgWeJ{S7moOE0-!ug|qv3dXfU{5OMLU8_8B@}B1bIA`kyiP&cWqM zrxq7*wBX;Qk9z>?@DWkG3*6V0HIU5rE%-9(<9D*TklVbCoKdBatUgmru1NbD zQ4M)-qy6{kqZInNnaXM~Cb*Y0K2e`fnhb;SL1LYEdRA*Ab0B%&5%1W^9y&C@n84)4 zZ#U}pxv)=l>S`i)V;Je?5*^7I5BD=BS~i@nn*1=~dArG_XT;>>Ii>2;}^Aw0fkC8@zS))B=DF;!x-WyuKV&LshYJ zr(JKHe5&+xz9Zm2^_{ggxofFK3+;MTyMv5F^XTxO0JsAr>8)`DwI#We6TEE~HkE_O z`Bl1)Iz*KQEKxkE=Z4=d+vVfhr?oR}Pe{bNyfGf=#y>d7{Ru{&K}1ivZaCBzOvI4{ zk2WAAaUK-TkA8ij1r~J-iEB5}v_`oQ->~?0NWkp`Wu>%?hx5U(yyL+{oi{V``48}p zl5anD*3adjT2yx4>5N9n=Xp&PldBpEh}v88eH5zNc7 z$r0JpmRm|0*<@st_Y7_h*4stG(;aqHdzdp_5~A-zT4?9-fvQ=OWO6WQo@mgN4u$4)Faf>in5j*$?%x&``75b=U#xhl{Asd@7k{dN((n7WJ)x-hKz(D#j~VqH z%hu>KmR&ac&7hoyJo}%Uy~Vn+t9E)kk4z{fhGcIOoumEL-XYjCuCZu|uR7OP`E?gQ zU+V2d-)mbzOYHh%%=SYBs4celsVM=54^ZLJ{)23XxOZkdK5;UiR+F}M&$E<~BLQ>c z+Z&1dATcr8Rr>G*S+J!y)I8O(8+mp09E+VW%Z@6`_~iVISC=#cTsOogiZtxMw>jcP zv4I{xxFZgqh-?K-z`ee0tAycmW&xQVIvfbG4XMeWc?|P7UnCpz+ndDb8_Z`iB%n%X z^LNNe=5MfhbNMNhh>ci~Yn~Rl?~Wi1SzoV`i`w9W68|H1YRdHmo^K%*9`JSSoX&w~ zgFF+Iy1^;|V3WbNGNVAa%d@+)Q4Yl*3Y!Q1geBhSJ)w{a=gXZm`qlpYN}S;uHIAf* zFQVHeXS>gGgghw@w%wOFMiMI52_Bc^RiXSFtLGoUy1RZG!9+o`S3TPP(|7*+@cLl; zt5XWLpV`!2SMmZ@U1+990}{U|x`ylH4&<6DoXO@(FeNxy{ZfYUW*}!8{r*gmr=tLW zv)_ZtxfrKN)LEdh`3<6NMVfJ*02qnIzs|>Ndul zsDd$F^UXSaKcRrD_(4H@I#~he>BkHEsjl?+6 z%M}lSHyZMcyX_HT`&LSso~ZN^l*Q_;A0FT&DOl1rng0gxI2B6GiBq1?b;>olTw)Wn z)hqK!n9u%OD@5?2W5z-GApJ#I=@%%kvq#_4i}IQkKBBdlLwVmFq( zX|Xy%q(8d@HM8D@l79zphVZquqAs^o<%rWC$_H5YMUL_T4qo$wiP0pP!WDMp-~um$ zDP^Y2=qU!z)Dp=?= zvFzSc&D}P=^%>Q7I^~sd(*=7zJLT_6yQBi{&+9rI^NbTFT@!2Y)sMQ}}jiT+DB6YCT%K=uH{x0s;3g&=OyZ0q47!YYtNW?^TrsnyA%A zNAC}Ke0KB}w*ie=tIG#mw#SeRGAL)}0R1dV zY8ON7qwgbW3)4pA3p>9OVnwaIm?lf0aJS!yn>)%4ibqK5R9$pWYZNJj6S%QrxWa3= zT_rJ5+T<*^2CcDrRe(IL6JPm}8gbSCu*3cUQYHXOE_d5QUq9laBjPW6M3s5ppb+?; zu_oAm;zRG}VK!2zWW+u*k*5=dB#QO4e9Gypp^B1AW~2jhiV~{vw!K)S&VJ&T1Rb}I z+qj-_3eQr8vLVo0Y?KB%d|o}5lj0|-NrI%u4h3DyrA4imC|!hwgxKZ5&&8e7X%(lJ zm$}AZtceGUZG91CTpNGuuKGjGdHh;pfSJMQnMw(PnU)l2{y|Z43)-K1BuiSigr=&0 zL|YU$n_ZR>(u|5<%i{S#as>&6YzFL$5=uRZt`$N(tB_Yo0i%EBwDG_VjCj2Tm?tQ< z?Oxroywn60xe|WlH=};{9MJuTZ0#FrEwHZ`*yZXBD6VY zQ@$38nA|!>{U8tA+LBmx@jn&kl)9}vDi~{lycgcMGK+9$-Tu_Oxd~^dg#8=vB;0`% zTy6`!I~DPpYk;K$9?`P$>+g!_yAl+b{f}qoA|4xZXWZvzMMM^pKi%Snl3z8C0$nR? zLXa*LfHSsB(qtvbRw&P+`e4BcAx=}GefbsyYtxqdTvvQfFf2FZUb^;`@b&ag(63s+ zo{xalA+uB6fe`QczQUl3>Kzo9Oa3J{{WkW7I(;|p^Ri&Z*tB|*VMS$m_XzGjBQ+G& z;#-5zl=&nR_;3AtJ&+=BcF5YV7n2==7RPjQCo4f8W3A`bH_$UtI@IJXE4FgtIrw?hcuE#J?CPy=zU=<`nNtPk1WmnT!eNQv?{x5= zUs=4#GtBExfzEJYM%#9GlHiCmU-TCT~ z7=Z}2!}!)XJO6`$PDkgy`+Gbp4RfKH*+qS7YQ)_R+MXNn^A8exh6Re{+|jKEgibEF zNBc6E!aP|7$VQ1ifi>%NH@sJZzpK8_E_=oC4b_S6TMp1?5-wgNW-nsl3RwnumIr-I z6-WV1Qq2F(jxI6J5c72rUOBCLU;Jko52q|GKUHTlhPU9hqa&r9ZOm1%NTqF_C0`Td^OX)S3+?}ONwP5JOZao{n;{V_%6``u zV*z>k3CLGEDY{Me0G7ZB_PFshr(!TX(SDHUL*-I<0o|eV^?Y%tiOEBEA24+%fwT5wQhnG<)~^ zXVT{B=`)Js_d<(B;{xBhYZbPd40O7PpMO!|PCdJp?zbWE*k3K~Ls6%Y(l~1vk&Y!y(ZbNe;$zeFrsy=iO-BGf!UBWZ1~dyzuJaGRPMSOb|8M zIo##uKXfr_Sm+~0=gkqqbjU6g)yymjbSy_NhW4z5C6H(Af&Mp15}2pje?u;kYpcne z8V9UDGC%E#FieB>LGv8$#Ds9vYZkcOT;1j{4=gcaU&jN{n7d6nwhoV{Ro0%$k-f$Z z_xM1Ku+BoOW{n2kL|!8_pZT#O`@EXxZcWE~_7^=9{@_CyL+L;DH7ZZgRLYJku@M}wCknKi)C=- z{yP5b!3r=jSA`V?-FZHMtjMG4vx>$6L_c_+&;(B zZFG-MzQ4-1*=P}v244O8bwxdGq59C>;$YG;yoj$E2{{eg{|&SF9kzhwK5vyIlOMv5 zVxvjIx~Bq<5cvwcX11q}Tw4Ptx~9)k3Hz@G+UmcKYPf&X3E@SW($nVkw8ONy4s~PU zp9ivCJd>E+N}gB!hsr*wTIkNR-TTsUH+D>Kzo{$!F~%<<9Mykgh2`+$c{rr1AZRE# zs#lj}x)@tyPh41&CNsE?_!_h>oa9W@`INVEov3x@pz?R`!)XfBnW~M6>M|NEkr<5_ za9zp8F}v5mYL&Itt}@=ckUu_Ocb@Ta)&c9!eoTK3v%xm^N+$gNIfT}_VjaH1{>GnA zWZ`q@=O+11|Afck-?|n2+OiJ-x4mHTgbveFR*)w;>yRWZT*mmKhusIfPK%7GdG7Th zU5k_K-jaDUXPFU5yB+5=QHlbNCK)EzYx&F_B^6W<-=}_RqU+@38~WpbA7rsuLf*qh zf%w;LjdTqXpcBzIWgLFJSDe}8u9nmpPaK0)30xpW5H*UAM6-hOXH|~Vy~yG;-a|cT zgE^MmwQYSUMf1Lm(dqItt5`vQuQZ;|xxHd`xnVUiwN?+bNbKA&d5?M1=(9>o36yDo zA+!^RSklvNXYSS7;`wI$7XhP5Ex;R~x)1P};X4?B!?nCFKlNjxMYD6iI)*GC?xwjW ztCZk;E_Y`}0nh)&>@@7A7d%eqZs^^ei|6w!4$toR)CX287r#T?lx3v_^n~z)TlYp~ zvaoXN8hJ0JF0z(k)LXNdK|1joyh`b6W8?Fuy%na*HoKlwZ*qM!;18Ste8H0OPN-It z-W;_c1^1zaJ}F-kE1)mEAM#CV;!D4=aiF%N>pC%(FZlY+lhWcI0Q?MC zwAZ&MFABE6OFvCcQy|Y91jdpP<`~zJIh*hB@^qMj;SMKNg(=s6d~%)iDX!>u2dVW} zHo?%F+T1;5!n|4_)S`**1D0{}!ljGS$+Qn^*ph<*%{8oinB4Y%q;p5+SsP7p;BsF9 zKQ^5}EZ2>=rCwZH!KXmxAFiq0ZCxxw{eJvr#WmPQM~vzL@UD5uO9|%7Vh;8>)m~`q zoYdmjmU;H7_RPLB;a7fWC{rq{2(9=u>c>%;cPcHntFxvbrY;}UTM}|>t&2c<9u1RW zk&;ke2(?~NrYXgkD{f1x#wdyPFn*>SG0C3CTMxp9bi!ip(GIz>9%5%?GZ6moW zJ4xZTW=BsNCzNFwnTtk{!Fi5kLX+?JO{4mzA*1H$w!}W|xOY>2B{qjS=SmQ4d>L3r zUCtK+Ss$HKLLE<7`sW&Mf($D7#y&-D`p2@+u{*JO>IWHqqarVmLNEXXu>~@KUDRVf zwOew`%`^}zUz*-^HA+NsuX=;w;*BmSFzP_t&ro6V4xYhV3Yp6X4=uo1-15 zw8mN`EbA80{CGN9L=h3`Tl$&)!U3xa%p?Vn(ej<3@S^0VN9mHI`HjmYSMB?)FUmh^ zt3~?j{&g+ zMZmqSF|f15$kUk}1VLCP+rkl@;it}am5ZF3a$h#L#K4OrkzMcA{snz;B2ir8NY;}>yCf!(I7v{A_2>yyiv zJtfx5^~#f=g?4to?Ybah^RwmN)Wxaw^)R#~(Kfms(gjL8{B$x;p8wZ{xU|Ue^Ea;r zv8S7PV1&CcZ<=(k;|_u3S94V|Q$^!^9P8@SQM;WRCkLldtu4sZAm)HhjP^^+3V^^0 zbX2Pjc~8#xCrJM!>p*B%qRQX5e%aD~kxLcwU%I`bQZ(Yqr~~nH7)X2#ewe2e8`72R z=izFR2QJ53j`e%Ke#1Vwrky_PzO&NXEXq=Kpq;=SmwT>n%Ciuzz1_eN?kOEKe+DHy zG2x>7@B6m_|2%329EcJ;=N-vVtbvrIv{oyEv^P_pxDT81gQKmA;!eY14ibK&42S7k zn`YS1DS@iNx`+PU+E(V;rUgPYr{2ljG86aU>P54#aZvn0u8#dt>2wNMMloKi_sa0? zgiCt`q?B{$&qgaF9WUg|ToWhE@F#X{s_+3v1>m81_eiHYAnFsqM;hdE^cY|ATUT8x z$|*xlzuAV|pV=j295(=!(K8vB5j6h+ZU65$+4H96>7Mtai9-xB-8nJ0Lgzux?MOsOi{qC$Wa_(U&gj~{XSMXD>spdOhcNYBE z%&~i~pD{0Ur)AZZ4BA*5%L@7=tCRsg^e^1GOnq+tA{?EjgQ=uI!tbomcn#?%#pLoi8MrZ-qB^6>#b^RhjAQC zG2FV!waS(&f38e%8|R!J<(g6INmBQ`v?5P?kxa9fNsbH?mb<%nkewq;5_wJ+VCDow zr5u;|Y@hI7FpyLOs$g7K?#NNq2c<~_5j}1ZZ^jv{jUg6AR7{4?&PLFc-1&iy1s5Ra zY!qmEUq2A=+p0NJMPV=@xhmzv=7qOzwu*Ys`PRzIj}IsdSqD>eM^%s@HN zKzd#NY48qGoGFhF|8RhYM^YTc!9Q4i-uu_=FfW{I4}>wKLvC_MW1pp)T^kP*U+6r- zGm{bG8?5sQIbV`ZI2JC4e_mIAhVRbn&y=j7bzEmzcHHVO%88#3u8YyIJwwor!W&~V zDz>K`?1`?yKPtuDuPgSBPAsYuT^ZWEoJRp(kJq8+MC{W;!6)NYZ?0jgxpU`F7^%A< zmFd7bj_8!-gU(TkSQo5Qn0#XOCC70d$j~=v4N?Y3e?VLgT$yFt5}H=;?FVGig#38@ zWA**>I1PYQtUSzUe2Fi%FvzQZaFPVI6t#VU?J<$im0Sav=aaBH~RA{7Yy5Nc``K=(A^zFP)Tk5W?f={ zCqan6#eFcw5yQHXSMZ5`shht@BLn;%a7(RnyU19C znja2`#a(X}08TkMkwfuzU5i1L6H$!O0oJYRk_5U9KaWdqeR(?hL1G#V-SsW%Q%aLW zD;Lx}Fv}Po!V7tiYqaGcCEUvUX0g()Ng!qsLh=~~>(H1V#TYfyyx$K&U8AO!a6k5) z>@x@iUziwu=v|!yn@mPK=b#I!OOu-O*$BtbCZK7tIY!(r02|wQOm+F%IYKir9+pS) zIq)RXD(ndqk$Sw8?sqDSab)voAk1Fed7JUX){J_;8i&xv@jo7cb1!ilX)uce#p%MlHxn>UK8 zN0pElz?N?W;Y3lHy_=QuFO=?$2EW(7JmN0aG2+Kdc|J4QG8B5=>S86ZQK;>{vG)m7 zhxcdv{(0K(WT}1|+E;Ql=)zto7w{Lv`JPz=T8erHRD38%?Gn?QNpV|O9~vDaEyxt_ zjHJRG));;wyv*HPX}V)`%Jkpd94V#NDH*&; zQWGSSGiNSdV=e!Cm#0wVlY_Yt-|(~0c8xWh%=fna!Kcd;vBx}Lij^)R_V@Y4nH+hY zl}b3lk>H-&avz~sd=kM?5>!?$r8s(w2#1%8k7ji$O`$%3%e+5_Ao3~#`8dO(qw>q! zmBN70?rlnm6p*XT-k0=IGH(i5SjfyH&1l$$yL?3~bhRa!7I%$xzgs74wY+RR22p*4AUuu-qklFK)WDVp+>mx_EH{4^u319GQi@ZDk z1qgh~uBDyAuW^X20Ok2Y@e8xyTEN+#$M>ON((`aIP#FnKD_S7I`K*Z!X`*(lSV_R|84cSs@u@)_qz4UW!hc0+@s&Q-TnSlVcYS3Bvl*Zu(L!_Mz zTeJOBWo9h%WAH-}*x`Igxweg*F92)1*F0L*FoNKOj=b=A1kUCu2(_y4W&nX;{1bdIKU0L73lhEI*u{tk9ZB7ZIY8iUD%Ux1YobGkU&PW%i>+=5z#ez$HN zeaL*UiAxntj{$xsSIir(FZ|JWd{7`1n%R~|vV!livka^iw|{F8AA?i3+tAI6Hb%_l zYobuw=V|_{FUMZ=!uD&j$-GE~fvEYe4&AhFme>G$r_hzZ9TD35mqR;JQX!7h{A95x z@X;%pF!mJB&O4>etBG~1qGWPsVlqdq{GohUlm8)L!?a*OWq4ZEfhRv>XmiC8(ZXOm zJPo3o95_DtLU+Lk;q-!~V4U~luB4Ga<=yJ>2EAi_#^0t$9r>-CN#B*J{J8cEgxhzU zayPny?0_^x69(idE@fO;{CH4~>q1JnHM2(j&l;EIJo-8+_V`gZzmU_#K87M!ZZjh*_Oza^BbM@eG1_TX! zrs1CWuj+;}VK*;xK>NSc!NgZ8FY~i3X)1N3lPf-@_#2Y6YTtBfz6qPY*b2qoG#R})~w%(TRBVY zyFq!wc|65_IR2|=8R)OFk`p@DUn#WlnXdB`d+`RtPY!J~$GW#Dvymbcw1ESDHOO^o z`nQ>MCHC!tj>`{Bh1)xS%mpGj?6m(SSE9gsB?&;?%bWwAp%%^Hk=G0P%|h6ls({Ws z)oslHSmLOKFSxI@a{8%4Kl#By@0iWk6bcrqI+Y*r9%DQ+(PkR@oKIx&6rb$kF^qT( zFOE|iR5?KSJY5-r#4H*3bML;z-}t@fC`<+(Q60!xYa^{)6l?-K5(JOd@QM1#lON^O z4xfdm5Kz>LxYP5X+uZQ9;t#sk93QtjUZ1}5l8xg_`%qJC0(Ue?-tY4+ugpws^rEaH zrexf(#cCcqG1k~+x)|+rr#O*ni`to!xSdxd#iC|T4r+W}9V_5-`Qa!V?A!wi6w%o| zG>Jny#Q^H+ww;qGAqIO8C+c8NBJhaaj}25koLZC>69Cq{HTjF?dSFShK0#a%G2)(}InWBP5N>*cV)0YtNe zdsC;qPlx-t%HXO_#fL9z4tE(H^)=sA^ylpTITY;urweN9le1C3jm7*2ouAMYjT5sgVpv3Sf%Llb{0m*uc8chJ1i_zi%HMZewCiN8%)jv{ zE*e#gUPkA(a6mYEuZLYnt(;Cpm1}3zs8=iYhs(Q~i~X8BkNEYVdGW5JaJO%WLRY7} z<2s}E;ZyL-xs?__H#Wj~9{_N4K9nI?` z$ZZDwu`%V*rR|9l*^Ni4S1OWe=y#_B{aJB=JszL8?~R>~N_^0w_GnGO5+5*-&>TyR zOzDeno0-#8j}?8_W<-6=^nI3?f7~D5rO9JNb<6R)DGhTb@`vtiPgD3a{F%r0W7`5# zDZO(#%$tYnT68M~;}IPs0SnpB2+H0Vka327O$c}H=!3sz7XS8baLH-PUFGEUeeT2z zuI5aPFF*-RCs7vIQvR#&m3cnNKS&+UQht(=E=7s4Lwc&vYd z$L+GBt> zdz1rK^WD13gk-27ZOoD~ z-R$N4$6SUnEl@pp!Lv*$a(mK2y<<=QC^cUpt5N=F=N#uh9`j%7mu5hS;~!_b(`0bT zmecX1gGnFH>Ousl-aS&|?FYH(a*B`!&ouP_$5Xc|vy>^#Q#7X|LsTF~|vL`nH(u6~>5e|Qx$?CFO2tJMd z*ebJ{{Q{LAI?y7}ZW-&pz?vtYFrLud1 zc#4V)9?2vrh2yNNZ47nW@a2uw67W5Ff6~=MQcWONDD5&#?aPPOaU%E8gL`73o^-uK z;g(k}7=K6lp;LTZ>GU~Jab+y*X?&>qgKAWLU#Rl2u3ErC)%5sg`R7DmbxNlNj8`<3 z=1>jTx(td=h2Irm#^v+X4Tj^P5~&aYhlfKqx)r;px~Xcv;&QXp?zP;%#0=^8+gRmu z@!-8+9&s*u4%;W8`~FD}(zYqP^-{OaZzGgmjx>pD1-OkHQ@)~(&MX3s9I{>}`3|Uk zgri8RJI{HvKv6nx{$x8?t{7wyIc?5QqV)=gTI!3hT0uH>-u|E zg^y!i%b1RZ3QzZc@a}e&z7IcBiv=s}wJ*N8e|SpTz69RDCE}H#AtJhzWp;DsOwVt9 zlUDAvqD?K1-I_te(ntDm1CEokm=r1|B&cy)zb>9b6E^(eKUp^)by{#NzmX;4_ zA17z@SW3bo<9%yDRtxVz3P$2P+pVkxP#9>C9W6X!{)cszw!Qza_msyDch)5I*5vce z-Q{*-TTH;1X_O>3>2;n+jGe#M;6UyF6u^IpHfoha*53K3Z@qznayjBQephy8v(8kb zX`TV}1EO!HsAS^U-uTTcaXgt0Lx&jy{?g4hth z^q*yL6W=a7SKI8KE?_J@a$J9UcU}1$^*gALrJDX+_lFnRxkvG;jra81(YcLf$6F?O zMR#;y7XRD`kQDoo#01OXqL+~{)$$ldsTuKKvtE^Opm+_aEpq()Y^xzt%~b(`ImKg_&yy3X~Wtqi=1 zjlRB9m$@BX;~l6nzBh^W!xj#Ybv)?@%|3u_rn2s4&o?^tjGvUoitKJD(<)rS_!)6f zyNAL7o*hyMMGP4@=Fv{BI0zeW+N>o)^~lx6`Hi6Sk(~bN>bi(O@sZG0{H zUMp|81_+w>JbYiu_-0L|4#Q^Ow%*nx`t5l9@W`mu&l%Lu)m}y_jtF<${PKx#>>D7K zmk$jVAW|;%XKxa^#dL)bKrKPzEX>0{^dE+~~3aBisQ zW)v9&kU=y+d>@e;d?kvYe$fHz?O!&UVRPYPZRvCmB9a?R9qcOYf7z}(D8B7BpcJaK zN;Cv?n;EQV&AOYNg-acX$`v}PX2#%cPwO0AELMNp*cIsWjUIF$5&$eV@3$mGd;63$ z%Q;od8n;+p^JL}BH+~5r=GUS|SgGIV|Gou%fHGR7!(^-R`wgwnSB#TOFF)*KW!x~& z{jRNj=3Y@pgkZC857o=*`}{&XMC*|O{r4E}TD9B$P~aHy8e?8j48}$HzVe@KZFK2> z|H`A_`;iHoOIf=-MZ@@AYQ5FO$fvLFe{y-Mb%*_6wP3moA7{hTc1&%Ht&Dx2Z+c7- z%xX{FbkWXy%9@&`zxSeq4|;gnFP{hS0r2P`^O!rD&)Q6Ee?=1at0p1_&;nKd$5Yw4aP0GZo~4UQu;)NF1~WfVA_NZ4c) zu9V7KRP?O1urDk;5L1KlYo#^5Hf54b#|Re>#w-r}Yb9BJ{{a~fDXCPH4u4$$))igZ ze1KLAKd0N@^2(4k%M=`eyJ79dA>;TG?ZF1qBheek>X^fnLmhVSe8#NF&~_cR;4zL+ zsB{Qx90<{Zefb|n=NixS|G)8HDN@R}RB~JqB8MVpw&YZaRVq0vIh4af4s+N-l8BrW zHix7Waz4(;oMl6qW>mu-xjs(B9g%j#c#U#k>{*b}dM9v2g6DBw6Q6cn;8_xWKN|6t zZereCzKfmH&tSciv4(vNx^B!V;A&-0Bq%KvCrj$=x@Pc#9eZjO!p!}GQA2*-GlEXr zl`dy(w|8xFUzyA$&g6zRLo_Wv%t~lA&NQESwq#!Xq((8&`(@H>QHCNhka%IeXtr>2 zu4_FkaNuML;J5jO=*LiVK2k*DJb3$f_ zv{6v7Afwe0DFb}gj#cSS?c7uU^&0SFofgG!sm~-N{EQTYi2O9aO*C`l?bW@(w~pv> z*eE8DEw3=PEmI)GlbDb=|8Xn#I!d6!+L^-pI?TK!SWRX=RFY3@pULx1Tb(ZA;Viix ziut&H4K}*Q0B&8|SsYMQqjIBgnywmd*cl=Du@$4~I~#GnBBth~QP>`_v29gYHBFF{ zloQJ3gyag$7`^U~T)&fn-K*qj`&Hx~lq~0+5u={A5i%>ym`hI(KbyM-wOHEM8f;zA z7M*Bat)n?K+ykj7KgeevhPDUuxNwSPs>E_Rpm#AmZ%35v2JTi0?1ADy=N48v(b#nh zc>c%S8!KJ*bE{+80-d{>0_V;)E}-m((2XSQakrDuq=~O9GB_un8H>`>rnO#2VZ%C> zvRj?fOJ%ne1HFslLLYorgr(`TpdqiSLs_naVN;gnZ%XH$U-Rj)-e#*hgn=VfUpxb- zNkoc&VI8=?5%DV6Pj$<$&2>56zgA@)eltnt(^C+cOMJz9xu#l4-}&V(IUMsL$e~oA z_hPu7v4gZk)?JEs(HRQuc}5m|1s}8a&86;>i}AQdOIT4HO&fn&G6gu6YQG+ERZvVG z%3JmD)!Mxq5YIrs;zL{|V4ugE)6NN&TVJ=C-jWBRc4P|51X!IO>7$Q7#%Jh2Rl;Wc3VderheCojRVI7s>z(MUYtw<1jrevJ0#I00 zWX6WN^3mG9^~Wp+izQAKX)-d3B{0Sp<N)MfJF?O4nI;b6B346^TG_xd=2W4~lzAK6_virr3R0hH68AG@HK zwpx@K=_fid`?6i{$<^MQofuRRYX7YY8HMl%+>nmEY4>t3grm!VH#$5HomcO!`Mv=eft zK_7qlnK-0wQ<@NbP&4J9d!e(e^j4!iMRGpho|0>s1S%fZ!WZp5WoYoBQk9#9?s^x% zd!GbC1~fCItWqw0tKU#ZhyOU{C9@ge>aPaJspR&A5M^(_nZ5OrnenFeh z=0z(xy!FQ<=Cgp8sTGJK-U7}_e#>V2@HTG1PVacuuHL`$)q`B(ba9uQN1cT1@_ulF z7f_qlc53?$@B^=50)7>lVk4jdF{IlgSPWbC{B$d$NnVtE;^Pm zoR+s1oFGuYV6L<9dj^uzO@s;68P3NG4Mz?y)@*z+IaX{7Cu<&oL|#s6w+Y>8mI1}X~`u>7O2lS18KJ)`AhsdNBSx9+{T-~ch{rN+#_ZZE-ct{ zy)x_k(rL*ju+68OP~v&CqotX<_LdWQMhdubT~h1${QlOU&xy27H!17A<`bO~b>P;` z0_2d%J%sAYJLq=369KG<&SvD`KOwD1rIYb3Kj1Xp@L-7g%WBJJ!F^o2GM>23$&PuD z$-WEyEiTDZ#v3|f566i>-KY9Oyr65+krh9l_T1m$EHVGiTA1{_$y}8P+`K1h;C~&e zdPYOYb8$`zigZo8>b#+}UOCObvt0)jj^-{1MB#3`m#MHPrm4WBXxwP$PWNxJDvs1f zL8x-|*H$+*dM>i2S9CDRwCu-KnIDmtcm_Fd9Q0pQCGLDmq~Xd$nk&HwbH2OjvBE!- zPeU@UHMVz$Gvc-{?mF+Zujph+KIz2ENc5Q{mRF~#x_l-Wn-fkZ9=|4U&p$(>jl#($ zn+jX^gl7c5qJIR>&J|#EToaFlr{=FI%HVoVPgIajc$xMz)pp)F`iI^z)V8Q5{xe8x zCudi0N^)Ms4-%u#S$7HhI5Pz(LHR|MZ-A6-r+4-v>|>& zJ5S_Nw7RNBMAJz_GgS)>o?)SURB1Wapub`tb0nu`tr zD6Z%4D2F*F=2DlS{ifIWt3^NZQ=_-hz-sj2TeMlWE5-(ZP9m07d<=3#Vl*#Mf@m>c zSvs);r9ty!FI<#UKZlFLqI~0cy3$K6BZtnc?lVVulz`V&xMnwj=xfd24;kAL7ijXJ ze)f0&gr-ANm$%zvXIWA!HkhQXdphFX+3+{*4RPFi4F;4yzrv{fKWs1?gY|&Kjmlo) z?KS-bNPh^^)UzR~K9`BF)Yk#Ni;yHF>o*AwguS#f<<|%H`+V9y;{?PXwKM=1PKs8v z=8qu+Mdx08{ef=mGv0g^DqCDw4}jl>h{9Z)co1#zLaKg)FxfvLcf_XEXj3s5;{SL< zotwC)pQBs0zci`3K|AqBjP6>8?&qNSx!#~sZE(3!lje-5a_d#=1GoC2yG7aZmy{?; z_AqC5>ZaVTMXgINtn%>R|Inr3A9wjun?J}2xZK6|%9Xwhf> z7*YvpR9`gYLT->CK;!Ce*u5K|R86i}8~fbS)0M`bxwp9wPpw7k7Ln)*^*FOF<4qfr z`T0}ZwoXTORAX)ew;+F+5J)NE1Xr{cb_wC>mg`&I)+BMOqR|yMa_PgHmyrNp_2&f9 z*^c4Ooah1jy0M(e-jv>mz$n=$Q|vF40+xS>VUdhEH@?(dc_~G9Tv@igG<(BqdEWXx zM`NG~q2N{+DrNM?;`~qC;TQh*r)K}R=1h})3vziFiBAKD-#n%mc3ZXm=e_N?3YLnK z+j-4A6g_6Sd>a0jT0Cv|q}^lw1Sz86a>sSmGZ%$Q7f(=1_eS+~8%f^J-O9tOU&Zeo zhxF<(PYCu#%rs${FB^dec5+H-ve-jJOQ2);_ZjysKecr;Nrt^sL8SHHC>H#g{G9A; zUSfd?GNRK>KP)nmu0KYuOjryr?LFS!7aq%3FT*$w_M_h`JG|R=@sS;?t4(t#-zx5O z9Khz5l-K_@PmG+jEhSu1};y-k`r*^+SW8E06 zcX*HgAyK6+ZL#h*^3SI)N#12JG4&4#f>e)_&uNm54_vlLs?+IMzkA6Z@C{JXR^&>1 zd}dl_l?SI&tY!F+QwvVh{or==rzAMY+C>JiL3GWtl@jNbQ($DeBx^7%D+K+U3Znjj8 zU?EeVriVQJM}OR=ytsf_5NjS;IQn~#C)qKwCs7hp6P(Wm{JqF+9u=&}jM}Y%@}TwN zKP#b{IveeBa7f9jEiQ;H%E&+K{$)p(CKQ$bxQ&u5IiKve=^hGEfg=MJawpNq6KJ9~ z>FDbHvCTq~iVJS%1|z+Btk1`(KkC7m$1ZyD272pZq;8gGOyLe+4L0W_#XlVR;b=D@ ztzf8{-I7$P(l7K(eHH_*ekQX!*$w_Q$@@&e8Zb5b;AxHy6cY}aQ)%%z5|wFO|45=yBbd-Kb(8RS>fmlG=RZcg zQY}&&-~j;!f57S?^s4fmKe-Z5u(;Z+?$x=5(A$${U)nlQGFePWTzMlovL8$x`H4Jp zJ=pbbqWo_O;}2p`4k2=Yt}*eK7#=i?33!Lmub5?Ng>a3HHx-R)IL=Ga_gofbqnV6M z<H%rxSw0E~H z9jC;A6DJbR69aOHj+Skjr{Hu8l^tw&Ki#5J%j#z@ar{Wd($-)Mj>nt(+k{i}s3M2h z^Zb%=sX-*a#jJEZCR_?cx!U%Q9x1V!q0e_#Zdpm{@|WTKkI|L^)>4DA{4Z{Qe~10J zGk|W0C=8Bz$%Od6qL=8dDtb4U$2K)bb}2rkJ%k_MAsBM2Wb;Aq3d+RM_nl8cwR0Oj zNG9hq%&#Td6qyU3xp*)p1FzGKceuU&ZT~_jJRZ1Y=8HOgYtrV=4Y+uGUf6lYg8_{} zjLvB8PmxOxer`*NEm*(zEp`3my1Vf|p6lF4OmnsMr^2^UrNg0$!2mpd%f=*DF3y!f z%tB7qZRgv{U+z5teTR}EdH^y)(yCVKpeUp8vf+fk&UMa3$e9z{X6ct;m{g?!@ag0D z&WGt+!zYl_wZf*~&V_?3kD$)cTX)jyw!*#}=uToTzj-?M<(O00%bQr=aPy0%uSRux zY%Tz_$wsOU%q~}CSDY1(Co*tkZ^!rEd94NqYANe5!eiCT%GN!du z)OedjLt7*2G|~j6q5>(K1+DxKieZnvOra!V53`hnAs@S>i6U!FQk>g6p>zL(ea+z^ z|KlIzC8bx3Pb`s}_1?#yZp=s=Z+Y!9ru$N^)GL{utf;EzZ}B$YlIPtHmip1)KaT8GzEf4#{*|S)rG503 zG6R=u6oG5CPL!|yFe7D2h^Q_Ul?7>%3Rwb}p)XA|qwL18I1 z-iWAVmQisMx`*%#!7z867!f&L+#26!D3V*GI5@X?IAXZe*omxm(Wb?IiQJX_o~y5u6REYopaF~Vy5jFm`TSte`ONeH&y%|my?^b?|S z63STnn*zXm%VXPZfevO+=0r^9_uSn~ORc=+e~GDjkC@U)gCXx;mRp&XZGa~q*$qTw z6QZrw^S|o57tJ7lvj-cUo{hJCEY@=1tz6UwKa(GS60KcjzN!t8nOj!=;&VU1?`#S*k(<3Y5xG;n3a-D(LtKmYi}_?$J^guiSqVn05sHJ97>3?1xp64h~XwT^R&CdF>3KUY-+ z{kXAS=J0;Z)UFMTDqw9P?o%y!i{$Y7*Jy-tdE?&@%>mP^1$707hf!T8(5;&-CL0F9 z%5X}ft(bQZkf#2)H>l}#jQc-V|C&HR7Vmn6jw&2&`!76&UUz5RA`npw8m)P=k(aUR zToj7Zt(fhME_T>F(rh^_r{I>}UF2%PDv!Opd|T?wMG@@1>(H_+hu8+`OWAO}csNex zQ+skK>sIOZ*n!t+4Sd$tSC-PFm3O&_lG&5Nk6cwiW?RWrNi3opRN;T4=RP(>GHkZ1 zMbbm=Z_az6>E8F#k$Q77Tn9sZtL9m_!xlWonLOP;IV%L$37f^loglRd54d{)T(G*m zTg$)B5fYb(FNu?9`Q7KLJ!2lUGy7_W7TykRd>b14I5cQv(6Y};zbx8jN#}^6!}WG| z8(>|`KI4-y%5U0WJczBVS_$yq0gI?d}q^|5hjH{f{D2u{i7{eV5VVr+I?^x0+N|%^QcKH0YfF zL2t}PRr_oG@0t|n~I^_cnh@j z`|Rc(3vSSwXFANi)>2zPXP0rOw|V03-$cUKe+P)uV=j;lOG4n&Zh#wv_5DigHAq^W zMC;4BGg~UbdYWg&H5DN9zLJ#QST|@T@Mr7)Z>b}0E6xS=`<0^<>2y6#8N@h9BeqS=%im=)}8jt)Ik{`P_g>hB9YJ4T=}So`Z+v z*1+Xpd%gv@6rUCxPjn%+{RNcHq{0Ry*;?ZjN6D}G@{EJ4j1a2NB3In%6sO3Gm)Hjv z62wMdqZOS(b^%S_gWU|X@fH3)`m|2!t0XmSe(6^D2pTzSK0~nTS^TI}((a{tK2nF4 zeG;F6-O8Fc-Ys8>;@#K`gAz=@_EjXAW!F7v`6-d83rxldqR~iV`%c*IY^T9mm!fv+ zR$5u(boD`G)+6h$8o1$2PfBIgfAG=TA;Uk~2`2c;3J+$Uwd{V5?mu)wlTL9Z_^kWG z(ivq~%cE21aMzy3ea8ahX8+$W9n#^UcV_(RBEEuk-9~h==K%X*GJT|Uc?;Xlv7Uww z`cm>@A#0VO$E2%|l}weR^ow~6 zNZxW}YhjELc)Q*cBU6VRWVZ_gM;rtpKg{oNg?^wcz8w8w($g|_RrYA|h!?3e9Y~l4 za$m&Du_nLA7~;XeGi4xcZ!+6^PKaucv1UFA@8jH>;k=J}8A6m@YgKYLn~%d~2M)_5 zt1d^zpe<#FSeK0;Ds|#Cd*HN%R%vZ zTb`LpV9}#1UUO?ykr?ouDh=6E;2!x0_r_-JkOyvN@x=qu)Oj-$cGQc zwr#uD2hRq7KEIO?oci{Djh1-I9oREjG253(H}Z(8o1gj?{VkWfc;e?ALT)L5j@iL_ zE%0IFGDKf5E{bT@e$ZW#A)A1&781Qe^)apOfnKGZ|ZUYgx+|Y0-{}1F3f1uyo<aD=fE7oMJNH(z_+ zG8?RmFQ?}C6?aJph74AV-U(mwYMeP#=)d1Ozw?%9+3B3sw8y=3PZ!%Nu{CziMw>GA z;jYJ9f27q43Uc^H>GXsKV7CcI6`g>UP7hL9g!VjXTkv>%Z9t`L_T-0tAL!BrFi-pl zPL)l_*uJB z6OFZBp&oVex30X5tW9xfPsW8D{Sg(+AE?8I)Y-r#`gC6#eKT{1WfqPX{K6Em&9ClS3}FFZ!6N1gyaS#uo6mjTHM;)r-i zbb*26dK7%Wah{UwA#wMUsQY^$gS!mr{FLtzuOgfizd&+4}#@~jVeiIWisULnARISdYCcvxTv?+L1J-B8J?`EFKt+VMbAFQrY6&tNA zqQ^uNJ^LJIkD`{d6*uQ!%b+(i~{^ebvp-Rj<8ZcH?JlRU&gJ5meFOP-MKe*3FI2*yl0I zaMsF?Awj@!KEm%$YXayFV`z6OZDV6jd6A$?{c-|j`;_AN7ozRV&D6b(ll>m}{2 z-3<$juEDKtuU8!hU7!m#>-r6hA4O-bT?_9Ebp`Pa|F)c2DF#j*IhG8X^#GkY-6}lz zA*Ec1y@zBl{u(FRT*^eLOS%vbR2S3p{jnq z2RuqU78cr`n8f^wq90oAHweN$RwUmarM;0MNzHTgd*+eqJb>l;IQ3R-SB=3_NY*c= zh03)8hob`lI*ZvVYhr}2dSwHeB+_sAAi62!-A?0$Kt>4s zCF{T`@%KLJXpwug?@^fbe*Hvwo9@~>Y~^s#Z`{XffVu(k3aTtsgpaf6^_(;j$Oy#X zrorODsZYuKazZd=H2+=*2AwLe@cdYe+oP8zV(qtu!K2quPp4WSyuW^TWFCcx?}1>&`(Oj=fRU3 z+RLokOId1DQ>o+1a9lbC9gEig~`@i>~tsUuXX=UaFBKHJ_7o)@$aou z*}S$Sb~ZR)|8Ce*OFtL1XQ7xg&vDzh*$zq+W^t7#q9kTM&-*OPg22YrGSt7S8(5+6 zH>f$E+Ll|l{yn9E`giSb7$?Wdc~o~oX9+g^#9tJG$1GeFUG{Kc_OawZsNpK6@WQb2 zv0tkhY|<0CojXbS{#ULcpG9g>-gz%)dip6Np2o_H#m!cDlpOtI+%e5wZOQmEEuFOC zI?>IpX*wR0Rkf^4Oq2kfZ0u}V|I%sqI09i%F66mgYWvdMlhU+te!Ju38HBLnA~SzE zKbMnBhpBw;5Ak-)3UW9{0W}{8_|doX*vF(!ZEd_`Bow-y5^~2(6uLk9H*|^q&}U2W z&rR4qPJ`-52smW@@&l92uOyHMR%_nnc}mm4s$|5}T`M%gn|rUsvz6u6oz_vkw-d`i z^&1^e4>IA(QEykyZxox>29_Ah#shBgg@g5&`6T4l^T*^{xQuOVL{6~4nYeGgplMdbtFE9v*FUtzgjg3@V zo<3X+9%$}zwPkC-oNl_$s^im+1BTl_2UWVxwO-6&Jx~QvPfv-9EVk_3oBuEq1i2hj zp{Z72UKkH2+Ptm@!$+d~WU@@WEtYOfIx8*0Jm;31wsYCMcH3sg(8ZxHb*}GRGknRo zB1V|6E{<;f<==jB&`+x)S2qLhLkz)or8#bf^gWFL(7qE?Zkarc<2?(P*}5!b**Cp* zba`vrg!EFf-I8xMc%LlNaAHq+pg_FKXdf89K>mc>)WqFCX!I;8q=M@m{fk&mnjmTt zoOJQl&pIAzd@y*SzSfcjRJ{hB|MMovFyMKcnf}&&lfn$pc?GEUQdKeDO$Gb2V)bKE z;`kfD#xwKwxtImdzIu6(UkT*awuIvH){f}*!a++q)y9@Av!lg5NPByD`ynw%``F+C zym(K#gz@KMQ~L?IgztUG#r!gE%24=||93ag&r$A9w+vYiHqN(x>+gM{`#%4`Oy8<* zIYugTr|4=txcV0CRI`f|ep<1>^Xw2nt>Bd_2$1a16y7TbBjsqlF~6WGcn?@7k)g6C+UtQfd2+U^@)D$&bs_o%0XH{=?)g1hr0 zSzBPowMWwq@V^%;{ew96gv-@IuEQHS!+K?I4C@`xb`k*hQy2~y>9j!L*mK`4=QIT0 zN3wTH7wmWtURo_$?+)ZglH4OD_Jt6A2ScK53Fx^-37QsAl4$I5J}ihw#U3m}AAx_w zG9^VHV^`OU;LiEvG>B#U^3BI0rGL?BOxUXpSDt%UA+5lb<`P2VY5W3rM}BIT6x)fN zhvnrq{jnij57Pn+ecXPQFuHBq5w&4z2%Aiq5yjNAoPIYvwpcHku_{o zIxkcfG~X5ed|j*!({gt_xEu;IHdr`MAPYsM?~QCPZm#9lr;GtpK?zkKxdsiwG(Ts= zIfPp*OMjN+0DZL@AA*5z=`SRn%s**NE`=A269~dFtxWjx)34(3s%*y2Hb!F6d+7ngv?gm_jr6V0gRvS4@omN=*13>;yF>?-g^2|qJYp>bHAv0^AbV>rH_?;5& zvC4Wwjb~lu?MmA3*AI#%{E8aRF;(wIKa6zI(a3KSD{pxprKGzYC?~cU+r>V-IOBhH zH72MXZAoq_KEy|)-(5NK{i?%X<`AXdku5h;dK{^*$v>I?Y%0Nz++MGpdYJaew{#S% zLk90y%5C1zYIh(+QDbKC4W;PdjDOR+hhfTuV1}tp|4GgZnJufst_2XD#4>nbrod*0 zPchJvC$;$wb|H$24zwQ6hVVzY@LqyOO54UBC+JuBnW_N4J`3jIu*FLJ8!$Oa!nBRA z9rRmn3+@GKf6@h8csiV$lUx+)kFi+$ZArfW?gtz(hJMYx$kOTScUKU13X3%;3+u7ldaU*td^y40BtKXBG3+XIZOp3AfToa!aukHKFIa& zJQ)NOdN=)>a{*M7#jkBY)qdqj%;Vssq+>qjQK6Ua#kUz|h{$0@?73qmYy*u`S$_6p z&}GfV4megvoN=FfVrL*N3Fb;d{0VlQUrLTfd$Rnddio*y=eL;Kkt0!V7Q_AlSzBH~ zz+<{*y&ubF7ap+zPuip?uZJR3%8i~f{Ur@#g%ywIA?2Tcaqu1KN*#c`H{NghAuW3D z)(ImMVQC4Edn%RxmOrJqQ{A?ungwg5%G4rvhD#=Y01By7pq{=PbO6#vXCV9dBYeBc zL7v_dgq{~7aKPjr_Ve#C0iG4hc*#PpU}*xqst+5^YJBgne{$o~p(OUZ2Uim>cKV(& zxP27yEq&_=)jrj3pgx?%4|z5x60OoVDC?V~0B})(ya^!TZ@u{YNb6z5DgLkTfNOgj z0Lb;pMxeDI;Ra20%DeL+dvGbFkea=PI2g0#Gq%)!eIR6@$-0+p*t^&w3LU-y9ag>l z@9*CbWgk^QVJ7rpgkD9v^Y%A$o4e@!uV&t?j)JJh#-EFcQNw%llby0 zxc5w;&hX?c__n)@m-}?9OzStr@~V91WDx!JWX+cZgSV%&vOh#%B`^yuA?Y#eeAg(P z-#yaC%9Zz&b=h-)eXd^QG__{#GzN^bwjF|>h{_T#P!9Z6d4iTQqdy?v^8HDaXr~_M zQEWtbJxS$3P+=3qm>#ecL2ulHdAeHt!EmH;$eEb6L}gfnEN_tT5v2?(N@{|~j0ySrD1>wyNYdSCj-U+%EPeBqUUN7b7-de1w6GEvIx+EXB{bzDm`IEgke& z-eV-ONAZ>$_h{2U0QsYC>;#BtVFD`jvwPDWg+*PW?nq5!4*j1n>_E2?`UvqdefCOo zWqHb~|0AkmFP&M9esC9&$-K|i!XC$~-LZszlD;+mvO4i3tF{5sdnXA2O(OARGGq)T()v-bK!-BQcM|XJjKR$OR4Rw8IA)&Zo|cZn@8J9Yfj@ zc;v}ZBLhfeOP`RlNvt3Vk`a;H*mtnzpZ>Sl_O%Rj2M;>VEV=F!<%K1kqPCx-O$AR) z`cyZLEkqyh?=xN&sC@;ET{k&jA?>v0nJ&E?9~um=Cq5x7q6=g8;%q7}n(XRIBs-s% zC%ixu$h`3>Ct7IE9Sc1Rh|b&@c_jhJTdY29Lj<1jFKc?x{NcA zt{Q5qa8f0f4G>qpD!EyC^T$aK)+G+p3&rZqRHizwix}WUkA>c7?mK6qI2#P2O*lX6 z$9oR7b+ue#HY~qmloh6_OSqK#JOT$o=1gt8Lp!Z+4K#i3n5aux_1c6F*545HU^H>smLO$m}R%dWx1liMqc4oV?Eg< z`b?Jf&5lp!@N2?43-v5Sv5T>-%OSi@8Xf3#ta`YhM}8KEEy;~|(vPVTF|49wVK-qp z^&W!iJ1KB;8R#LZ!$;c}RYz-w<&@Iy73~FiIX$+{q+LwCBo7|c+m>60DD-|&X_JsMG%%Rl`I zZTSy!V>jx!>HRyvppF9Tt|fys*++%nJ{bECkHu`Ebs=p5tHfJv-^>0)w{!I2|8uWr z@1yTd)spS+gjo&@U+>nLa_otD=H8jQQJD|-B~TDy+f=2siQGWH%eSK4daJ&Li{sZS za)NHkev?CCF5eGRF<$uuThDNWU0ZjazQ!IF<$1?~!CxGtTzT8}5kZVeCeECF{5W<5)a)2l`Ud(#};t=B8$SfS(Juj|mN zV~u~SL|p-}3pPIg_NQbpH-G+6R70mNxa~6Qp7X~m|0p)1;)rGShuKkA1s90!r)b(X z#~G&^ra)G9HC+28PN?_MsMo&|m+=qG_=FCzFy$834P)syNRLStSfaNZ+)vnxr8og< z8w$N_?-pH?z$iX@#_ym+fJdF2Y^3m?E?S#ZBw_y0B9KkIC%@s$MZ1Uewcp_Uy1Oki z9@K9=8JRdaoR3b34o)As=H!KmmKU5~t@R;X;us>{p+`FkxY*<(r6auO5rjB`=M4nJ z5wT(PVL+#ZtE$5gcRn4gWCK3J>DnK>@0Vx=gKA8A;zw8*_%pJ>?N~YGnbRDQN*-* z&s5F65Y4#i?|Vftn_|zY8BMIb(HeSbOYZ|4^`s{^@&U=_U)1@^0ZlIUFyJh>abB4S z4RSjgyx~plkX>+3AWA9n5w^Xl*l>9sj&+VN9woeWQO2XvI>-eb(}F$BPO<9^hp&bJ zNlAoG?_azPn;zoRdwd}he-;=#eEl3Hv%DP}>6Y6q zP=k{H!cJW%aqpE`7O{tl7iOu1#eQu|oa_s+50gIiN3yOee{uHIkNBjU1B&-O!gbFW z{qI{_&WbGHYdQCpkiooCAunP-u{sglwF!<8iyO$9{u{lQe?cx01@PU|a z<)Ocj?Y_H&hYu3-;nx$|5>ar%Ueu=5GNwrB$WpB}(6swr3V+=~H z54}^ua_)Y$B+jM?k_16tgZVlf+<6ecV+4HNgK;x&1`8~=Pfs%QHXhw2{ZHlDSI~VC zCovLwHRStKZd6UuZm0L9nf*O+9(AW=p9v|h%{@=tlc^nDi9uO3hh;}_dVV9H2<%Q! zMjJKu0k(0ged#Lc;L}a;q>#S+zQTYV^0{#i(T@-3ThbcHZ_$yT_$bX> zSsMB$@mHTs7aJ#JIrmj`M^MhpYzDNbeI+)^p^tFRhY@-Q-y>gr|B`ku+5N`R4_^*y zh})nr#@HET#c%COVG`EDsVFf%t|B-_=7Yb8r<{j(!3ERcy{muQRE}G7<^I<4hk!b* zW1mSMy~FSF^%fJros?(yC%h);??ns<*J!IT={!Qi6J1JI%d3K!5DRJ(LlI>3Fj-LH z^(valaf8Y6w%uswDSEag<+3u@v|QAJ)Veo#KY!qF4&N&(^mbcKmzhFxvz9a8{@${{ z2xi?Zj7wh|7)9=YKP*Hv6qu+tvQUX3h7eF+XywvI7xu?v^nw&KZ=u#lQc-LAo#{_7 z$?1F30V`8H2jdQ&lzV;9^XMNH>CPt-27lCF95IkSpjc7#Ho21Py++S6&VYNCSOa3U z0x<2<#&L4J^R}eEr!ttRO>AzF1Nv40oG8yKGan;w9A=<%1*;f95Z^d#e{=VBh2P+w zoX`~LL#vmC&fZ?AzFH3lMcAdS&l@3#w*H8KLieli-4j8=(OQB6XyMLR$h^agHSOJJ zTZwmImk1`b&snApF98#V+^iFhn@3uNy(>ldPI8-!|iJ4wfJZ>sV?G*`aP)IPSDt4u^L zDht&~>1+^bYidD6)^RUYZYiwMU`=Y1j%I_>>vf;X_s_DJd3 z64-?!KvOlC{^fr2DGhFG2HlcYoN4J%?L3t%8#Eza*bH?3b^*@>khzyQvXrLA+pok7 z`vJQ5GV0X;;L8$-F4*c>bRj8Meeb&910u3w=z_)y z1qY@Un}rxKet)sX#C*6 zhRl71=Aj#=>KLi_2gK{EfzG{2%>ULD`AP81$b38Qa)&HqBT1UY-OSI z7Ukdm+2eVMhhWw5rZf|jhg#+Ou6~5(9&*$94~Jld{1L#(Nb*w5Zu4msoQbhScC}Sa z+qL}ur~5LOS{4jAuU-R{nU|@@gT4DfKUVcWAkD+5qk;E6GEKky zKD)6VkNb6?$<)FwGaDP6%@1MpO(OG#9}B07Wz;_;siuncVVI zCMD~oRr7YZF{u3JiapHkKCbky$7iGk>%YZ3Vo+T=%|asLo8vn2QDf0=b@=V7`VJrK z$T#5A8(CZ7vF4A873aR2&aG{~%lVYjdem@lGCSAXbAf4#utl%WfIJ;^Euq2EDJb=| znsu8fJAu(6=W~*I?pTLl!SVbtda)i!JM#N;_29orL}nlJw_t7P@Wv|p=x()tKmA=7 zKHMkfHFQXL=j_%Qkpys!T-i*J{2w<9aJe5g|I9>aIwe}z_z75tE!2j6ukr#}2%j7I zd{m+$j1*02zX2?%$=geKJDVaGJim{8GiMhxZ%Q=6hCdfWd7BkPY?vj%S0!Q0`}1A( zc0G=pvSB$n$sF4$LZZ9JWWFZdav&O+ajue%I9Opil;$PM5y4}4OHB((tf&{vF-<8E zk@KLuMcZZ4ZtjQje^nuZ^R)dN_9c+v1%Vn>iBMYVtxx0~*qy0qZiTMf(e9rdG7%D# zmV!;s2mSXaT{POK#38 zY-3r^(=5R%3p-(>Vo=r6xB8{Z|0mFtMWlXr7I-l7FLJSu9INiTdAh&hI9JX0K5E_y zU{q^TjpWR@y0i1)c?*WJTvG{NNah4ItVm1CI5=)+HGtL=nY(@sK;Xy?uab~e4AB@1 zL{veO|3UEw!DuNKJYfFm@YY-8?dUh8e3d2w2rU#9UoW`6kT0+XD$us@z8i&$#truc zg;1oF_Dmw%xlIr=lxDQ?{-_0Ft=Enwn0j`|z;opn6J?Y5pgNQ6{R`IjtiG5OFQ(sZ| zg#g)EaZhwZY4&bO|G8QLDjjWw_{+FKH{77AY9sCYyPg^Q!YTXNhFX>LX)v(lVn_)2 z9q>df@Nz%24J{H`BiV*iS>trJ8?d;CCN73Kb$Q}u7d#^Nr`(DYszHj`n#IW3CN_+${nHmrKs_ z?K|!!VLCAYWo*nP_epXlB`YjhAycO(MZ|Nq_98ZaI)JX66Xdfbqt0tp8NpYaXNYbg zl8mFzX2QkpR>rD=q>Sqj;@?7s&C2Wi3dt=g%)!t%d;0v=N&Q~|KO}Z$M()~}Scfa| zdE*KrD!L0kMObKhqJ`U~JKe3cD`SvYtM&>~B<3_|AhVubwpVu-oe!&Gy^k z7*`&0hqVU|SFB6MKSl$VGoi~WTHL&J%Ft>FFRPd2@#H|XuHgru*0Vxn7GoIx1Xx}q zQtk!x`Gj=5WT>)6G5cPtP=S8y8YHpN+7Vej7*{y$I&UjMPpckYi{8B7-bkmKE738| zAxq%=2&VJFB|24A!OiiG##TMh1nlzr^VjJ1s`^A*lZ=GfKGU9WjshQTG&@QPYq~HI zbW(~;X&vJsy#>RI(sa1dMK#}lbAda@R@N#oj`He{ff5p%iT#=@o{uga&t~xE)>xk`3U>PreYkZKq}8{R z$NuK6s_*1phIVs18FK>tsWX^+H@N2K#Vy^=M5AjMLH*QXTkAeJ>El_T_k1#7F{YAt zBKo!lyL3-xI2d^ukRU$Y(#H&al`#K@1uE{vHzT|4X2f@9Su|A#Zu+cf;WsU*n^8d2 zNuyH^Km4yR#mDr2iEV&n`1I9q&tj`qNq{)H`g*(FLY_23bO%>@bQE5?J$?R#&KHr+ zPpoVur!tc+y9vByb9mgwZWAW-&1+SV>eh`7sf0=t^Sd%ZK>K1yaMhWxS&xuFNBZP> z!z5#@;lD5?j+N8K)-&%FzbCg*0{R}UyHKKLMy{Gj`t)W@LLgeuVwz+Ve_f9&_cw~_ zQsOd+WNMl-t6qjz#Hyj)iOx7Iq%Smo?$dxyVazb*%W{mT^ozS9LTrz>;EQpohGwV( zVxq{;v`3Oz_JLmoH$pzmYqF+%E?y9K7>N1Saa}jUTh_2sBP`W+l=%8c^PRQJ{HkZv zFIM@BhE5$8|6Q5#DyYXeACpr8J!vu@$Q{GRT3PfoUi#HOeG%*T9^WOM7^b^`2JAT` z9E0vI6~EoWoF{;v$Wl)megz7-&TwK7_TwUDX?javKtOB6{DhY;=WxVBYS0mj^=xRW zT%3GHJTe5cBVrW^j8YKn%ONy5!D(A=4HG4{ypL{0c*n7&=0u!oS7|0RBnWn% zZ@|X$-fXY_IL_|!o5(c+B@^Gj1s~7*$z7&D_3>(dg7|CXD_1(Rcb?mBzd8eR=#87a z#@2Y<^Hg$=>%S-WDew3>;0Y25==Vh1{ZIfI>w=-d`(&N6_%|PdHCA!mF|4X7u!rDV zV{p4|gYdi`p}4RnjRCy!i~euI8W5-=$S>O>+P~gmZk?5w z@IqER0yf-#FmqXpH#pZh0JlI+UW7H8Q6uC~4nwdb)^j@Yg}nc0d0%CyLK(#S;@ZP; zhU5lDFw5H=$S}&G1+sc?Qpa8Wu*dcHl8tYUhgFJihoBu6XN+-X?At15{_T$sZU+)? zxjl_42uAV&T<~$k^y8GraK*?X%%L^mOpge$l+^en(arI_&J4ZN|GF= zBvdTqFl-BzoO8};BS~^t&c|)Y`7~#8*lNZwj5&-QzxzCXzdz!-9@qPNz248KJXR!= z6x$mbPJ}l6<)r$rg1EzQI!Q)E(iUS}N@csGQuRh0n@K$bu4hYWNsE}&?;n|=O#^Ji zZAwZNsJXroSM#2I*ZE7t)sHAf=@kO|c6Iv`fx9dB;e5eXhQ$12lWF*(WCq4EqPwLY z(%u=z*E|TNWVcs(PuF?rl4O2Ce-f3$vKX?RDS!Zise)gPhdDIF8+pjW!IsqZdSosN z`iw@m^zzNyKPT`BKKQ(c$Ue*iBcyuHO{bKrp8)K+4r}U%QBj_l7}qf4U_A;Z%J^2k z*b6xqObDkLj8RYO3*3)FICmJAVT8h}fma3hli!x4an&>sOs7Kx^yq(DPczBNwfk4e zWu!=hPm7MSVs+v(w*MLLUYi;}vH$DFUc+w#V;37J6R#!6stpgOJ|vnmz=nX;GiqRG#+2XfIbY#_bPa^a^R4N~t?d^=_1x#O|W?K?%y5SNE%}8c$Y>c|FxoU&2PDGznUh>{l z2^c5JY&Xp4+)*pv^AH2xa`EtOp1n0aa8MJb6B`qTvyeQ&_+bcA3Lfij^7<2=ho!m* zG_6=I>1ixU{ne^W=Kit>Y)yP)Vs(mPDbvNwEXz-d=i~?!pF7eStG}M}V^2lA#aTfG zRq<}x*ZU2`Ouc`|QCftE} zaMRV#)dpvpy)(l|lEK&z?K5Ie%$dnU;0M8<>*8x$O2m>GG^3$|bj09})dWpFp6Mm} z;IM}=U4X5;$hU1o)f15tGyY}V7!z3Pdkp3aG9teVQYYC#F5xAo+yC7*6GX`4V#xo1 zljpI*Jvhz*s+BZJB=;F5qvf|cjzT|zSLOm9#>&0vJv7=?{|oDoRf8Qo8{<*a>dSn$_ zT-QJ|Eei@>k*tLu%W!cx?D-Msx*@PenN31<#~|Ttf~>CSWnBvYCqC$$XtExZG|-vS zQj;2Jd+++3^p=MnmjmBn)5NTzf7(Wh1xKBYK2_1rO2P41aHL}CKwu|o5IfwbihOunRHI$VyFhm&JWF}Oo+?VSr@Zo<2k`)nH zi{D?(xZEYE6_FJ1%>1X9vLZX?Y&zLI4s83lP}Meitz|EyuTf)IEc!`*4E(0_>9t7d zm5l8@3l8f~c4K<-ohITD$3-LEi~jt6HR|G48t5@>HGcR(6>@)~8b5U!iS4R-gbpI;C`-% zscVnijQMKNipRVJQG{hBi}< z6H7ePh${cKCgiuuCvjS-_&bM``m4sKgtH~oXSMg?{SBjBEOEn}0XHzsR@^vN`xvk* zT__406{?`R3Rz(qYWS(vy{)PjDLLh@%sA{bOZz7XMn7ox!V{?-r`QjGUzukOx;^_d zjM`MG_cwL|jQo{VH)Xb*@IBHv9acx(S>5?|Fm+xDn?5aMxB2=>NS6IxNh_re5eXB|Hj$}jDMuv8 zU@8fj7!%GY+w~yTh^q_GM0`*W-3dBajR$Q>KV&H~Cb+V0PYr-skK$-oQjp!#H#>`vXk%3un239?MXw(O5;0MB71 z#JbZ}!p}|nWx~b`i1^TwUFJ_^<qrMsR-4NTpzWf3E%fjeGt&fALJjy$ce6hsgJ> zU*Tt{r%6NdL;a|h_IADbdJ@DWQCMt<+Sk066ObuDh2*wL=GGk zB5N+i-%kg}?F^2qXN!D6i}V<>ytNKO9_P>8{%_(m=E)m2&(j7o10eoh4g26IJ+imj zaQfuuM;ZRe$f}@`dZoQJ4)zg{|2pC4n|N2x2Qf)Yktq=)WL}}9t@#C{MXOsC?H=C4 zL~kRZ8W4lcRb;zyf=35!kgc@ zC8KzCi1i6;_IwfB6GN8~E_pR?K?U)yA9P|St)`lMxNyTc028Eqyyi<94$ z^mckhDs{Mkt~{1Lqs@j8y==%T(5w8l?NY<3)^dBBrh(7Y6E9&Te@b>J#A2Pe{C^YB z`VTp`k0mRJLHfNub&ylWb{zUzE3Z+j+D_|{Zk_f)-Pa#D{D!s^tBEYmnSeTd8ES2# z?e1Qug!&5XGewq(yAH+Qvj#*~cpk8dd5Ki{at68@(J}lg&CuZS^VasqmC35^PfDjv zW99>JK5wO89orbXk33M5#|RtG)6VRv!8#?eXt#BMB&kp5>CB-UPbFpv>=n!J4Ut4M zwnUjoL;5)mND?Nyk-PlfnT6JE- zI)B3Wbf0l*YV_vC%77PmSadL5c|}|iF|Fz^q4S+flmA+#YwVm}LVO3|^T9;x_TXl3 z9(?z}yf8+L_CY5W{NbFrg8WT0Xkndi$Mkej4}T(zuO&?*Hg}#eH#Y`&-|ql693mF;ULT=WeUbUhDsAkZz3r3LH;rW;khX^JvDbF9#^6@l zd&#(T&Z;t9-S$9W#}Wp-Mj`Rbkml=dL96n(-5(ipr&hpVDo8~M54jv~Xuj~<{i(!v z0~1joCwTiIvme;FlXZxTpM8YPkZ~1fb@sR4IezX3_l-XCP>$xflQ#BJxa68A#$j7H z?cu(2{qrWjW5(@g-bt5NUR(Y9aOJOd6U^WoIMLQ0L>WewwwGAYH$lLrKIl44@ z+pa|ct4h*_2j{wt(QUYBA`BY=+;maWK@5m@+pyn@jfgBbnK8n{ zLOw6mxdth0t`J&x|Ef}DX@5sk$M*7IX_2fnwKtTyFsZ+zT4YWytw1T$f!U-Yn`a#$1`KceO=$% zhD<&!Suca%MpxZp5~eA=?J%R^y%gcAna2|S?Y2uzMMnB8UcWi{fNiVGFvYdZdu|4gjJ7iwP#u0fWqj^t-twi>YY_w(^4 zwvd0R&vVD09lCw-P@d3&ONd6VrGeei{OfIh@7sx?^_KXYt(s6CSu13D+>$A*UC;M; zOG)oCHh0B41v)GIXoe=EMS21RfV*Dlhb?p%+AXC_%`F)dfR)1w{X)J4rrmQV6q?)Y zxEA8Ct$YcCvrVA zxCfmQnh#7WrNcQFI8E>2=!=-TLF2Rwv%-6Uc6`zFK=+(CZ0DFHhk4 zY^l@o(R7_JJxYET{5&44_g-N%4I9hvBlW?hMnyKuzMzCai&04qL!a~vleTk5dDBXc z73wVWY=JCCDUIVw zyX2B^#af6FD?I3d1!G0*QOHC3A%}q*IBZJSjf|YSJtY?#ldmr{9f&FxZ*eVBZ#SF_ zkm+hTp6g9Q{E>uH7he<_PQcU>DJLDg^QN6gJzm9+RC;f`TxK*ZsuJ)E*%`$7G_98e z{_!mf(Z$-3hteHMKShj&Hu>>a5v1Yc1mr@^dyb{A5x8eFlSFTI?~-}g7Qu#nh6_~r4GudT z|7c3eJ=K|f=UNRao$Gwt`O>IKWq_FL%1>olvK^aLtl3`Wy%8V4(buael0Odrqn@bR zNl5TG@zv8K#!Ck(h5jQjHJS$p)nLrG=kC$}WdzSk=#wM9#_F=*+^R`ttXNsr4g41` zrK0)iw}|1_W4ZfA&u7K{n;vyTbh5|16^2_pr8$W!T`_}jDS-e^b4U&1`aoc;RExgX z-0TuJpv?}8XX`Ii-e!}$V`|Aq9a^nX=5S!wy#2|K_3&GLOL5o{%`47_Jq6I!stjs|?4@%KU3Z#Sj@EiuESnsdA&A%R?<>SQ zto?c!z!A7A%Xs+Ie%XMbvWjh5$lA|aYhCLtaed0ec(x#rpA%9HQ!Sa#>S0h+v6^^< z^D^q@tV3ie7&&wf`%;JrAi2K$hH7{ps#9gXeqJQGY&#Zy4`QxQ%^z$vD`mv^AX0?@ zd{Q|OGv?1?z;8!;)<;9nJ4~sk7TL&aS2YBKfuH=XEt+;0a}Oes2m&dea^G-prQLRCD<9d-;NNyjP&RrJ%DM0LC7bv!A(e02Z^w zv~x<|k065BPV}%x=HW1j{d)^W>y(Dh(M^c!{*l?3^RYe9>f`!n(n;ROi+l@^ru{W3 zEo)D}aJU{F+^V(FG7up>aBd@B=V!>Z%qrUGVrqypt|6U8yR_l!gmKS274(HGi2q`! zr@EMZ1UuLtF*Fd^8!qkq2|A&VB$mERpX>RlI6d7w=r6D6Jm~KuF$NQelE6!iC#c}M z!^?-B z-I89xE28CI`*20y4)h6{vGA1%$Ue;HDXI;8L&zeN=_kp~bEojw4zWkmvmZgvVecZo zW{MohG(8S}ibWru4oI#{F2qJKuLiG!p!2Q%zZ3XamA${N$2M&LAZFCq_BLux|FY7M zne27gb6RnpYCqnOiYLZUps~!Pea}_L?R)Bf0G}SEfL)HKy>wq!-3lhV7w$W3YPL6D z`+@P9diSRP*PKZUqs)hfx{ZHjCxcahB~bBp5x?^%CkzhtKffB(Toth%Lp#wy$3s54+&b)|oQ8!i#VnCa@+*WHccz(? z9F}y>4Wuu^Jh=j-h{+G(huk;mGar(+_rJclD z(%91^##j#%@IO>7IRp5}WDFMxtHr+VFG})Eq)yOU1bxBg-PwmM<2!k2&b#AabVdfh=fS= z2_;8HV!7CdmEsB7lk6;#488}N69e#ivrf}3QN4#u+-s-oZ^0ER`+_9gU%+G-12Py4 zs4sMa4d2sRR+8Y75IK4rLwG&LtFob8W0qk)!kJTcSy9S7Keo#~B_+e%#!g*9O0c&7 zrRgKM3yV!dVIrXPustaUzE3aT*!k&oa_r}s=H)w!zn2ZqR&p%#F~XVKj(?kH zP@q`)k(8QKYNm{bOK20q=T-8}GG;*TNL+I4LONsqIq>7Err~t($mTK4rNqrM{T{`g zM|xeRqZ}p}x!J%uL;t?SLF0Y5LH}&|BSU7hwrn1EDfm^rYQw+%U9j zL4HwZ7P@|*In7gn*iSK339Ht9L;E-nd$4IB_-%a~^b2{;N&`Udd`aE7wApBEE$Ljb zwlK5va7b2tZSE#pjq2^2K^AZV@=i8IBnFT_3<9TgsYGiqPE{OqmQ;R6`}0KG=asVE zh?NP(8Z&G*@bx?v2)@tYz+o24QrHjdw|QgHEqn>uzEwR)3R9caaADEAjV9l!xLV3Ef$>4gL0XRPzioIzdK{W4+| zHBe9uwBtlq?=-yX4H{T+=%9QD_at}28*&uH3_hDT>5L04YC~PRpL4tcDSESA%O;Fe7aj9?=E%T|7vrH)$ep~%bi;6n zwl7>`hp_52)BbfoXo>H~0aBlMGE;U|ubZ{ZDWKY3%1;++YJYY@_r=?=>@@_VWXe&T zl%%@;%2?eEpJV{X@eh7#b%s2O#{B z{QDqA8#96BfS3EuQ@=mJtV`s44VB&Y9sk4F4>aB<9n|F>+$-;(d>!5ilI8s16A}31 zE_crFsA_U_=?>GLd-Z~G+_PL>3H!^G5AHBdar`zMt65v4ii+nnAR5gQ4|{8b8svo3 zR+OI@UGb2fFGJh}X@sZJNWM(H3QeL_f9;$^{*rOYG7+pkuv5xhp+@X$DZxmZ3C?{% z&rsIezGMw`3HJbzgoR_Eo`&Dj3hJp8LFQgvoAkkFoAsH!e1yiRkx2yV2HOI+W7R37 z)RF-ERDwy~Yu&rRT$iTiIDOeNNP-S^64qgFL6?6eSG|sG4QWahqBas^m2~?X*NbH| z<`}Zc#rdQSsR^>G5Y@Gu%}1@sz?##xSm;*oA zfss*BJLfe2csJcN%$A=y_V35jz{mV-F-Evpus-|>^|EtVub9+ipGV$Idr-5);5_YA zH1&aD+(H22#nlX*+uIDXs!woPsV+dPHhC8oMe=#8CJjEy${XD2lN$rsbx%gQqPq@O zX-sbzT2MUZAiBvDcDL)q>R036@{8OH`FUp#KjNFAj)zff*HW|aYrB2!YF|{PZ_D_V znapGu1&-cj&XycczA^@-TmpkbCN3anrw&yV&SoqMF|+G)m*0t2jNpF1hxNzu68{Er zovRg*SR@x98T|t2;NKT97i+q{px+jr-4m)BGXD~dP_9g?%M3RAWxAy*u)=?GTEa<4 zY?Qs}<>X(B;p6?%U1Jw$LBKZY zuj!5XRc8HZ)_-njp7TAz7yajFt9qBeH&8t|w!RKojj2PQg#9){m;BQCyR)HBm!_Qa zpLCIc@nBTg+L1MR=CYQyx;C6jiG#(%cgXwxvcoO~I3poxzYJYZ<<0NaibF5l(cLBE z%m*F(E@F?o`K*YGi#FSm65UYa)VX^ZsVns_%zyMBOK z+W1*+$p|3i{ilP<-IGm{$rN6mFSmvrMehumu1}vqbQBKdu555FE`l&h!D8hDk13QL zxUI}GBb|0(lwyJ?4}|Cn)rv*N0W5V3gLv-twFEb?AE9E3qk?0lX2b*@oOG3EJ&b+< zaoB(Qm}jZpni_rTIsqi#R>e4Ju zXAnBsENXnKY4qPUR>;@w5L4@P#oYGMvp&-&aY=v>)WyY6J}A@uS%V&Mvti(1STN`p zpTJM_u^*f~*3VNM9@a&|smuyM$KfU&R3nu6i8T2yI-c@lS5$;wpB>2pi3}>i#&2;V zL--LU#`Esd`@D}eq3tnVANg~f(>$IkCsT3;1E+MVOt z++9_Mr}k2;ZvmVSR}K6TD*U0=iY-TT6>A#Q-ToY7St=B};9_$8O{f+1sH2JE&L)vl zp2?VgoAUT)i(tZ(6(o9IM=q&e%c5zccwwep;1j6zY7}RxFdlosd{)*ry>h`bNzSeh zy5Vy^CV8kO)@6}yI%A>3x<+0;a&+HGP2i7A9cL$xvH%K12PJ27NMx~q1Av-_bhwy7 zX7MS;m(b~jfTT3K^)}$e&FWHSvE*-JwmsAy9fyC)icJe~51pgLVaf*`Z}kjE2!!3) zeeE?>$fxtnSjSVk;f9=PWkCzjOWL_lan<#i(ft6BuP49WgR|@>N_vg$L6(A*SteyW zzi#NgsXZzg_D{ltzMx6>W$@(mt)^m81E8~TaB{N#=3+4J89O)rkIe9ylKa3zYrU+9V@=DIn&opOj`fre^`#W_eMC)DvartZoEbCI zUljHv%3rhv76aM3NSK?+{4{5#601qdFV0_P^5L9C8*c3`T-%P>!H)Y?q|kn&kL9cE zoD-LW-lA0x;!k>)NA}z5aAQ&BVD1OaRP|`utWGaBtMx8hr^Nh3u>1+X$o5-av-~p8U>h_!8jdbLoRPL7A*nX(@IH7qw8^#zcJftP zpobnKzlHaZiXI8Kt_>Cz!xcX<_s+envr4$nlmRYG9Jt9Q3`|8EwS+W}eI1zUGa$Cy zV(&hXY$175a*kIVmdn-OU)N-UiAVGela12tUdWcu%#H-d>U|qXH^UR7T&6wf*tZu@QeJz|3Rq_WD=-kM{pL zP!A1fOCvVIMn%Pe&FDKD7{O?|Uu>3`>U(MBG;)7?I)XBP@{QC|lJKP`(%ULSt8MD+ z)-gw|5x=WU|4PuieVu3}82RCfOG^A@40%(#Uu47anX#T@_^*+ACpNY)TWc5~-2cm{ z0H=s8B*Y}$C_6Z^Hm`kMd823P(1B?u-m^7x7R%D!i&R|?^Yx=%(yxA$wV=MuJpP1e zR~e7$wW5d5z_LiUkx)rURIlR(|E-bzfv{@Id71;&#y6hvjaWa6zlKW;xd<$itwgCJ zsBQl;`w9$!-#=0>mJ~=xUJ;)CC+#Ke^EuUMoAd#Q#`+VU$#fx-2S%nMWxvk-s|~%3 z&m;M5Hr2^0cNcRP{g|PV{VXwHJ&Z3JHUvHWE#Kqhpi!h*|5O5?!|@X4dqY+jKHhl! zsMkl(tKY$R6j@Od9SLci1b1?{VrlGA1xbbm@xdRu*&dg?VMiNnVI*TDqA9=l$o~^uyFL; zz2MXr3+l76Qf=q=VxD6>#}r8)f&V#`7&adX^NWft7jmb3hvib|I+6OHZCP6yhY6sR z+(zSAw{P!)WB<{8bkb~~tt&ox-ATv&K&vb(8DE^Xjw-U(upQU1)zpC1xUWT&4LdsDN8jKTxBUm;;&Bp%x{X{y zB?d}YyLF{D(Igrf3=N!mt-Z8*O|Wad!WPDXio`9zKSNbCAV3Vd09<-}M&6 zuHzD&rsK|PA~MAY2<<D$QWSU@InPb2~ubg=Nkeg%y3^7;hei~F7I94k_Y3jrFlP7N9L zF^KPMPRcB9o2tOxpia><8*!qtUP=r5i?kG@gUQvp+Lrem?nf+)d2H{vtrc!2fU4?L z-apS*FvOWb8>AHw}krF{7zHl+EKs5chK6`a2CK zCC#G$m&c#B#=)#S=LfJNWue8FBW6PMXQHsX5TRJ`D#&CLb9o1KY^^K+(hp*DNnYv= zohmc$F}cQbJP7TJ+XDDDOoeVNyQ3w>aDB><_OjwTeyA7gFmB zI$$#TGw$BH%xVmJLQ6SE&`6gq#Eaj!5?}KRtbMc3XIgXTu=fd~3X>q18K6 zY_MQ@j5JD)38FGP-^|X%-2lCd(D$-5*p>^pZ+w9y?kn`>DnEb+R^Qo@L9#rIaU9*u z3_T@uzj8XVTXuU1l%m2vOVCg=i1;>Y;_|Db3FwJ=X$IV0IcD^zK^GIA2fXdqU?!>T zdn}w5wQAHW_iHP=vK~QjIUA9*_v*0W56l@I1w82186p!@h-p`(v-}&FD%hsmhN*=P z#4_dKPCK6M%n0=X=5WM_B;HOPoUp#5AtX+@9bqzLOVPiPM_4?mJEv}IP6(Gfp=|szW+0XE*NNxQ^%Lt4|9bj-Z1fv z5Qn#@J)&^PLz9x>C(4x>GhUr9N@>oeYK2c3@&4fEH56z6tchf;pZFoB zJhku#C3ayQl#MOkeKdP)1J!LULYsW5?%H_QZN5$9$Uzkv7%kJZB`OjamNlbJj&*j{ z2E-cozAeW^$}05=GX;i2d0a4%Pch!8JAtSX3VQ^TTQ1*ds7DoG(JB%B3I@f zAdrAMj+?@2l3NsJuiNb*l*9sBN~d2a^`%5CdudCz4;Q?nU*wq>XnSDXYUz#KffCE8 z(zt4&e1_*iikS~EK4K!(mK~FKeEmbrE%DAGDAfvn9GI zQ9-|qZ8_%a>a01c6^SaK^)?K~#%C4CY`T4O4LF`qaT3J~e{~7!_{x;~E;yV$iWq8s z{&e|pEY%#WfoOg9S8AkLqBcH)77Pxr)tG%BMSR)d*uPiNIcM)b|6$(>JXE*KUMocT zt;78o=+;BN!Rc$WV&<53=xYx?{2{MORDDDy#Kr>%FibMqubKYRJE^z?_4KcVtpk56 zV$(QnVNuMbCNI-oaZBK`i^~3`<_N6cp`Tj#;5RsI_;W?K+UjtP z<9k=9?iwF zue)G_(qx6$IdAn0^0(OB^lZfob)XCjgF4XUAE6@0d(im2Cr25U6)E&z<9Q@MlHz&a zFRta{lD-k5erj00ZeqAMLVV%<@vY;_!+z(S=J~L?7BoT27bWTAg z9fYM3(Gd;r9WhC*$QKf%zv9g8bYm<$5j~_4Y1rni07$_l7`odLBAesANiVv%MAO@n z^EW6Be{%UgagoQh{4M`KK$E=waDN-;)p?|EH@ZQ~ic!q?W3@P=`5y>#ienrFNemH1 zwIaDV2lqvxL9jslLcZc1K%o-Ryzqa0ysKksiyNP)HsTHIEtS&VFp2FJTeW99#{2f0 zDXlAoVZ>YAADd+YhSMyXu%CC;!|wQ=)Gr2c*}mG0Q%il!h#k5n@`g|x+SM`OpCIT& zRfF>SElx^cVk5*vz~CO|-zX1TdGHHCdA*Xk*-=wQC9vCA)n?w)aZa0g;~Rn~3A!j$ zL>;eA{FqmC(kOYl4@_ueU&JNf?_N}2ct3yl7yD)He~cMB@x92CS0y8nLXJ1h%i3;f zeV>kMaE_@hn8~esTH;5!{>WAt-K#&*bNI}TaBgPKTPAxMwdThKK+4g`M<(f>S%#+B zq@(ID8qTam4oX-H7>qOX44z3#UQntP}{ zB%!bP)59?#c=xbbXVeuqZYvg|J*6%yCx3bazBBD!G|VfwrR#2aNq@n4|FdTZ zn+^SNUddKFvS?^b?O)umP}t9WI+tWLq4Y-VoKW=NkLmHadtEZYorS)Eos5J8&=Zi} z&BMO0E;_tFI7a>s>*voF8zwhC+utbfVISZFhmpP-41x02_@I(^x>fzi$BA;)w*X$5 zo)IeUZyey_(tlw$Ff#RJB03St{tmTeO6oV z(CCCeUo*m=VVu}XeXr8Hnz3M=xUkN7Ey|>A5Zb=3`!+Y)YFs&Y#C~79qvRdqazpal z%>3z*X&v0Jrf2B^5CQ`L#g$x^sgxfJ_~v4pZ_ayL-Q6jbp%nf>n8;;B@21V_?PR&8 zmKI~K^!`d{whK`3tYg$)z8UonMj`(tO4kO{DRpnmc2Pv(yzNbA+@<7a{u+av)(9bz z+O|wW<;5PM-4R?%q}0!T%HnF*=DIs1&7!5Ftk=FF_z&%znhxKYwG0v^%|EG^C9x$D ztF|Bj&@elEZRUo%+al(h6RZU5&hm5<`^tHK0Cy%#UU%p6EXD1Eja~+@u1A>MQ4|CP zmchuKx3ERjP^Tq8`0j`-5cda@(JC4F6e9ll9aRI{9l#=Hm zRk54de5~sFEl+9e z_ePs|7m$)1yLscEZLOmqju8pV>cDFM3m`X3pq?5Be@nvY2HcLt-d70DR31j`>9fTA zyo@AI8ythgQ=N%ijx#bHpOR|cQ@y2guC7&Sk*`Q!_Y(Wxizz^FwUv*=?@>v<^m0qX3bCg~oymtc6_ALlQsQ{oF{L&SywZ|lF)0PA!aq=3 zNUiN|bml$r;hkq$!Rc8 z{F70UE@g)*OZjzo0f(QwdK1s@ueryLUey>s^Zs7xbMi$&hwMqqD=nQzd{jV@qE}|G zb}m$vnqIs2J*Ii0T}{*Te2&KX?u*JcqI?FAOgAcKhZ%V-8wKsK9G~BE3hR%-jTn$80q5v`PS{D^xBH9u@8Qn z&>Nj8h%0hSVnz52UY#pK_jIUL?gWdd591SGZAYg}K@w;ttJrX+V?sT#VSwuZhMmEO3>L9WG`nGcvJ9-6`xk)X{DgTdrW{@} ztxBUDGjBfD(tb_-`xJgyX*EmkYKD*7{_VqsPR(mCD%N9WM{E8&bw;sE|GjG>#6C1C zN=V^%t`GlxWb}@jl~%A$_u5M)$!9B6OwC>`gxg_74s!mAjzP-C*jlgMr5@0S-$B@H zp;d&cxZ};vlIqs|@Nz3RHxIW*rvipg-vnlp&9D`yyAjCLHESl`jdhWniQw=oc3fs& z40{|MOUZ1vzxNmm2~ywA@Lfur2;W8OIRf6e?23b^xMvIH=%UX#l=I(v7?PhUyqe@F z4S4$w@yF)%aeJ`neUcnVahlQGc0=b})9#b8pxEuFcAH}Krr)^s3iUuYgWJvbx|u2C z@`fbmGdcz~E>;!i+17QN{rPG1sdEUqLS&(OuA))vKZ0seJXT{k&k^L5hyN-*TI?Kh z>?dDeHpPqmcwS@la~A+pAOrspKh(*mA)UIj23|k@N>t~OqFTZ9ok1_&rP(!IQ17Ed z-TXxV=^Q=$9i@=g89f^jiUHaW)@-)qZP3FRw4YGDzNE!7f7(Y7lvsUvYoiY4b zPfp~%?cGgHZp*K&En%0Dx0^=bLzoMyzl{T#RnROQEkgQ?4I*Yw*bbau{Y4Hy%(=HK ztQgr!I#Eh`OBoyQ;IDedwQg#0- zx?3CR*hv{$xmkbsF))=bt)+fw1o58zWn5Y!w7!u=j}E|`J|}9dUq`9M%1LCo{gIS= zlMXISIQaH{Tc(QQ3_ikmyD@z2>=HW(5s*~%&anCv{UPztQ66GF+n|PBy$kONZ1|er z50F=zE`dDz(sfjUU{SKZcwO;OjTF6(9iSA%RBr=*3s5J+_cAYr_ZPdxB3f$BHx&rO zyljs%m?`I#998xvBL9Z9^NvjatH3P%&(=S8g4~Un-2O^_L4etpfVfHtdGpiQ`;Jb}k%4<_ zCoZ?7g%KaXEAH^D)_+S*qc4T31dLvyclvIiutG*#obm99&}qf}!v2k6h+pcH-`i#S9hR3`9S(}(ZUQ}kyS-NBF+@pa*uKbcV)VoHw?vn+>z?^( zO@k0>hzF%2^y_-PHQn?#WZ`QbAx)XC?B9sk_ysjH3Q1bJKgL*!lVCj=S zoqYye;-Y*iXVMdl%KqM(@)$3VMs}2t$bTejekMdPG?*8vmSJD<%6Bk7?@0c+Q#|1; zPebzZm>09dM(X$e!Z)_P+KG#|cj{TmpGgg2Iueyka$ zo341P*>nHNZoj8@aDufu9^0RH7y(ZNjUtQEg`C+*LA%ESDEd%_={298OS&4z1?N98 zN><+21&t-{1FlmrH94$OwKzem{{X+Eo)Ath@BW3keD2mmA^nlR(d}~q2m$aWSMHHH zf#{|YMNnhz`qlWOX2fs_JLnT|@4YG@=Fg3N-S*d2M2SBIgvlSK^>5COC988jQZzpp zHSKFN-VPd$!nE7@v@iHKUJafR#bAG5<$0{i z`_$s_Z~Emm`d9#x@I6oCL$v|>YVg&QLBXkDxO1_$wbTeYMxq!wH-a`XME%mZ z?rpRkWXG*z!X0>B=?n0I`;>l$$1S!-lYV3rg|3G1*Z!Sa4m*X+!Q0naTK7 zCnBaLi6RQ~ZkGnP&eE?u-*MG{Gxr*Lan644%7Bw}h1E`R0x-^V#_u2|B1S8mhKxb9 z2QkH@&*z>KI4sp4yiwW|+uXX{7^M=Rze}2>?|z5?pt`_2Z*Z9F+bB%fJS>@a9(jUu zZz2Zg0M@2+ZGMKZVnC$lg80~467;W5LDtRdK~cUP^BOOmB&ETxe}cz_RUHbL`p|Rp zt18`~I~BK`o^Ud!DcAcu4{qH!3R*zjXvW(}nt8o|ZjTJlj@Y+hc zcCYil9a~!NB<9ee`Ly4+vdtOR8*zkf=q`Y@3HDp+UKAtGnQRF&;lk zRw*kAb=TS4Aj{+Bw7LRTG>I4_{Admu^wWSk_#w3F61IneHEwR5S+IQgrxp*n@jV(- zi`3h$QeZ*v&+2v*B;Ve4aDVFl=9rc)RI>i@rht(`)?x!$Wp}Q->7^;Zhd*K|VGl|L zjZ@4)&B=K3Y}U8p{OVdlOom3eMIz?B9~=Y)+#P|HApt=JE7(U( z)n9N9%U9_^qPEvbTFuNOUk+<2PfPZ$!-S6oepomX75eqQdG%e;hQKEB)RB-QJYxrI zF}PTOZwQd$U|SyT^#-(uSNIAQfT&``8-o(<7D^R=bGJY(noC9u2t^lU;~iyIfDDs1 zn{u%1rbcq|_Ae3?`F1W&W^^A-M*S>{r5feb-Ngv8v@d4A%`b4E8Lei9L{5ai7R0!@ zZKuG>B_<6kY__W;kuNRJDLv0Ii7#aePtSIbAB<)MdE~%gFUCj8|o&9Z9w_=_~Z zJA1kRagy8M6icEvM(wpH)?kzR;r=G}3hwwE>O#;}Nhjc+pwEVPMhoCmlgpZCR|%DQH&J;&~3^4AbFjuksJ9ARc3OxOdqvzi73_E0cE2 z*-dZf{9wbQVC(c&Hs(8Ni||kyQR_()QLBuwI;wm7!}e<*)mLX8tU_=E?#x)eL?KMka$c>)?dc!-f!tne}-W_Jg)L4Pb6vuiv zAAzKkG{E^Dqr)lH9{&d|mNOyAv^`iYEDpoIj}1W?+s^S$7G10PzW-Ro6#8USq*O(Q ziaP--2{i&2_&*Wkt%$A9ieXz+{nc{N{6vyHxXpNh^Z0@DpuC2yb)tK-^a9F4;d*a0 zDhE!^FNxYb4E&8b%Gs_3E-&VhJDdz))vqBLHqn?i`wrNnS#O5Z3aqgDS?@bw-6^7!ppD)~v>hfj8BiFT80K6t!-dj?c_nT3&^ zh-76A-wPJRZZ|VY5;INVT3$9^=NyO6Y(lC5Zj+hqVjv1+%@IB*>;K?Xr1~aYOD(m_ z7hRMf!u;)xtpfZ(^LUgrJ7&QL&mwLt*G9l{B>E-366rsRC2VS{?FmYqpj_!Gu=n5t zVH6Bj;x z*MnCR&!Y|~WanaM%pGG)=WBYHrjzW;M1SWRnx5NVtF6E!uamkV;%mH%sm9t_KDf1S9#BT5p`P{ZZ%AxH|J7Rwti2N8%!gRMfk;i7 z0S?dqwH=o5H@Sezh3P0V+TEEB!YTt*Ha*KV=jKHr8gxWibrEs+sxd2zRk5W*)y5G}139PtNv0j%Rk%JAY-B z8*h@&Y76pAICRtC08|@-?B*R@`%sM;sDOk@(PQ_QoLD<&+2oGb3ww?_j8Ag{iF|05 z)cC9DZjJO4=~pn^8SdQrGnbpCn&x}hJ<3g#V-A>GkI>TXfQg!LID$<$N_aQwWY}l1 zf)2!a*&pa@B8ZoZn;T53(3siFXz0NghX~T^Z$2F<=dxa~zWL!0TIf561{_|)!?|ZV z0Z&B&XEw5D?*;o~q0sXxrdz!v5mf zwPTC%dnE?Q5~F6ODsJNq`td*NvI0DZ3Ft-QWLWD8q0kQ7=a5GGjHRh} z!Wp8PAn#llnGX_`U55V`s8}9^i1><>WDp1Sgp+)gG&=yqpV+^L;S9!ngxeinl64eLKNtwaoU`!-T?jA|tl!nBKR^Y#fD0c>~~)uH*BS51?^BRJA>`YuHkI-HMYS8!rwgu2Ubg)RH=SmkXtF`ezv1w|O*Mu{cbRUY*)Z{zx~IIH zSSN8%`6XWv39!Oi!=N9ea+Ug{ zi@~=th#!kp-$*<{!JBj4dc$qi-dYH83)st#iI8@n;6;F7D3|@nykR{mVORBE%z#%Y za|>T7e9cHFvOnP|m+rTI;Spm2re#w}{YqGK(FoR+tUJ*Xb(%pvfqK;7_*3-uk;p{k z<-|sAhapk3A=*o4t-W3fdr!KTr)^l&AHiFRm0!baOqqQxHg_@PIIp8MOs~-8108a0 zO9613?VuGj<@fL-P#GgVSVPGa+L*kT8Q_kPn<70M=NdNYwORW{+~5gn&UVGKaUmPB z^n+v$9{z}Ra>-@JZBYIw~*t5FzZn-9zY6nziy_&{?*+#0bEQ*Dys>>ZC5R-ei|fJh7+~@yEW4aO6ea zu3!P|iNJG2&v{S$&=NmM>Lq9)%7m9!5}{Y_?H3W)Ir&PvJ-0Xe)#Y_lfs13I&n;fv zeAb~9|LeZaUf{j15cL9J687wWnLaJQjjTGF6@K5h$D0m-@^36XN$HO2dn=aoJF2hl z!4)H?d2H3htm4frC~k&0HwW{;QRmhijAgqj-@RR-me)N*!8ABKe>bAI$*dc z^pwOEPT`*zsS3BtedIpYn$Cy`a^xz^C@bWvIR4&M_{&~Y0qQVGkZf6i=Rc7X8&2Tp z{e7l=CPJ}j2|Y6LX+onnPvF=T$i3z9q6C(t3N;h)FtGwOp1 zq4ZK3Rlfp8+2+I#E6eSMcUK+Al|x?IHNW$DjorzfZ2LseAxq_fXYP`#lZ4|TPdh4H zgFpDX8Ac{ey;j(uFmkPqQyIe%R5cVk50~Q1oY;r(eWLte%~)?5H&- zg5VK>>pIfVpOV(c+KLv|)ORLtzpeN|eC}Cb7F@7bMoau~A3vtma$VH_=Lvoz$x2Th zt!RiTGm(0l7%mx~``VCdt|C8ecyu)OAz(m2xu36GhpQLoKua5xMr+FIisjMb($a0mUXydO|+S zr#ydt9VkeS5y^T``s7{|7s#JX@Z*+5*If_IuX6_DMncS& z0MCzeXEk!KtG-usFo8hX||g4o(Sd9-BdbW1|(p zP2W;z+j_PZ*VvOrkiweuLydtlw~reRjhD;Z)QIvVm+;{q?+?qnPnK_VN5qi^t9&Hb z|H6T`F9=%wWsYhq8km!q>}S@i$sYD94J;e3f7E}P`oW*hbQC;3!UMF3OL+B5fbl>0DmfQNE<+9t5fcM9u=Eg>7sx`JJ%n4{$a>mc@1S#v31Myo2p^u)7 zzLOwpeZ_jNTYE&taa<_c!G@2!NMaQ4;ET9I+80zH`!l3GJ@qnp9wt>h6K`1xJriW$ zJ?rS9HsO6acDSw>l_Rpc_+qF^H0tpJsm%A}T%IU1TjH>p7{s2CLG}8RE+G{HIXHfw zclS9f4ddOMNdOMxmRxsXxol&{LF)!0j86Lz;-+49p48^iG#+DPB)jVfMDNNTC@!^w zf;O-DEkX}it$#l^XH!yD#DYg7Qz~K=YhIJgpX?q@dm%lXL$#Ix6FkOIYsx9IcTww) zO{X#zSS&j@_@AHmas*C&NLcd5PCR8{JnGmcpn#Lbc>GF~BG6M*O6xSuWYCKu)RMQN z#P$+ib8bB8*f-NvH5EXw@s^E!93gWJy z^TE7_eeAelvz=%m^~0j(Zeff;)9f9fSOWY4Rnq~Rg~|pCHwQg|13c?FQiO582o=YJ zrBgO}^ARV9ygIV}#1c&m!7Eg@X`t;UK49J1n2=jb1Mzn8mb=y}8DUyc{vO6h^QX7s z^-a`ooLw~g=K1}^xwzZBu7ayyp%EbYbS%dT6_zy@rQ4Lfr`QR5LODWM2dy&nnO=zZ z28|@X@#-P;<3@YCmYb3>RsZ@J!oeeV_NCAHJi!H!ZBI!3_J=ygJQfDWJzNOMO0WBqDkk@iIQvglxvU`KxMC%G7 z!J)t}Ai%e-4$#wOuqhF6h4)v+GI|^`g)$9@Tgm1nE`zSE{4AM>E=qiEecqdC>@EG< zp9dj*KXoBnnBRG!a8mwdk^DvxL1$0}X+;QcT#%F7RZ+@f*zbj$B&=;m`2;1#fgv=o z>I*rRJ8#=1UjFSo?SpzHx7n}2s=fDfy80QHsHeQ5nSBY}I)NrPIG3P%J`M$$l<+`j zl0Y{nnRSn^hx3BG@ZU1+yeIo1>=O44^zC~RU84fZ=_T=qGJuLe=wcax*FITJkviTX6!)_TPR72>>{F49N8@G zxwWa1Ms`xyzRX-OuSBF~jUI>?=%CUSx6)-OpZ2d(M(SdOr zSt58qT_*Uts;XWSH}+|1`ciJ{QVt8bgqliruy)7$1RigvPvp`kiMDiK+JFnwm`@I{ z=;2?HMYVg;rhA`E7oLcR$>TgF>0kD>$#|>D9);$lKfQ3Q&#m)Rb+Ep-E+%Mir17=| zaau#1b?${ur?>P4kN4Z&4ow)Tj7X#4rq$$TvkVQyBT4P%wT)HZACpROwNOp3EWJ%l zML3v0JJ9mc6?@#1N1~hC2(WU5(Jfv z-Cmf8!wt0Q>&!u=U>~r<&2XWt+m4vNS=y<&4Bi=#dS?GHKUwA;r$v4s+eFB8sXa6gYcI z(An++fM4VTbyd-K)d(dq2@?ZpuD>_7SX$36j*&#Fq>f&j4CP zr&?~835B=M-_zY`gW>Rprnz)>AJLC-NR9LOC^R>W+(?iH57Jl0<) zz+J!W9AxQ$Eg>j-NY+B!Lfg`^kl z%uHxJ7l(Db-xah=wYhnyQg;y4>HYrJwH;mRH&XZWR>r}C9+>=fRjr+RCIDka>n?!- z9|sBQso{xbgCQS#V~H8xFrUSoEWS|?%Nwimd>-n%I)-c|>H~p|l`PRXO0scq*5N2m z;5FdU8YINFM^~JfF{IlQfZ3Me0;j(GES*Fb4*(#nj+W7ZA>P)Ij;XZljNXZST4LW2 zuaMoQf>_##C9{R0nvVih2{*yO_4=ZwLb7f85+X*~n4`E50gBhsiV!N6>mfM~?_`D z*xy6&INEPUkVO~ZOl{A2Utsz_uSo9|HNwn53M)r#$&GffkUROSAFu=O@n#b2nL|1Z zaipF^pq3l!DyeT*6E_i~wkd(9t~cM)UTpOvgOXoz__WT0u#P?6&v22qspohdvR>?% z^@z(#*RhWWmQ|j|YiucBG)b_Gz1Qdu<-K1G5D2}0=E*K&ciAG>#zL|I1`f!1C@0m) ziL&{|kh@a_9UOY@tii3o2p_t+{Qj(Dv+~k+?yi*#iEWh-z14~Ll- z(+CZo+I{r?Dr2#FcfJb!AJp;JkF4hZg5WF>Pvh!C)?^Vt#WSm@VBTG0qjFi2UfJZ$ z-5Kmq&mR7p$gB!Gbcj?DU)54({`K7q5)fsZRI{RH(lwODI zea!jnzLJk3zdRik_IF3s|MI1MNUwHJkf^pIMg8IuTiYh9V5Q8{v{Q@0vu~ZdmrJvx zfXLMZ^>WeOOyp%aiL86p(y zAr27ZDq;E*6jNx&I9u=KS;^iU=7jBHy%h5k@hS)V4)=W{7oD%%OU>R?VGcdd8mO@B zwa0$kb{z5+2bsn|$im%lQ?|R(SmeZ6;$&rPWhqpnH|GS!Y*L`Pg5}z&orkwQxC5Z} zHXVdgBZE@CZP$Iz5{J+LdOA!@M}J#+&|bcN`V$kGz?9R7M*!hzm8?tBqK+8qa2^vY zo?2`1BwfV_r}CIQ$8>NmNB~?bzen#@5VPd!!*_Eh>fC=zs1BKtY;X3y-3`fvyA1wS ztXh4{XKjtiBR3_RDiY zU@2EPA)LcWASN_g)BL=u`hyx!E*HAdma2pM zA<62@aa_Lj(f8ELYX9lNi9ZI?!s_6N^TUm@4%(3f`pNz?UDaE{=^_(+gUAmb4dXcV82?Tbtk}d z?ZfUyn&LZm*_aOV+KSS5Q!%>R6(VH0h8R%^#!`w}xzp9O73LH4GuI*PSHx=3tIpjq z)!^u*(*f&$UYrKc`u4r5_D&Auzm_KBZWI#fPf#xt%?)>d2pBy$emMS4!_Swkm2v-k za;+G3uJSAD4ZTNU32F1q`|CztRBoE4wmi$sdga&unw|c%JAtfXSshlQ^}4FZWR;DB zLr&0Ep6_(#jS13ZoDs@zXcotKd|$^Y~%B3r|S&1+jw^d5>sil(gsreBARK}?4S<28OT5lG}Yx|z;| z{Y<_smzc-#@U$ZXPs%yi9e_#&lz%$`A!xv|-9ZOpv#m9HQmbFB8j(OEIl%y&`lTf; zIcjt$wU2SmxVy=g8~f;EsM!eOD8Y8*&)sD_4zz%WY;;|Ae>`|&xl*0^)}$MT2-Mq_ z3EZxHL>S7Nx!>It6x_+UeKqjL<49pCw@U+@HNN~ zu6LijS?PfW$5*#rwTYikfI zxwVqF5KA5YR$ERN4^{l5X)fu$dsMf_5V0+r)b98{HEnWER=ZYDHVPE)F%kmwqXK&p z5_6yKd?cJvXf&7#`XBtE%iQ-5(hdBbLN~yqUgnj^(Q$Q3gEOm8b1NXVEL^lMOL2Ex z7+Tn9L{r}WhM5^PW{X&vDUts-%y@AW7K=BF!PNGW2sW+Ii3VQAn<|7_2hh9+uDqR# zi#o;y-fUIAw!IWseqMWvH@2kQgnRvJ<1$mol5;HBQO(Dk=U_4AcaP%K&?(l(vU7|B z!QNh5naWtNyP{%AaJsd|vZBty9TnP~?oOuW!B&`)ylA*T?ug4dtiDR7&3db^3e9-z zHh;}3d;it%kL`+50T+YwwcnnJffLM?s$9=@@gpUT$&n9{iC-EmO$%uq~=dilu={?va);Lu^2pl-2W{CeITsEpZ6b+oS;|Xke@^h89#O~2x zS3|7VxDSA2ah5OX227ST5Hirc%n07x(CJP%ABKCuh^y&L_@n%GKamtcK}$7^6XN&z z1MMUA588aRlE>J;2hU`VNhmqZ+rLIhkv{8=a|JS%b%l_x`;9L!P6QjAKC~0N$p8oC z4#hrZeI$Y}QT`c8_UCvyJK>AwPObtSD=RZB9=PASEl&Y+$3Xh(#?T6$a2?7}iBg%^ zlGItSwp&j^r^gANZ{52uMwTvxn>%EDs=kmpv`_T!d3lP51ADmt|VP1dSy3I(F)EE~jmR-qr5w01HlZ=(49c zW{ccv&-@$Z!~?d!H+e$qL{+j-g~hE_E5Zd)Q1N}6@gGX$k#o;4=bzbcND!rn#lgxg zoKC2PR1|!1bZ(a&+lY=cZoX=4Iv#0y{$k|MF$bHpABhd`jEap&-rMgSqZkwB)TaMG zkM3gmZi8?Mg)-0|(oO!y9{~YL(8Q_MefNrj@u1~^aPSiR-wUsp=M<^KJ_Q7K+OJnw zs{>cQC15U+{7{~xx;B9xY2h!eI(<^0j{{R&UN|i~+Pyq9>I>zCz{rkZK zA%ft@_PZxrSlDv>i(TMgyI$FLVQw1548d?68K5uio+`EE({v5dt61Qy??>!MtKyiNVh7eoGbd z!b$wXi9@(Nt0yYXZLgR=))UJCV)X z)Kv}N_WKB%!H837-6(bLBcrb%Vv~v8jU8x0q)cwPG^pToPU;_<_rssPX1 zM4kiI;py!B1p_tehU>AV5=1KL&XTa|973@kc|8tLx>++4qq>&$rCliMKT>GFhs@Ie zpbR2a-$Cly#-0yYYU0^Ce5*D<$qer_?ef}3@w`45dWW6LNVf;LoJnL0qM0I7+GX~{lQFYPdbvIstMGfEd zJjLG?=F_(fIYIU-mHS}ZwdDp3u!#^b?Lw3|GZKGQ^Ey8|;eVq`%Wo&*X4;y?q3*R# z3UN0|FJo%S`dPy0Kiuyld(hpdZ4vxwUf&tA#_ zzUEZ&%`-oCT-rcbc{sKi=d=EVWjPJYto+$-i-Al(5B%&WB?UjpU_Kud-(Lraq0YZW zz1SoM-^1THoX^X!7uV7|x^P7(27-g;U03TxDykmgc&~hx$Eh867w7s{9|khHE$f-I zZ&8oCeUO-1@I~c^xKNbZSq*i|zQLbPG0fcn)rt%IN=AVvB`tVH=>?k--8Rdc5|3t# zn_#@2eSAkN0REGZer?Pa=XPhdwZp4sCLuvV9zQss&U)O$ z2DF7;aKiSx(re<{`!-B|=i?4F5zQ<6(TO#6w;{1d-0 zv`K)VIwB*9c#{BntlCqgvIJ?-^wJ*?I66TLma$Ops>l7(3hp{TII%giLlub55)KmT zW!x&Y;-rE=gAIjMQ6;_UGrF{#ktwmDb`AsFNuA zF8KZUunHI7WQ5#Sykuf5S^x^W5MHgu{PG+N0Waz{@Y3Ok4+z3ZDM|Tp4Hlreq+3c2 z4}8zEsnBY{*y~?uss9dL$T@tOR$}+uT_JnN7(HB&c|oVqJD)l5kzNwQIm@^>VTFF?sFhX|$k1g!^TJ zPSmNG5TzS9s0i}EiR!FBg4s=$yzRP)8{UEI!7716@!W*a$n1&})8>1RCoZ})n>V!V zZ{P6W3VfGAxpLz#^!7ooCO1!2OJoAlISIEW3*S!_ENU@_C7>60J=VS{^MpI#;w|)V zZ%h{L6)sS9)RMLaevdS%EwfcXH22x*Xq9vNKp|Rvr#b zbL(!LSq|hCi__Ha1zYpUOcX3GRZ<5RNmg`emfR)kDC#HE;TME<-9{*{rlLR`ApL&( zbh9jdEEvr1;qm@_0G3}2HK)h|zKaiFc?mHZi-ifPS`ho%e1CqOo$khQf|l}Y*lFt& zYWYRn+>3VV;QxdK-#<{CuIBhH%Y(!!St-8DKTy@bLX~c0L9;@s^8q{oj$gb7K0arr zWq~P|S$)x*(1|-`>H9+(t2p}3Z;?zVVBy61Vihk$m`z(|Nk8xkWT=d<0zBx(UE3QR zl;@M)KG$Xf+Br#igo*-iv#QH{7TiFh^|DQld#JsAi1{aG%hgFW{!aZn6Azxca7-BN zud&@PW#;b%e`R*w)YRni!x}XM4dKqgp9Y^3{G$Cuk4$PB=c1On=BZKbi-se|R{r|5}NtIaY-g$i!? zg5O>H%`(2^FXr&4hxcP2Hit+KZ9agcb<0S3hn@sz;#KB-nywa#)E`qxGz$mHpMD4| z>C~UtJ-gerh!H$eUd9;FKjR-`81b@%`%*-@$H-QpU-Pwtrv!;}ESuqWwQ*l)^^rm4 z6WK$I(CG4!7}%1bzGnqKgLyk~)r)bF2H1DRQ{E;`8Y^hYxtUIHWn;L<7vjAhCFf`K zb-2f2)yVJ4dh}J2{&;@H6}m~EU9jG=@fN^Vg0WMA*!&qI6?=Q- zk{c{E@VKsl8$GEkxL${jC@tC#livk$@y0RSGb>B4YRNFJ|0?6wC4T(RGf&dNs=Rjl z4HVzdTo1RnE417USdhD!riUFmju<-ib4H)&cPX|96yq3Y;*-%1ZM`f-;*KsKn*sO% zKJ+5Mpi<;jtW8)~#EZb0d(Cw26(^3{p6#ubvSP@>n%^8eGQjwN<%0S#(8oBdHDf2p z_L<}B<`q5Co#i$6U4q8@l^JR2alT7yI7W7|M`aLby2Fk-EUAnPCcfA47X=%l(tR4{ z@E(Jl<%ZRkEr-1OW$$qh!f1dOp~pCV@`w3^dPjkYa2M{4JgI#1qc7S)RFbC@c~GNsJ9o~_l^B*yXute(qRu9 zzb`TzY@t{S(bDb?}X;=55C#l;@I(nT#{55xb=uD!RpYK;Px{W zT*-A!SdTUptqaUMR_7!5zOCNDroC1^EZxppvLf=DJo8Qw;HMPCx@u!v(6_R z%9U>i6)%+H*>XnQTtfgO(o9ovdFb1!wkrEKKLW@?H?8VQYYox22Gbj6uFPHB5}GgV zw;h3kjU}B>GG7oiTK8P@sL47E|YFTj1IqJ1IuO$#?)4pyZey&_sNfddL75iU>GE@tlMMdoqN-$3lEf03>_!+$HJECO+* zD74yMfUR2A9_h1obX@<;I`jhl9PX>)y+brj>kqJ-oybneAcgmo;m>?O84&X{0A1VS z6ZE0qknoVF$<@XzkGCK{qmv$TzV;uoq)+>7-v!$MDt>|xK+xUDzJ=8-8#=8;KgwNw zCKzi$6?ze~--xA7s@Nk);)OIB{f?KRqp>C;b?u!#^anG&Au>Mv4W~HC*iuH&pviPy zi(mHl-xV%S;8R5(I&oX{rADI`y56CV( zdwc5VpsY!s3_cNKcz*U%S-JwsAQktI zlc~$@x|~(loXWJ)T6jE4e1ps5w zl>7MUVCkss{m!I*3+Jw@yIBdI%|rqV+ZWW#tpLA2Qua|--t1=8fhl0ltHmvcw?rVUs?AyRyL&;xxnAAN9b!ANjLx3JTn&|(z zx{m{&@6$ZcJLm)(fQ}TU35*g|4|j`0&|x%I@I5*aVx866kx7$#_!7K~Gnq5D4h{<> zGoH_a_No;G3oR$EEcuG>#O1{@9)2Q66fUTKAEQK~i-R8FU7|xfKM^ppfyq%OiqJP- z_ez{qFZtzbt>jrN9h{l|n27oS?5w@!nc`smlmtRw!nr<2W7C4eeO1xNWcMQ~V-(&C zfoJPac-%$I2V`-k%ZAI)v8<;f=#Kjc^XrB9#8hAL4C0FmfIW^};Qt)D-uokakzRS9 ztMOq5wXRRMyw#0@Dcz)OOak#%T3q^oT_N{ofFU`y%H5!psCCd+XJH(~FJF5K{CM{A z+ytL&>&QI9Q2(Hhd3nEJtvOhOpmV^E@{YOgFMb3@d9Q=3YQdi{t3^8_+885{hn#ja zU9BDUA~+#t-1$J1CH$gU;1zybGre3$@e#8mOly77YVDi%Nc;Ky^Bat1MjvHrA!1_M zbV-<}hUDcLA-Pn2Jp%V?pc6(=RINzquUH`~=lZ}@@#7x7Ec7tjxEm>mD>)x5Zzj-(( z&|1#@Y%-&tUya0eY^DziKrG^+RVTtFDpm zPAOeQj`|W>P6XSAN|0^cmXBWR?hBSfIv3IJMvk5ia)7ADmOSv+Y3ORVjYBr<^DapF z5LawOxGtol$1I;MJH`JZ)JAyW-<&M-hC*pe`A%Cy zdVOrAxw6L+~dxv0JNbc*=-RBe;z$2E<21Rw_d;c2HLR~g( zn6Jy{SJ_K)N~pf0G;y|&b2IP=Sj(}k@kr!ATrXg#=MG^E?oBr%2poFwbO(8PU*$0Y zFt~svy2LYTj|j}{OrPY{>*ugJ;}P0$;JTL8UwTT~gkuj;Yp9*#ll5x;_MdKai(T_- zlqzSta3Q!LdqsRD!E#e9)`b0$J{orM`C8DbXj7XXpIVLIc)(fC6Bubpa$TCS+0Pvy zD1o3=%+DliBToiQ)WDAJM`SZ!##2=e@uhl9F+pA9rlO|UFKty@4^h6jG)tx|>tW5l zHfW~83{Ds+4{OvAwAh;Z*B|&tJG{;%$h~Evp32koCVJF$k60K>D`}1$M#cgkEe70{ zUln2I*x5>L6}`{)P&~uRTZfr%)T2wp`_EvMYI#VZWMrLh+D80~_xBFW=*@Y}9xYaQ zc_|0mLS!UqmZpPt8gT2Jc#8Mi3zIL<|2r|qM0KX;sSlT3-f9{>gp3pJT7duJq+VWj zw|Rya_-lz+Yl_g0N9oK5aB;x_80pA1p zEG@qmm@m|-6~$4Xh31@BwdHf!&mKWtK7W~GxTA|M{{0LCD2PG6xv{;cMV{4QKiU*n zH1Ae9oNWE^K$h|A#rUiGMI64-Mi_jG<9y)#{Mh0CN&h*UyF=#uxVgxr6uLBVs4c~o zh;G0o{J@oCFHvtvzMeH$;yV@G@7uwZR)3jvMG5*=oIdom2~1Zmy(BPj3zNws+tjz2_0a+@iF@OFhM`YqvMBn%3mfNnUf=u8KX+O2w^9`mW zeBwA9F)hw_O%fv}VLwneohbO{^?gY{aG+#RYpMLe%TG5pZEWzDcxNWjnwq)d-tkUu zS6>SorG{xc=Je$w>T;F-SoAJ*dmac3f4O|~hw@0AzFBhI7f}BzA)`V)wdy&^XV=%( zEv9}F_vyCYfVw%T2ONweQGzj8BAv|)27_l+YKF02eGhsRC#`Oaf>7tCF@~ImnE7{4 zcY|i-=9wCVbFbxo3_g7k6fb0onubJEpOErxRfV}_c*IySy`oyN;)`txfskI3&xKHQ zS)~)X^heomr(v~yT-rmy3y4AikV=f>I<9`qPxSv8TYl?eC3QV zuiEcT;&%M}Tw`lJarWXNmH%+xIif9Dc@nGn{=-8)Pa%8dkt4m?=q1j`I6PoW+K zU*KSBUS}yIVH-YJ4AbX9oU1vlGCviY`Gdjy8le=rx^bwrJ7HDFi zz?4RzKg3Ao0rcqi1iK~-^e0+g@<`7APsQyN>Ke5ajR)Uc(-QdtwX~=g3W%neH(uI5 z?7NyGZJ+fh$#|NtQ}OQ?!2|A=x9Va=$I8B<%^G5=G19@1Jw5eE-H6=iU~?|N{`?qV z8!io;!_w)#Yw8X8+ojxV?ic|ypKL>z7|U=Xdq664N?Y6U2m2q7aWV6C%YzGc1_Db* zXX0Tz2WMe^)Y+o3f^7kyoO|xq(87TobOta7v}m<~`GUDgN00`1SVLl;LA}6E*kjdH?j+=u+zaixt;Y`XBdpdHPAg=#)P+eXi}(@*Y3dlL_JvN0?Gwr0tk+^sXiKiXtIi)4 z;EOwpUEWkrF@&DuI8C2l6J4IyDgadV2SaP*gIUoJnJaU`=c_6FxY%L>k zn{6EiA-&3P-WaW_c>$g7qdLKm>G+luZ|CG9I zN9ohGj-z>vl@Ke|ba3jCb?DQQtoK2={l=pOVN3E6a5 zl<^}R#9&m1N9k%+S(z5w_diGT(TdjMs6HRJ-Bq6+p$NWTc2`N^+v%;?c&%Rl*jkk# zfQoUW&{@c}FY_jOT&!cH6MIU#-o^jN(V2%s`M!O)zCvXyLiS1sSt8j@l4LK1WEmw* zC_BS2Gue{JE|ood_Uzk?Ejwf1nXF?UW`>zD+w1rK`~3MF&v9JO{kgBtc^)?_v);xd zgNZjW;WI5QpvxwP!mr)ZpZkfqOu{FXJ1`C_W14^RXnXjW)WMsKRZ&7hXvIj}`|N^{ z?H0aU*E1Hn%(@|{is?QdloM**#mR0?tkb-HhaL8c%}rg^W=~R^Lrd(P#yi+%bX;&O zx%M&y$ny@)Qq!&b9G|cf_J!*gxZfwu(aSA~m{LQ^)H=htExAk8)7h{vvH`<+Wultv2}S;E%}d4&Oe63K zy(2{=e;aKS=Q}arlgsO9!n&$E;_!^oR!Gjr^*}2;FwQGmCr|Uf+?t0jpu5(XQH(bwqRL?{j}?$#Z)8vWLO(=G!U84 z`3AR_D$m(Z4g;x#7Z}ETV+1Gw*GS?Jq?zUWBcwAEwN8gbpsE>SSouqlXizOsr?bd{=H6IFl85||OjrN}dd_wc7e;xlsH*mzM z5z}ACVfb4w`DJBkqOQO#rw*MKlzXXn?f%oYlEmUe4Qa*to~!`~$|qp2x)%ipoM zM~?~5w%4JN_pJx48Nk(E@F(x5Rnb#(hM1F(mB?O^yLwB=sPs;UkF=Pn)Rdjp&xYsi$(@uKX$m?)v** zeR#QSY_oOXvy@(SH}wjL7?f8X6G=(qGXe7JXT$}sDzGF; zBmyPL+{m$b*z=&z1gtr782W1uU>aPv7BgF32sy+P;`!l&5<3Q_3o32eB>tCG;wMi- zeb$#0v9iSs(`uTY?2NXZ$0wbM|8!ce`~PT{KoGTjTO-s~%eS$k3{1SRi;%1&f^-3< zM7Yz>I>m@Os@N+`ADB*1oo)%Bwf zM$I}2jJN6r>ibUS#VKMdn)e`T)B088am-PgHa5DjM+CyI?wFB>!b?*PE2aWhUAc3Q z(k5aKFQI|pw9^@1VJVt3;tfi6OH(-sZLaNl26lTTbI3mpyC0!;fd zbIz#zK}Ue8GmGkILwY(ZG|zht8REbDnI;t#v}wb*jr%nhsBAwm zh>xA*TCSgT#}JYNcSiUcT`A6l_EMtNq88|AHEX=Yts}0|C*C_^eIdHx;(^|!KDs!r zJ^UbN?JVJ-JDiKham~te9wzYpI$-osI>70hFN8A&$@~&qU7wCsN**U_8MNw=EDvuh zb3JEzts}+uqHtGm{n=|St(PVc-$dB=h51{n2fE78 zUqaC7j-sx!bzM82*us{2vNW!`%ga=#H>~Cn&fXZ_b<(1%^*bGnlEke_>H1|3wjxC! zj@-!ReB;fkhfRk;mv`bZn!2F+;H+&ftH7y`!9W&3NeG-Va{H3{ePMslgKZwbTA#|w zti51ZrkOF6=U< zvfhx8Efv9Tr1@#B^}=%J)facKQ{T0j^~uz8+>XbZS1U*hQoaY4mkgG++t5S$BGa~E z?g_Xk39>^pysaZ2cQ#%D6G1^w~*}rw*7wl<;_3HDd9YERTy~w=tadf z^fOtQV)Ll%WCv98kq}*PI5!zTxx(d}N2=S6%ZW?<$K{`Q!Zk=N(0fq9TH7riNPGIX z{;<%}&X(Te8C_G)8zVS#xQ%(-{L)6D#+@*&y;q%1bauGCmt%*^?ksi5OZ5d_VP}6F zG(p3N_g+uQ(0lopD3ZJISnmR+_rh55dlt<;Lqp{Cy+0(E+GA@X_c~QBthf0gXR?*Q z%D@<6Qk=Yl*4V0<>0!OM#`x{yVMX#&t=VIk&c^jaxVGoe?*W-DYb8EL?sk@>}x>m#D;$Tcd5sc;J2EsAI2t?Il$h9vs?*@}fr z2vnFl@?LbJmDj!fRn?}Vyr?6;)2*|OGlyY>AOCf4{pa;$&#!k}+jM~~WxMOCC%gYY zOzuihdbCt`ym(3_YPRt>c6Oi3_}H84<JH?k zLuDp5GP-ypb@Nv+=FfrQiLI-Ce?^!&B~08hkYZM{P*y~`8Vn;;1b8T)Y=p=Ih)mbl z(DYbq(_r(BsNYJNLRCjk;Obk(S*&{}RV~OVOx{wjA%h9g^egdt; z3sgHXQ9CE?Dwl232-Y7`cj+43FM73}_cS)4pHQ;}y*0eER&-*XMjB;R=PWug3RbNP%U z{m8sUR~<7UMM&fN4BXZRnhM+5@I!rYI#HNsZ`7ytH+X?+aD6^Q&2Mp-uN8|Wd0#oG zZ@Q))1MOHNm2rTzbRaCwcXlmWQg=4QPC@O}n8JLUTXP#ThwyDa$OW}Z{+hYYJlX8H z9jP~TKmsx@$l;iIjLTrV*Ie{W{Q{bx2R^F#{^GRaNjeaQ>>)Cz2UW4nawq;GB*R0j z6rxOuaF52o$xSu8P`@?-1(d2}qIHse&Ih3~rW*lOC~nq$H#eZt;qP>;I8%+3#`%KC z_TP6mvlt3I=nDgZZvR1oxnoR1)G6MHz?f-EW}5iY-WwrRzo^jEk_b<0P=RICyt-EWm_@># z<0b7|!A`b;o&~&h0)6dBwU2_FZ23TY#6~`}8krQWJ1{5kI*Sz@w+FHJ?`>;DXhF7O zXX&`NyIKP*->n^r6B-1alHre?kk5rWJmx)&sU1CjE37aesmU!ACnGw_T9F|7^FQ-w zkuQG?yyPAboh!pf`5Qb?&>p${lGcHatXp2`HI`$!NjFk$d0-V`Ash#=6PegQh5ypN z9+`XWgV4{Pv{Cdhrrnm34Ptf2s&T{km)`^?QvSjNoBj*>g1AO5cJ<6-iJ8)=-Gk#q zLd&T~O)npN91i#^q!jWOQHx~A1-Ypht&C0k?GITAv};~!D&k$R1|lEDsWEkU&-f&8 zDYFfxW3{h@?_te0U|HAv)b`>(_B`E5)CA1LEpQ{m91dC*UQcHNMlyD8SU*4H-B{OV z>p-TNua^}z2BGFVDz15HFo91muV6pDcSxmi`sP$OL(eqH) zH*k0Jgj=Y6T>?7K0}ez)Nb9lZqyaBE3f$UW&8yI#X}bhLvSt$l)KBoo-ANtRQ+scC zw$}QR{&0pR=&x|@s->Zq7N8qGBlTUEw?jquSe|KH02RJ}HfrW@$|)Y|v*%z)C9V15Ahe}21iKu+;`T6@-x)q*K zhyUatbtK)`es*k%R@i(2GU5Nx2lQfW$gz~!q}B)uYX3Zs+=JvC#bft+xXL|tC$%)k zMjdcpZv_P0M}Uu;m9QNQIgBTzX@>tX?J1!*mj`D*ZjM2LrQqkY-sT}}6t$&-1C2AQ zd!HuW@BlN?sW({Zy!ID{xsJIB98939w25zxJ&)_WDt^u-L;hq}Xa68OB?Nt}`Rbdc z_k_vP&NUyIADGjugb8rp3!g<%WU>wX6h+SQczX!Wn9tcnW@6p}j-QlwZvbZjJf?{i zYniQ^dI7m3(SM-SLe1tMs1Mfa3_g;Yl$=(K!-2_VOoRABXR5sU=LM$-D0CAPGynEf zCv#z`qTZ?s4PS?kpq^vuS7V~nk;!-Zk?|~FFDTx-P*AX@dHYaB#Ab6zRgHKhqZ3;Q zc-8^!eHiLr@5AYfWY_2vPuJV2%)Qt`y@u)&#IqQJK1v?dXB#!l{0gU zsix^JE_lO>T`iAFF**yxFQ2o5oVgIF+>1|1t1SgM8}90A&TyU5&`+Of^)k*MrkBK$ zf)nf()Hg*N;l3FI#AiDm*O8UXjVA#ZOXb1}UPu#%unyaA(iL^>Rnb7iUc8~Ssrhn+ z#b2qIL@|$t3R-XDMX{`m)G9pJm+E1x+SkF(q=VfDdx_UxIrjZ&_?7g^d(-o?`p;Ll zYoph>xAPmnk31IdR*Agxw#YyZGcwezwQFHK=n#4?T*bEE?gx9SxAf58x{+S57}XkuU7Pi^+zJdbpUK-9b12$DfGc7~LSYIX&sSNyT-=a7 z*Jy`2YlAI~;a_$4tql>+b$mgG@;0gw3hPOPb;m@7+AaDOL~;iFJqcXa0-V;1)2eg( z3w=GSAr_CHqK4gID3Is;^UFJ}4+ps2QjftO5925Jmuhhu!AAWFM{46DZ^f)&(vkV; zR@=l_ZqduyrmNhq_AXJaj^sB247!bXwWP2%_ZUehcehSJfeK?AdD0*(p8F+?AP(C-^@}mYT85<0s6BFEQMdekzZ*gPPXhN zh_P#1B1bsH;yJ)f^A8{RH$bTHJA<@IdXuck0tJv!J@Sy{`T9=p z^+7`lkE3U4BGk*UzqU+uo1VPhfi&8bAdI!n9@tMn#Jn$aVnVBeM{co%DTvq|F02<{ zLlg-iXL>-41wmo}FJZ~`;NjO~YcAI#M&cO!h_i^U+#2PpuD!|j{f}tc&Tv-(G7yb;pvzg|Rb-lHokDNa!y1TwXg1f)c zo%6W?zX7|+H`QqkI1dao;ANC33n9|UNbdN(}S zPaO=&3H(tQK8Ok(flI8q)kkN>F1&dsvMJnEL3Bm?o$>%%IA&gHDt~umC&vm$VR|Zws8eur<>V5)_Tz*CBu*z`z*e$w@y2>x=(6B$>chF43-Yx6 zc;6eSl$y>fk>y|?fQ;LEYaa!2k232khfi)39sY67AK8+-hCes5DcW=_NnN?Knc$@u zaN)WC5HIjaR%p50iuG;`?wO)EVZivn_LF)K-(s@&q`Gcdp)0NT(LTCS!3-Lhc1uB| zxj3S8=FaalPuumf54mEO51ZFYuOY?7VEX{x957bs8M zf&LZ7==l9WXYdXFtq-uTKC>T4v{-jSV>KU>6~r$yX72{juzK^(drB?uvrC=>I)h+A z_Df<{v=2l54Y723KXzNBtLK5^OtL5c_nIV|2%Sb{&P7>z0Xq+6rJe0ywMD#(*yxao zAHOb(91~agc}=GTYdRKX=g6@9A(a5KeH%GPb?>J+7(dqh3F~XIVhn!qGWiEzBrF4; z18*+2J^!Q+Xu5f{8AQ(P5MARPOVPRHTR#)^*@W>q$eHe-E_Hoc5X=*syla2hGGQaR zH6URh5nj@^dc$B{&19x`U1zU3E-20FhJX4AUqbG&pHDfr`sP@H{EntgGY@1`NFY5@ zKNgUCCU6?g7r34-zvaP;dp8W(6}YmE{s-V(QTSsrC05HB-keW+>ZvDob^eRCu21~I z{a}y&z-!-of`wL;r=2rc~4%PY*Ku z_Eq#PU#Ru{{0DP?Zub^0*w}sg-7MOp)Dh8nKx?vxhF||zf$Sd~qJAp<^ud$7-C#l9 z5jM9<+al*q)Hpu?6s%d<{6gcHRhr6YE=LZoJ^(AF$=?8{(LB-zXk9xTj*7AA71dRT z1E@PgJ7vD^%dC-imzurjdJDf2aBz@QT+L}3(89zXk%yLiSKs4O0q$hqQUV0Vdm+!j zmzvpv>SMQzcQG6Xa$h8?vi2K4(rYPyrvoswOFvVaB!@W)c#g^CAa3b##j@~Evj!j{?0T5zZ6U2H(Ft7pnkJ(F zU_@R@ZN*!k7RA2di~YUazAWW*DjcpF$Sv&i1wF0aLob}t8QBVX-|C> z&ZG*esng1@cH=O3E~s&ulr# zWskDB>YW`P>HrU(H*DU;8Z1j$AdqhwpGwyo^oyKJ^2hIb&y^eu)Ecj8D${tDkdo)Q zJ}nP6|cMmt%U#N0H-q=~u#B}~RV(*cuF*9vWMc^JhmW>r0~l zKQUU#|1N-C={J$T*qfwbHm_HDI_i0vs@VX+FOLO>rOP(g`OUOY5RK4?d(P&jeLF>z zuTEm?;cpM{ukIOAezw23Kj(Lq{rC&rTyxnOSE9RlOv$BZ)~Hry(rA2;?aU3mbX9&e zuzN$XPprU+AZD0^RYD2+w+TPuqdb5K5yK$I(A-^h(tC~Lv*4B9MyEzy}*%y4_BO-FjuYCt~Z= z*%4bJIbQ5m|6-@s1~vkvHJN@=?x3$T6mXFak)<}~xNf!!Dn4iXM9Z!}Ytmn=%58>A zNm-NQt~l z@siFWYo^G#pcO}=;=B50+kgD^7}K4ggz^{GOYU5!u=m`VOfHN z+IdXJ%G>D4(8_0P!yS=1r>FRPK-T4sJNrKhqD1zEc_42FWUVgrG@Z}dWzlOSiIfUS zrd!g*r_QdjFalL~68^+-izWES8fo_ArJv42!|k*)L$cYBRKv`1?lEMS1D!%Zy-*OE zt*^x&ND$5i_tYB13q2u*{c$Da5&}tbHkMgA*cqy3udEsAM?HSCmCw#?V-cI88ld2D zV2e+@6PA@Ca!Q@6dGnoO^vW?IQ1dTrd25;Gx7Ue`pjudq;VO*-dq2oDv$-N?%qSD! zUnf~L71id1=8ZhDZF|#|ptNk(w06%k?6v1Dbq-b2i1=+t1F!*RQ8Z!~0_q49S=`6c$#ToLwRGYQQZ+OJda(>#|8vK$jl z-lu>`mz>a5{UV7+x0U7B?K(N%dw%zP^KcX6oZizuxfB`f(-qYJcE;RZ;V^6eVb(y< zo9~QaDl?;bqGBDocv7(>5Bua*y(9ev$*jp(F%k4{4&8Em$l3}H?T3f|*(ur&NeEsU zx=3g^)-jsF^ASnEHfX(EW|KaQv4frDQE(`%-u^8Ek7NQIUxfWhSDxXDGe(9Ujm5Gk z*0J3c%rX)%04gu%{!Nd(!J1`6E>Ajkn#;j7t6VV7$3#QDGnJeYJ`2 zL7W2U#N;CUo(?X#l<}|XP9@x~+nzK(OaNP_i=q9tBGY#ulMq!7`z+>Fk;hlUF>hKn zoLjif^V3t49S|EDXJ{j=gQzb2F5LK_Liww3f5rXSn=QQT>j?@a>{K|qr{7Slv6?oE@CeUmm*T2TMXa4->-xJd%~rC_e)D2s>|%{X^XmAM{aeiQzxw= zoqU&1T}&EYGqC1~$p_8?ozS-!h0oO&!U^!@kEM*USc&<7TRMYBXW7ix{#d+i%6tnj zfp^HD8n?D4g2xyysz$I(Nw916m+A)Ybp5{B%GgR~+$C%8g5XCgS{XR)hyL0bIKWL> zXYKuI8sIWndiWKn>0cHLm$7=8KJ?oG*WCZ9oYp zjSVdX33F+Ev7?I;pkKb-8#iBNo+4(?@G>UNXVL$;jk5lveg~_dTYGaXwZqfr{0Qbs zxibl{&Hu10^Q?^S-v)g_lUp+sZ_+=_9RqqaK7wlPPy5)Qd-6|>c-#@(F>JVYfABIP zlJI(yX$9O+aX0>t{0vr#cc=@~8n&^pmVE==4O=WauC8F;;Fe=tgX#xKoJr~~2rVbogHH|~-OCh-*y3p_Vch3MhLqMjA zbIgc2j?8bky&Xc^wZpf<&oNR*oH=XkEb^B;o)6Fq2)h+}D8n9DS^btXBDE%xtizpF zdUzi5E3$Yf9)b4zN&KeXk>J07xY06rT1dON%Epa6-|ar21&wfsdKyD(f57lcNM)Gr z3Q7lo>Ij#`wla88d8IsarfWl=5*dI)gzK7Kigs|B!@8b=((U6VagLEm&A68p8bUce z$HoXg&mW5obs&q4bvDh5#aJ5w`$Wb?6=C2*)Z^#}suAY=f|Q699iJ!LSv^anL$&3D z$`OM+hqT3%ORfiuW-NDBFxOLDq6V?yATL>2f|kY?6mPq;Y+wl3Jzm)*#^th&mFp}1 zxw&4@Zho;aOi$ygZ|Jf2y@s41hjvEq=v(Skru3(!EvD9W)@Q^hp&4_B0sv5Ut9co8 z6bo>9RVW5|-<(`c`S%6iw3|8hYnz|qWQnp}UNy+p)U=q-&!;*4rd7$WREK9(90yek zHT?l>#51gD)5pZC=!Tm5&>-`imfVVzz8 zqGe2YRS$K#?zGm22JcftlA#Nwp_xzFrhd%0U43_-tG_6+oIda(Y{J79y!r(@d2=hR zJ?G3-j|7;ogE}0fNuYBcD!dPU%S3VTNKKyS$c!-x<|x+y%wq&5^fGMbsgr7K|{)XeArb7FvDP#Z{x$?{Xy-gREGu42;{M!LN*weGl6-T zhiGvlEz2BtHntQlGwlS;jE7_>GKMK-C%i!AriX}UE^>UC=B%jge9D08aZ zU)+T>cSQ&GM@G7!K;wR5VsL%Ym8Q~WL%3k=NSGXkEJh6vD*S;C2nz>?(wf^nb0_A{ z#eQBYfi8X#`F31q6f}PmZJf>bUsCX+YJK|jg!ew;;-X*DcfUBt3JD})Q4oCuoi8O1 zu`$ct_D8xc(+mo3FSP7KHyFzvFYrOr!ni`>RBy{vc~!?wVX+iI`^}KkzIZb7@Bsbt zP$5#b45B)081$z~j}-Q5*C{@JIVaDvx6V%*ajXyX1@kww12&2rM{ z#>Y1_<>Rj17DUvut>Sl#xn^EM_`p{8s;6c65^}m0&>cIP^P1Eyg5+TQ+A}0PLaBDD zngGrLy$%)P;c7}zOA+Ma2(gEwz!}eY|Ls6V-^t|&u9r1XHq7k2x)rn^!8m@kmD=ml z#Lr+4jF%uVF3u&`O1u7}HacBUFB;?{m1RcTTCCkY8pT+D8z|MT{bRRr{wUHQE5(QD zst{{fYB+tWT6W(f$B^KsRG5#3zKb!~PUwtAJ*L|fgUtG~SclFP4YLjq-i^NiQ&cM3 zIAod~^vkg}TS^tV9)?U9(+H#Io+S^rc01jqi2l!4qFp{13(qn z1!xNhdDzsBL#)vO|c`fCe?`BX}|%?0TEy=~cb zwxQ1%x#|KvEO9D`gun|@Zyfk;W|$%-Q|Q7wut^asCbOOJW)4L(^P}lQTFXz_Ew=lo z+@-Cvo5PE}hs|yy(YJ3?W;#OIX28P>c++8Cw#Wbl)1W9~(jlev7>l3_dz8YY^-F1u2C&IeE9Y9C95iU!d}%%p^u8ab@gI2h)1*-;AqL!p%4LzMm1d)@=spd|-j( zuwA%c$Z%S-&dpMG$9L^m2NF$cnr^BjPTndMPt$5~5fysk) zXv)EW()6G>Xv{B#=$`?T-|KFy;}8CWLm=Em7&0{IJZNyWz((!}ln zOD4o&_gUu7r|mg<(^9bY*<4L^=2YhzsPU4e8Y}5nZ%^bpR6^}Bq^EMCI?CtiuJ9|T z|8AT76MIt&y_=hRBVWW2*0zScktIjh5X9W7`11oQ?~#a~nGHt?636jf20Z^}nMZ2R zWpX!$XUdkMhj$s*cd213P34+q&z);SdmilZK5=1=PSux<5!rt2C(D!C^ic2lT06I2 zvGLuQlBO>mGc&oj9(E{wJ8+c~ZGKVx__<`8pw--yN6uG%y?Qg2BkvVu{QR$;#kQi7 zUy<>LmD#7odMP6H%BSEBvn3`8I24l}gr*(+zm*U$L*$jLWK{Ko7X$NpxJ#ne(YqkwmxNUcwYg>g6% z$9qih`A1ZNcaquxS7O9ijpy>xB^p^>BRN^yKgyrT@xkTPt^Z;CzW$+4@?=e=kRn2C z^Whb2OW-srml#OI_xM+w{ark^r5-|fL;YLGu|U3kXjF%8uP`;$f!T?UT5(XvZ=PIi ze#_l!4AM~NAN2P4rfj^hD3XK~+JcK?YFjMlM$^)j`UT7%#1%rrj_2F)&*YzkA<}v7 zWMaV&4DfC7Y%z_xWdxxDtcGXFlyBVoBfWyjM5JRfU889m-fCABOO1V0Y~G5|BpH4c zNj#Cmb#aRz%1UC6t|fQEUYqTnaTCDUB}4~2r%E>hH+6dOOR9rM<)c6mTY!Dve-m>k&#wPFI#*jsGHa z!^?O4WiN=Sj3@)SN1f2RN$W3-$V%(ht|cx8xqx0X5nJ$Gt)BcM{F)5a0OWdVf_d2` zkPrTMY-@z2{A3T*zkfJC^W?-bIJ__?OqI?}>)rSUq`>wivv9tLc2lM+0dt((SxcjT zwTcL5zC`w7K2Z1@>$??#U)5#d3%GXU1_EL~X5`8#d4!&*UCoLQ_9z4F$J%U}<1LTN zw$l|A*84RID24!>J7hM?Mew-;;$YLpfk}cGsZU3iG}OGh+a#ZN^lfP+b6Bwh+BA6szN; zkE_3q=`|6)JEtmq-Rv8}2%;u^lqZ5|t_zdaHXaDrmA|2_?N#vNJf)b%=3@su8M`i+OK%66{V!Tn0w+u>Y3Nk8{$9^QsWc) z;@(B?LOQdQKVM`YDCn%otWAxsY-^PYF=H<;GSu-2t3tY_J3UtJWb38f_PnuOSu%rq zInbRwM#HA?*Xme#)T$Cg3n$!Xnsk(>ZWB!=oST zm!U|qUFu|f9K-kSk|j?9Il83$A8QF7Wz61QEm*n2|LtjJF8SWh6Ri%aXph)^Be7uO zg>lNQ;s|#QYG%ma1Tg{i6o-;I{*r*Hb`4z5PCK1N@wV3+?V%AH4!}lc%dQiX!CzSI z>a8t=l}lv$cs-a@kA|}e7x?nDBS}~`Ya~idYy+m1OjE-5-XO~dpZoMJUptCt zXSn)g#hioS@j+!Q17w55%Oq64FN25D-UuA;6Qik^pD_lI%c#b0$RW5aWw0#&AoAX@ zAfeoQbLRnaKT@>fOpr|b=Ps^E*KA9z`QewFPeiVkvzDDsa?^v_HJ^IE9x*#gDHY1&Ttw z7NH*@0FjhD&2(f>Py#KZ@GJt#()?dNR%h)KFG(z_E>lmeH6i%qx}yJ8c9jc@w~tDW zO!`V}m$~XL{Q8u5Pc&SVE2P!_ANhQM&G5hvCJQ>Zm+I@(yv)mr65y+0W?KsOsq~k} zL76sN*ehP_ExO&~*6_LPNPW2SJp;skU@=H{uIkom{h5F-!&-`F<;*a_8ixVfReq*ImuUHRyDC9CVO&a=!q6o`f=u3K} zlb@AtV@h87H{Tl}3wQm}>E!Okeb+@bP8c!B|GZ%5MRl?;O` z?54G;abjA3Pu`A#qwAkKRMPSWd9wEw496jUs&I1~FBg=>#3sY@9*mvUI3ao~SITs! zNP}@~{#biF+v<7DlAE-*7V0*&)M~dWcN?A+=3$Mg>b`*BCv$4@H`GVT>qT-qzSxLt zlOYfj9pQqoHa(&CcPGYw9NzpmaTy3QoKhKPqb!bOIQ;@ypDUxZwOi!ar}MmC$F+zJ zmY#b?$NbJ~ac%#ZYQl)Z=@phht#fOFLK?ayOh+=E5xL5SH{SWGcE*V?Gs!uUZU(3} zK1Ir}j)?CS(FMJKxl+UUV>{3U7PspY8#2;45}gdPIi*J-o4s0zuW1hW@p%&L_vdG}$D=*Fn*VL`$^?D+ z_z3Y&+p+gTH}3ur2aB+n_mV<{1CRB=b&?wuV)>YyVgXA@2Fk5Z8|S7$Z@Ug<(|Aq7wvJZZLgnA$= zu2WhIBs(b~G!8K>$}@&`YB5=Il)RdXJ^i&~Bhk}S^>-E#Rb2@%VOZB7?vjGFZT#U= ze7wqjfG8~c!-vImRiUV`_=?M@h19ysNTw2!)1P{4WpkkRM~B2Qp?Glm57Ycf5_G3!*h%plsfu4+9 z(CCBy8p?>Zf5?kF3B~#DL;03g9dzVTLjY8u3Ds&Nt{wIJ+LGDCFd{EVm|nu8w3IZ4 zD1L@xWGR&eNeAtkJKOchJ914#w3zcWcmF|Dcq+)@Ev*FU1@E`8Y2C$bu%F}xo82V6 zd*g^(`Gxrj3dyIKr~5<91uIRbjq4*Pn~TU?_L`-hz>iEuf zOXlc(h{- z_z0P-PO|}c(cWhu0gt=eWjq==0m_YBwD|MKuCc}A1!Or1{tTTDnLWuZa885!~pM;;=A}UhynL1}?gEB}S{>k+3Sm=8$@0<}~;>}ju7nm-1?iWCD zibZCb07Dd!@@Q>&4B=0j$Gm)Py;nPX+87`6LrTrFWG%W zCzw+++x0hREGSJozvm;7%m%C1GsX1x^R`G?s3sa~I>mPQKokQOq|K@_Ff%^}MOPQ# z{xN}XMT5{oLH%FpZ`Y`Z5UBWyc~SC7sIy~(Fgv;Z1@qNZO4G2+=DXShx6}Ot#V4!| zMXX0GTXFh~sp*?XTKg+-_fPveGV3*uo6SO}D8%LL@)Io*V7NFn66mGtKp)P5oqS_8)wIZMP58a_vqXt-}~p$59XaaOge4C3|zu9 zgoD#&o~1Ov-;FHYpr&pNU+T%J{G^(U4*ullA{uD&h+DmfXm!hD;8!x}2vm0tfM93g z$wvJ5lJ;ZEWjC!17ZtOsT;SJ;z92H7=_JaklBu8QaAS)b-P;6=BN+m0&pMQ!Lk2}a zt6KTys&MBp;u5SL;lRoR^GAkm)G*bAOs}MX_DsX1ybD-%?W)LUaad2zjjMo zeMaikyoG_|Z`a&E#6;pS?`&^o*<)aG&%cQMoZ+Va`%@!zeH|`CK+&qOb*!MM1PlG=SPQp#m=+ctJDRlDJ{x;Hyq9|==$rm_}2c|nx5?E<&xBH4rfE& z3ncE{^|X~Z92GtGP~9eft8to6su72B18xpadCpbDB1=LDnWDpc!<{4Z#y{ZC7cw#> zN&IQ;y>~oq-A3+K*n1?MJdCs4YTPjR2WmL%QF{kCcie`>GUuL}XwJv{)%|dVeE}j& zF4lKnhDH*;%mU}k9}U;; z$WAnl<5yx}9D7D*^~to$E+DR}+bMLe$BfmApLDk!N}YMa{;j6oAlo0xb3as4-?kKP z29bb$=?UHgbMYlh$wVdDfPn9Z-&6ggpe6yAHNZAYaf2Qq=X{^6craTRCjE{z&1(T9?GG-YV-&z2qb{bc(uiq)G)*WWD*k_rmNxg}Y0Um=nHHN1QWgISAMGjh|7(`j zFxiVWCc9C=Qwip_9UjlE28anj_TWJ+3v&pFsYo>x>O&ZBLhiiZk0&aSZQGQ~EaGZ` z+6T&WKYu9f|58ZQysyK{P*J?OdWRh%**>VTa<`E`Dz%JYI8EC7c>``oojRw#^jl6> z(`rQMpz$!vLG1|sXh;Ajf+_JYqALtE+-%$DRjia*m&#|XC>ZzUi2NKTiIx~tC<$q7 zo>SrfjvKgn@}L-RoxkSR7#HZjhVSKi1IMaIWc?>$z-8DnoamYv9ZQcnan07Nbp(pc z*jJ>@WhAO<=cXYT$?3($BwpZKm@ABvoY}38-p|@_P#1!;*kHM*Z&)8YU9Y9!Dlt7 zIf#AgA3z%Ev5nI|{^q)a#oH%p;M=PV=V!Ar#JoWBD$XeM{>(W#8zmzHM{j>J&(BU5 zQ1#U!tK=fe6z&5KZk{BmbZ+wR22fy3^(n98JUtJ8h6IvVcbOC}gCO8ZWYppg+=)LZ zj8@Mu$_W`Jh+SQmQ9n6$`?^_t^Yc9E-`yRCcouD}7i`u2%2sI4`=qkD6+npW-J1+- z$RK213$S4o$FvbdpR9w+ub~^|F)N8`Tm0qEzc7GQf8Iy&^~^f@!!NY-5gi3L@p|`; zwfG;p^JPhDpQ7`Yc9WqIB<2kMlL(|EuzE&%r)~x>*GGB5NB`hyx{!W%w|ass({Q<| zQ#A2NEM|#m+f4Br>q}ygbhDUWri>I2@+NH*yVRKa73&PF3`FpEKd|V4f?D{WN3*D%{fWh zhg5H0#Ui?Dv}j%;;8ydukh20=*FDuZf2+;bNpB9`u)2f=QCVZ7KxDIr<#Vm*I5<|o z1t`LJMY4Z~=6<2|g^I>Yd!I24ntTKPy&w50HDBz)7W(2${Y8JNb?ukK?Gdq+?P8xN zJk7Vm&Gt}>BbhJvQ?c7pwtde1y=WUw7OEqV`D)3z6dj1JT+IhjTJgxm4}a_1vSCl<<26iQFt|Z-4hn!r9A;q7(?04~jF4~d8KI4}M#DHtjRT|2pPHK~ zoJ2vpY!A_n4!&e>>1mA8!O1y)#d53u`KoZSRMvb^l{k;de8g80vjrX!M!A!Gv2G)7A9MRXVrcQ2-vB9m zQ3ft(oR&khjw2gigWrmsw2Y!YF8HYHS4Uu^rAJT5&-%Gr z(aECzJX;7g7&nuY!B_9#vIEt=U=RDkjzR}pFx0LZVIMryB46b7qFXE)8cv|9uhlFw z6C#v)-U$C0<>81iR_Aei#~owZDv9qo*)jdH-}Kr&YepL^j|&dI5F^i)aVF9_k9sqp zzF}8~qqS-O4#i{C{oRKsV!^P2l{Rzh=U~&J(-tWLecywuK2F>$qQX0d0R`pwmet$2 zJv|$qSj#UV4dG%D#_m_Wu(vlVzt&v2E|42zZ=XdjgTy(s#w&2q^iHTf+D#;8Kera9!;AGkw zi$`E+e#3!i40H(-IZ?QQy$eGwN*)$m$tn>6fNar|;B755^Zcz;SJtC5MbuLcQavGf z>DIgo^iLKhu4{Qm{y3YTvK+YSqVtf13b46M8NW(S5T@ET6&UiHGPu?2rh4Gova1$e zV-=4fW*eyMsh@A(=bEIq{o*f69Nt!A$x_y%qI`u1{BXI2f$#*5sMN*_uJwEP-vqgI z%zS(ZI)Xs8Bb|d)vo}3$iB11-x%ru&=pC6pRZs#yQ8W>!qOjkjaBoW2T+)4R-Y1yh zLVLwKZNDg9%xJKmyU=nAT@MZ33L3%mVwG2v%$A&LSWh0FpSW3`^iztc=1X&*LRmx& zSggbke4{6O(>LN0;_RL66Tz7@ zMJNaR)I3>fa%omBu;RxZ3Y@f|_3lHaq_O{)PK~KkoZ|y{_weKK&%5LMJ~> zO*}5NszII(z02q8>8GeS;lDc-eTZKAu%| zmf5(VSsoQmq|D~O&W$GMvHlk-Su1U*>aBGW_$7u-tSo5{<3|qRiHXjVdwMht=kQ+4 z$Q3t#zO2c#BmcFM`vEc7SMNBbV@5MMKMI_lWI4%$B}E!rT1^y4>4cJ&V{XXQ9i)7t z*|ZQ)&9HBdY=vrkmYm|v9c_1~Qut9##DnN6i?({a8^#-k2=`9cg(Oj3Fc8ybJ#&!t zhSrfM&b!FI?8VnFp&H=Ya;wEH_jK;J?9op{_Ex#Bj}Kb#V10CngV!sw9LNUq&mG9P z4<_Gpu8(q_B|{L~k6tt~q!s$Z7ev@BTa3cCW&vtgx%Wfu3e-7^5H@tjwJF3(jI75J zm>wS%@}=KKx~^1N9~3d&CDTF&oiyv^2_8Xc@q^`(uqUPTGW&x!`TQfurQAJIc3LLl zYv>6*4w!Q61(qhF1$r-D?L^~iTNS;F9^nHI=3QE(bNXS|Ld@~*J>p2Pz6>Gq%AZrFZ6$hGQ^ zg37QcU%86C&puL#;OxsC1viIDgc=WGzmPPVoyRTCsx0Ny>%}zBAG=wEdM@HTuL+H9 zbH`KV?ARtnpQ3XoxCV^0u=h$V|6L8Gv1;{;+_4(4&;KmhCQl(j_$!!pbnM{?L2byobUyMq{ z1BHPGfTW`gR7W%M0wKurbc0QFxaO;*oTQK)l){qWAAf+hL~W@PqyZ06ed6_ljz3aK zGZr0hIpXg7eILjj8X(;7kWLAS_J8YR+Up(VjyR2a$24)ro7OP(JlX!|8Ym@5o0Oz9 z{=+W5T;x9Aj;5fZd!&uj&23%`mus6Gtav4S+mN?saup~wyo+zywba#^sRTj&iL$PBIV zj1rbj&ygN<^hsVqt8)D8T&Y*^iEbLo6a1nBs%M-$gve_eDL0HBL#{8as8E(PxAxAh z=eg`G@_tifX{R>zG;%asE&o_}JhCcsp_%_D)2Ddf^3!eH`hGPJ^ursK3q3p*T&gqJ zDfQ)FxTql`b>g`f>IKywgEE;O-$})(p^|jlyFz5D$i82}2XbG=GJ3>BdxBf!WJ?u* zBXH1%dUmMcs%TkhdFb`w$J%4EOMDSge$t=FrmT=1!H$l>??1C}&JEb#-{z-%nBxzhKO|NGBHx%TOyD|EFLHs9NOs+6U412*;g z!R=-3<1Z8cXF$a>?oh7QM?Uv>9&?@!xkJ!@b?XiUj~alW{NfJSYl7A!ZH;C^ z0q7mYl5uI1`MbSwv$$%)m1H4Uj>ESj;kMhMNkM!1Evga6m2WTmDGj;@`r`xo)_kN* z@Y3qK&8+x2*iCJ44xe-M_UYC@ekT2oVt`$AH0j6|zm%<~L1u5)%BhW@X*M$rwgFtB z(+SRItL*ROwpM_E(!E5bh+)CP*^Mvph=*my@OEUh1uA3uoLI=OjlaM<^gzG1;djQLtMk>#oqMjuXy!OI6@I5P{4@KKsy!-UNOecc)?1`6TTrv^>%^#J?<kFcyT;yY zyXi#*vGZ!R;C=Nq1>hW#k?L*9WL9VEP&pa$h=wFC^e@3aTY3TT^kbNS`PlX?pd^ixL#w<7X<_7dFtwJc=|qSuM? z+ZN-Cy%wWbwzBG*1B}O2d!J=)Ena6ihZ^R1!Azjr{RKoJLFWr!xz)Bb3wBMhGpL>+}N(y^D#Mw;yw2RTd8{0kWv!1%dNX;`;4~d8T;iJHf1L<4)t2Z#{om@+V zHr)P=3_6#;>2gp$PnxRTuVq-?e@6?Wj`t47|45I>t+IERlv+Q)-(9KY0GU0bwqrN% zqmKJ{4UV6rL}~a?5MZ^69`o23?%GlX-?AAIMMe(Z7N`A~JleqjgSqdi56Yv@ge?mD zIPL>V4=Kp6Fcj0c-Z2-~XVIsNm1tE73L6Nd3phK&`% z#NzlU0%5<)H$R4gBJF+1E29S-K%OTW88mQfp7d8@+;JUcZ{yfCzsEon`t z+4@DcAnnvsUs0VxrfaLtl)T5wJp<)81s`d~Mox~G1rk0>dtQ?{cpPacmX-c&_MSg) z1KqC|H3*j3s;YfPFAqy)C}EbmtIy$+_qBZW4sPsbs&3lfUk3E3=kOu>f;BHUpURm_ zVrdg|KI<+K?bO@h-YLvWwmX+LLj{f&!po69;aFzNW^~!2WWkoh?>t4|fUJ6fLA5za zH?+TuyBJ)$^w_*i?3Qhp)MmvT>mlL`%tdKe&mon5jd=|C)uRO9;*Uow!}0`!KkrzkkoY zO`^Sm?^K?GDyT&VkXsCASjAMU(dNrWs|&8A8(J!L>V)Juf?eu z?Kj+LwFx=AwI$3$%~6~_RzrP^wc*hLzejK18Oq&k$6vMiJPPMw6TcUtd|ub49u9up z_E2!1^-eY$<`Lin921s6^B1mjoT-O%_Wt%K3d=SCw~phUHcrg7#OW?7tq_qz0wnGQ+#3#Hg-=B}*tf_=ZHc(@h&u zi;8>8+8HT)o4Ic9h8yn=ymVbWxQkJtN-;ov&Hb_M**C{nWsKh6P}JQVwH?Tox$mT* z!;jUMPbSpxLMf0y^!ps_>(h9C&wsiAne$=J`;i$ zF7~@VKT?`YJvs^+WdwW+HD}&by|MF_F>X%*Ihn7ni_io%P%76so5NS-V*kpPCE5ZB z1$Y4_j$ycFP&z9s>2O7F^gSS#%DWz0au1xmx0p`vx+HjY_EI)66hVR6b-pZTDe8BN z;rogSsWmeQ{gE2$cCM7ia8|# zu52r_qDrJkQvf2&;`#F!xgsuAQ#yYTP-OZ<0QM#!T(*_B_|TA&)NduoI`^;79M5~( zhjVrTQzK62RNhyo0d21MWriLWrJ}2b-m;YaYy?-#X4n2sC$_^sGSFv2YZ%@e(rfPl zp)WDK?B+GstxrxihV?$`-+qS-3>y6k%M4v>=68HT&Y#tM*!a90tdT?e{DBLr1>ESe z?y4%(_RtLj5OfKd4ekpl8r~*&XW79+mu|;CfojEs!tozM1~a7>`O|cRX8s9T#njS< zmH^h&LJh{`GRpEjzS52wq8*Y6CHV-1PPx>Ulb&t%BGx7?aO?}L>4fg4U$_5sL|%hE zi<;+*)QS||V4E|Lw#YF^o!tILNFoLLG5D!%?h~?Uy*Kb{ETBCa?}EVO9K(lwz6prJ zeUO%A_o=Zjf#6W%se*8H7GhR_b!AN!=zYW`G504@-&Rk7E&L6d3`JF>hAAO;_>HwN z)b9$KNoolWZhY$t&wX2{^!QfPJ4fpW8#l~c~IL#6yvi~>p=W+h=9Ra__m_5 zrfcCF@;mvL09Nb|$*Mcbqlw+mKBneDE@I6o*ah`Hq0O5B3CE4JexuIKngjhUiUDyq zYZKaTaP&rHZ9k${z^3PG5Ouhu;6=CKgWoL+?moHP0lj&%pnI6G)2Pa-w7PLQD}EGa zHE7l296UCD!(smRufw?!!mlo!=UxM0A;}N)oUoIL_w`9zUttG~PLt?+1yL{8Yj^A) zL)4Q-4t{UNYp~}ExiWc=kwV@d zICj{WO+zroFk#AKVQfL{gpJ^Sjy{GN`4>qCABWOc6OKb^>z_rHUZmXZh{2H$fXL)Q z-sj$Li89pXJeA!i13fNE4_?}uls{G*D^yu}DS5@^{3|s=y!G}c!sVwKEibp1`Pyz- zw|?t>*r|~g^GK@mr^3J!{-9rvpG}(!TK} z6t!>Hzv0*30_hxV^D|HS?Zv=18V^tJH>cgpk-m7mRK6v%YETg?a7OxSHpTTB3Nt1> zEp`wYdiH_>7Y}p3_%EPW*Pr^4UEeEMyed}0&Kw7!3Nj9fc|Z*PX2nAVyOEa%|6&CTKj$JToMO`tO;WZL4VnGTe!bFxz0WzO zZTdHhf`ppK2(^CF{7J~*Zc|-{0W+M5-L~={!a$oJtPP<}>jr*5_^7_&=5<{evUksJ z<*_^awP1JP00*maiWi0VqdwsJ#v3`z)0(;RvTpzO3ewUyhoW%@k;RvR39)7T4=Uw{ z{{vilF{Jh8mBas-KRiRD>vM`$koJ2o?6Ufj=k9He0Q$l$d{41*hN7?FLe?!R3o0_2 zuF@lCuE5+<_LD9t)Ac$w7pJ)mBh^IjL&6T*ohg&n_b;qK>FyvVz zp=vD?89I+Rj08^deC#bi{f#meo);B=$2QkG?x~g15`2!mwESxxby2&bTD?zWl97AN z-y~#322J$)7j}qUo~2}$)pRbXrjMypfVh?r7ng`;yJUbxoLTY$;SLrGgde`-1cO(q z8A3&@A(73WU%%`=iYV&5Qw?H8HV;Xzu*~*;c+_Jb!KQP9WA@tAb!!ba?||g?{q}xW zp;>;Nj8}75ty%@VmVKwLcLwC+-@$!gAM9!a-}E&g&Vmd5iU}GBx~E8mTct7crjVW9 zdL9XF5ncMrl7W{8DX=%=?K-Rks9iDuN^e#n*Q)kHeDG(d;d!y)7OEd|_YAg8!dL^xbtP>+A}X(uyhR$B z-Qwi6hN?w z&=>T?)9u^Q?7M@!hYYz0lR;JcH9<&%40;OP)Q)mk{3m=BZTYoU(lfUicam*Tcgptv zGyax`C1jmV#i1>8Bxf8X@uDMdbxU34S zQ)VJzAE6c^L8tKp+&o+J#oWvF0+jom+6#O46dM)sopW&|(+Jz8pDBF@d(xO^-3ND{ zAd~jouiJ3`6lYDh8ypO|12iuN*Kn|$g}&iW2n4W`kL+J~e$b!ezA}B6q_iLTUEWIs z^78UMDBh;LU`u4bbqv0ZNNQT;T7K$R=4=y92Y4mssxbCGGhCc3(t`YM)YM{l@(#Xv2zK@a#DGCdMPr;HtH zwVyEAFL%M_L7KfN3~hE$qs(;so|>aFV7owfT#mVs20MuOFmc#_~FoB|xH58>B4KcUVWv z!*8x(7B2K?GxhSeabkP2plZ*Nh6M9TufX9O$J?Th8t%@iWmHHP?&s4AU#u7@3u*uN zfW#Tk>vQ>kwwRCw@p_fZtc+?uc0*6U?~}djyGvCeR8lIi2*(S*9^nvJU_ZV7t^b?V zIAy)=60Kqaf85`?>^D3Ih{;K!2{xBbwZL9B-Qn~rt8&Af5ZC$R zKYxv4|6yXFkmv)`%@r5iq!G$r7&L)4f&U5eP>Idye?5%7kL=m^jC_8SHw^@Abs}&_ z!!jr%7o#7nt|jD6>FBZ>=+ZM_M$N0-&pDwvA?#0KZ9Lv zirOd4dkINA(=F;_$Fp%)mgdiBt-@l2UeBqn=ozBlD(orK``8h5`NNBt3+xqs#0*{m zI|a|Ukthgh1qDXwX1ybA}G@5Le5uHY1zD{GYX-=XW--Fei5ZA*wY%@76 zXZbe$)0E6%&sbK0xZTG$RjzG+?ZbrW2GjV3V%?GD=&Ss>-VXEOc3J;`1=k@!`tPWI zc7jJcsa9R@Lze9_NiM2Ab4HoonH>T7YDY9?uwd!X8+N6`h=KEBRxT?oJY(a6U zTr}UKE&{75Yqx6BQ-orH$?1a#uhXqpT^E0ApGy%O$d}(wysH@2w&1%qcJj71m%EyU z*#6(oYWa)$4^|Z*-SyaCC`@>wp6O0oUoPs>QsuSX8xudh>KqCXrmL~cDd1|oZ8;F2 zB8NNB(g`=<4DsC``Bm%-adpG;qW!DzYbJK??_Y2-4T$JqI! zIY1w&<`!AXw|$?ncL*WQRK_@PXDN=NaV|RHa!cO%U$I~-zZYw##JUuGUeI3Jy~EA* zvp4;h@Wd1nTdP9VRM`Zc=AwHArxy0*)@9Jn&$!K7yZ^IqWfFCsSAf(z%e!h5w;UZT z=m$i;J?Lk&iAq&|)_&^Wk|(=yb=zV@%?v?Z&P@>u7liB=Z>PT^xQ zq_P4&ZSN2E0%!{3VK~J4$edKD{vx=oQK)KnAK|7r`mz!ZZ}}M@QC&L3eYVAZau+OopTxS-g`5J{_{Rd z&QG~|Fel_Y)6%<^Y|4||>7kir6#e>g;^coT!*yf8qK!VNG9l0-{C%sbx%bnY&AW_@ z@M9&)q9rk#w`5qeXyt!a#mI?MSacuMTO{#StRG$j#{D#=QVf^Ia(z4smv~dn7f@ID zVjwfeErb054JuR2L@oHkTg$W_HV3@O6kq$tO?=cA5ydc)sRt>q{Yj@6L(^8mHKrfc zPiQmku;X-#6subfx6q_;rpj{XX!I8=hdW;DZkKT_96Bu1)EkGuuw~$+guKH}^Gv(E z*ZCuQ6N8;PIxCNkZ^B7yi5{bQ6pjqorw>p-K7oEmP2bVr#*(r9^aXj>Fqp|Q?401s zsJ$#XVmRhmIS^YjUzCELt%)Ng#5SSXU1;Z_$9gmUOI4LH`2*7hqfX$0q#bv5I0^fQ z#G#RT~gs56j?@E3N)-r)T9X?iDvhJT7&PBtlKV;n^N7CiX8Y z%B?Xl1i$fA+y@UbKjFlZcCCx^sBC>gz$!9x6!WEO6ErmIiwfmPxN>h|-q- zx2w%NO?t)r9wOP;`zNg2N=&}Y)IpR`{R7(VmdFkN^rCVDc^^%@Xx1fEoB1o%7i`Ch z>8FNpP|LK5Z$^B7MegKVI+`!$NE}};-u%zDgtJY)a~&yH=H#okQv90uu}#SI3fMb! zbGqfJ7G*=q4`Fs)#TWKqk=j;7>G7c2=$=asid;MTNc$lDh1GS})g))>ir7vXRDP4NKWRf*RB`2<@zp^-FOgyvBzsw_$F$?u1QtU1fLrNrZ4+ z_If(ZyE{A{^0;T5DD4IpYcAjO?k~Bvl=X`tNr>I?C!6D~cz-e_nM17qz8(7idH{0G&Zp@V?FuV2l3b z@x;sN5Y#ta#7Aj6i8HpVPVf`jo`90Tj0?>T{qWm&L%el-|KnA;s~9r3bGqsVUrjHJ z{Q{zjspSSD5xVy}aPpI?UZ~GN6CKub+pcdhp+ypKtY?|xsaI?(h5~FZD5}Y4;i4}y zS*Kj*#^2TysknyMHzz(+*{AcMp5IEYAN(wZ=c&ioH z98dL?H(l6-4PE67BXO6qX5_|q{E1nPp&I3`Yo!qY0bTbAwQCn3r7V82blEu5sG-M> ziCGB#LcG@pY0qQ=JuStK*z?EN^DXzm$JpCE;?N;XkM`49l@Ow~79ydn98Qk!-S2JM z5Kj-fuYb-{9u`JA&seUC>&qg8){UQ`Ml-3&?uzE%E-(2@N9;=_J4+tN3=70u9Tza$ zNG+D?)Jr-H&3J72&<4*HsIvE`IsxC8x*v|#D5HZ)yuS5%|4jiyCx z`&lI+xF`EkXkw%E7-|8-5V#aot^KTo-%`q{~u9shr z81(JipuGN}=9;QWK9LV_NpP`MYfwrH2!74X@LU4c>w7L@UMYm29d zKY&-vV&F>z@ALiZw#l( zz}JnXmhDbT?rr!`h*ZcB)C1fG2>96arNch#E1ahoQTzM>usK?7Iqt)_(cDtt1(!$D%3(ObO6~V17x8?6CgYP)Z*0q&ZW7f;f&Aq!r&4r~I5F&_9p<7Y?>~}O<3Gr?kck6# zH}r#EfXE-N(#=BLf9P7{?HQ#5yZ1<@^1*b0eGC@*n{#?XPZ6&g^!a12e1029JQpXA zMWhkT-nrwhJ!fa+e*G~kP8z=<%NWrg1k)+zqT;-!2K(Pz zS8vTVo45B-<{yCZnm1C;cD33K1U5z<)4qe|F*&~?@PHGlW0CTkE!KL!h?KGVIq4|y zthiy~WEbt*zS`l9L4#%N!2YX5n=_rrxte!u!eBA-hvvgGs&Mvf>{=u5w<1iyB55np z9}$@--GO+(LLB=J^|&5%w%~lPYjON$KRYUZ!}kwMnwPvuxy{n{TErIZ-&XDkdjb>d z8_HMQ(DU$`&X5n*>`d$h;yZe2_;FjMp;-Kua62<)z}FkHN(5rfmbGwW@{ zcXaL$0&`#7wjmnx-lHPYb$2wF4&l+z7~ANQwdhiSpd9v4^?q5T?y1K4vE4!A<*FTgF{bsj$4)p~2{NfzbDFpuoJS7dg zJ!I}*Xt%-aqC^!Sfr2+k3L)&}mAH^zajPrJ6vR&)PX$CwkfKNAbVm7<_U^yl)wOj6 zV4!q5wO;v_jHrsNAj30$%_-Ub5B_ijVoky%1BW3e(6x)Jm??}Eu9uFvhgu?^e+93# z{6`1Ahx*+W^F2Bt!OdhXOmDPDt6E@gDaWmL2OBssTVl|Zmb_Da?6^BLFlx*-wcW9MJeb@?e(g)} zKX)_d@p42BoGjI8u?qHZh*4A6i0-<>Y?>wAw0?FUX6{N!uVj;$DKL30NAe zrou@K)hwbDhr8%^{E8R4QXM=Vce+Yd^$JxfEymD1c8bi|;6#4ZOP+l33q4$cns1l@ z6O#pbxg4KK!8r@=PR@CsqZg~%WfMi$sL$bV^a7UXA2tht+?(}9{Gp_P5y^CWkM6ep zsD6J=iRJv;xfY~BG1R1e>)Yj?bD-I+E`+lQ@q-ZeffICo*=;DfHx82%*H#;gw|0&V zp2&CF@l3v1c1@KcS(ShIbd~ObZxv}s4F?j_1&E1L` zk1IHJW9czYZ--mHpijYcVWS<+K++v_h2~CP422H7u{$&cSKl>-qC3s#{)^v3wo<9p z4oqkzI{Am{X+0%o#{HZZ>r*draO^o|Bjpsaa4s3Vs$UPzXO`C9T&5oN$xVKRe8FGM z)~rZ41fSRIGd&o>U3roXRGe7H*zoK9ZI1Ul$S$O0kD|M@ijw{E`5pyEeYj?ZU|@4D zgcl|T7Xm^Z|2tmA5$3U8&oq6#KnP%-L}Mz~Qa@Y1SQTGPvf{xIH zYtrJ16%?W8xtK6!K`5@f1lK&;*S3Hkx9+lz?#U?b=V5^?MDz9l>_ zNhK?gFM^nvF<>wofEol|DN}4*x|Nq)5pw!6mzsx@n)3zMM{jN!$EeF)HkA$fP~+?} zHTFtq!cb(cP&sf)dCo=l{L@&oD?8urPE5Yej^W6xkSE^yp}1&v%4F(O!-K`)6v`I`-s9<<#Jq3Jm7-;?LT4)AH)z10hhb3#C3X3|W>$&+ zYB%P>?&FO-T5?`KysmMV_2hVfJ%XmR7qc^^NjioZTfZX-hrO`V#JfJ)cA+i5*tC`f z_dFA(cP8i`F7dfOqRD6MzmKOwFcm<;F+XOrI-F{l9ekB~ZM$+A@sFLV6UlP4&IT*9 zkC$^8qP0R+Lz{@?gQtvj%RVMNe#fKLdM@ivnE%hCna~{E?1NBW4OocuIbfs<-yhJ~ z-F$I3d2kh{(%Okc%RgdUpMwkl>l`4S*1IvX=kzaciJerVxIcZf*=&1N0KP1&pea)o zw`8{%T@x&V@~0u=4@p9FltV@IHS5dJ{j2+5Dr3WbDeJANdok`Y(7mCArn@W$o9HX) zdGc28(bt%E$*fX7@Wk$uL%XU`fseP!!NdSMU#?T;T{&>yEGV^AFx~Wsw}%wgrwdYS z+wflO|BGa}TtQ+kRXsHjA&wfnhz(ICGIBRb)yDuQKG3E$cM9K73AeL$% zi%$?(GiJ|q`X>bN&T$*6()!iZRNh93!|fp4-qhxYj(;v%evSFROI{w(gfwa5M0WN2JB9l7l-l zj9Jw>O!h+41VfJYwv~g7-DKs^bDs}dfwS2P$W^hKvu;Kjhg=`>hYqtfAHj}6`4hL- zWl!y_T{TyDzIM;--24LSoSB}#6ZKzK1!x=#RM^}rn_e6Li;Ec z26YN6srH}S8wa|_D{)_05jPrhxw-G>q}p+8g)|Gn-TbMhmDS8hx|~*#rxnYtz3kN$*PwEN=)#HSI_g`Wiq82!=pFbOVrazTZKm%VFz~jk!+rr{IfM8p4T4I(=^IO|JJA>8aSx~TB^ZNUIyn=Yn6EQ-vK*6S6(?XfNLBX z9PaP2O+)0@vZoSp-44sSxWD^9k91_Cm7eSYmc#lnD!z`cLO!uA_3M=KU^ZX z$zi&Z@3g6I07NK&y#aqWFtjVOQ%Ai)sWCm0hjp_WIcYxf7uHTh@wCot3m)u47y!O} zbMF)E;fR-SK$5ysj~Keg#ui3lTyzJ>i=9#xCN7zAHdI71Gnr6y*{mX^uU$-t*_!1t zQfoQi)$oukj@n}@93V{^u?6_BdaK@Q@Vu6K5G!9^VaOehLLG(^^mg67mW2tAp zCybhK|HkH1o+M_{MOa7FQoH&FY|@p2&z;-LdOb8lmZ2<6P(OPX zlUi!R zsYLb_P>}Cx?Dq7>^^)83td^d#?1=zB;OonuVR393tQLa@=YJ%(e56dB*;Nw4`_6DI zrp>%SWD>hfnAD;G>{+XxFiEzW7RJ~6FI1Qw!5`Icipmrer>3lVlrXJdDsJul`~rDn zgYX3dwBI%TV4k6$@zDLlnNk_};#M;R$r4}6AEdNm`2&iEf#S)Bg6k=^P;;#RX7)na%dCR&w3jmOpmdWuv>=!581ru&f9+nwV4}BG|64NKsXN~Jc{gb4C*Y$h1d$Vg zo((BL1R$t4r20Blu0P{vJI6aJQv+eSkzx4eC2ddd58w@_rbWG3dgn|*^Oj@g7{p|H z_stoWlc#mvmbH;X#@km8aAWyq$bY(09I{dW5+n25avM~i1X=H%47hVR++p0K$tZlv zUOrFm6k9NzZRu9JVBeHUxh^PW))V#+9Y%om{Eah!*6vDwyfRcPSk`^}PbAdC4=F>@ z7GrmaFzZLM)2ZyF|2>y_(aZPQ}$5pe(>E`QSF|G`+DhquhhG>daEZFqA} zU=JC-F*npIeSIiwJppfX@dOxfvg^nE%lg_Oqr5iX>nZ;^E#+z`9F+LScL*jsJ>S4| zg73dI>xC?(-~5skeLGQ zF)8D>|EwonwW4Tnt<@?CFT{2wcmII5u-XNI&y?4z9qU4cXj6eh1~)NWK?aTAag9#& zr61{7{G}D!!a2{8ZL@W-27RcX3PHQNd*AjU(4@{%LnRIu#KMT7jHoF^`zj>;#-P|) zhJK0v(@s@VN>$fl;>7QCcT>}_>aaN4;j?nK-z~_u<@X5^%Z)`xcHOnhTJCzMRr+rK zc^6^1PMQu|4K%~$cin9|O&OsCg8|La%xEE4&lu)0{nMQrjCtmK4#yEv8UNwAaVYzG zoR4r-zKW-NbeA9cT$#LHjSiGRs^LO4@9Fvtlj+>kGYbUubHJ-t2(8vUj3@HHAQ1~u z>-f6u<@+N)k6t|_3mj&@W7~=zGr(?FO=G;pq7y#nkexdOqHr3r7$Nk(UcvgmNTrNq z-|->zX-prr&{=n6ekgL;F2y&6S@0bbi=Eer)r$6f1oNs=TLL^Lo(_wS{u1T|L+t8C zp`SuD{T>Umt6!|@tO!mtv!Ux4wz*2T)^PP9lDkIP=Vg`^G>v2p#|IAviBf2VJ&E6H zjnGjq>P48Z?RJg0HR7GnPf}J@IhBR;Yg$&KQvKS zG&jLgpwD%_SZ+3rzFixjR^VkaC-C21LTjfm~iUyZC^)TLNW5ivVp*G-{`pBj9dur#IHqxkI1`l zdtF(G9IF_*1sNX9ap$bXn7&Af@D^u!WzywWE1$;)9y6%xbR%DcV?t#qJxkP(9*^|f zZ~Ihlfc`{kd8{eCHNB^EKhgN;#??PXdNsD&F1KtzdZ0^?!ycBFGa-xk<|6zBxiV3M zckZOaTU2=0kehAY zIz*Bjz@ENbi^;-Yc?irnpLK$B)bWo4lRacrSth=ue^Yf`p$EXoI9~2gVWliU+}|40 z{5d5Z(tIn{1nV_>LUwss+xzBOh(5|WLVL}zjZ0!1;;4C*u2X(jPLr@hvE6 z>Z%!i&`=^Vtsk3p1M)5~^gj7QbZ9~N8Qq3G6-I>MGBBN>F^|5gLJx&V!f^2_xb)A* z*~UUmjNqe9BcF4jVY~tHeq~DM(U8JRiGOKu%pahe7=g2mJ|20L#c_doE@e0irTxLi)Sqw#&bqC5-Xi8r_=A4JI;A?V;=(S zcsOmSFP{+37UEx3*H-HE6roh3`D~By{ztibQcdWQO4nh#h32u?cUN8u@P}Nqe1eqRYWIqkpoMCa!FG@Ra&y9H>y4i_xzhE*Deo=WT@{ z78)mF`fMEH(YB!R=FU66p-&vGbHaFa#d)G)1YKAq>KoO_OOWw!v}?-dzEEPz4I};9 z05BJLZ9fi;w$4 zI{X2QdlgH4?QV@6*%c+F$3>>nQhD>sRQ9+{i~gJWOd>mSt)%YUq*Q(K8X+_seUGHh zlwAc3L-;njk@U@C{LFvcKXi*g%l8ZE3(@&;MH2$0gGC#M#y!Snm5{|W&L-OAj9KEVyMGS<5IzY}%U{3r&?76i{~ zfi%sF_!<5182=$5`v(o*6X(1iHm2|LSm6{yxr)`|jK&2^p_isl7h7)C4|prx2Nk%G?@XW3TdWW?{pr-WaJnz&CAQ zuPjR{@El%JmgYpb|5IstcqsJUEc^;+Lp$hlm)DL%5G<0}UBCmiRtEul{O1})A8*xc zi_*j&)=u|jxqk$B+(^f?Z@q~Ik14MNZr9%2opH_?4SNWbJ{f4gA@yJLBIa>*(Pfzf z^>fI(`}U&8nLg|_S--RAc)*L6G-4L3pS9(=fIX`4ZrIff$EMG_GHeSAp?r>Pb+@j+ zDd{j5hHB|Qz*(l!rhk-8yW0O;qPn)`U-CB%ASwk>vPqsky^TXW)rNRic-5v2asBV7 z%->`~m1pK&-N$9_e2;htu9iK(U~#i2exd6)VBYeyX&voyqkUJXn=UD${rTdZ`_pmZ zgZ~|A4nnf>w6k321V#o8?t&W40sge2Y*Iv zdOd`0%!KZyaZL36%{1&T=A48dLFaw|o2P;YosOvLv(E6&H17TN5Rm}$d z$&H?_8D7H(>>}9lLF99Qz+BhR2Q+fK{Zy?I(;jDmNPS zEFU%Kbil>zKKX%PS7*{IMTbkuE~3%r;!^TJUsHU2v8}4br^`X-n}q`ff2)7l{z?(P z{SK@E5@N)?sN}Nk(OW7_g8f&ujea}#59A0c79@x-jbS@(T3@pW8~bSm9Vk00*Laa!3# zXQgo{EpI7)65a7Ucgtf0W+Q5_`L9;>#$eQ1*suNHX=rD6#5nswLM-|0FelJ~8(Jqx z-ahH+>o56UAINy3exZ!xz;;1X2y(~cOK3{=k2MLhp7K#(~v zX2@rLE_AuJSl1fhL<6>O2DQw1K_!?HY&Wu}704e^dA|v%hY#uhHCfvY{XdS*`=83k zf8$Bdl$ad_VV`XzV#<36Q9L_%H z>+}5=?jP>QeP6HZdOib3Rq45H`>G1FN(dwEkkwfl!c39y1u!PitSM10Jbp$OnY12s`*%FO^AyfV@im65f zF*`E=MkuwW5)RPX3)4n)?2pUff6ho@k0{}{towF_#wR~&rmdU=j=ctFn4?2V1+zl3 z>HkrS9=^XLxe;ATD=8FWt)gqMT{(oB88Nu$*Dn z(Os!Dv+Z2x)duzc7{-PEcr`EIxP1R(NTM4GtuCC%6FyCI3XP!1CTII^Bpbkpk2hn) z+5O2yA&g`gj`J<06{C8rK;jp zN)4s5=$gbp+pZt+T-*Vl%mqyzGpSwdf3}&Dart*@^l3b!2<=v{cG4d0FP(kOVfa`_ zKy>+lLe@08lTJHsN8mJ(7y_sOL!f9v(YV?I)unXHv4~HGZEdvw>Pm8`eBaY=Q1NG} zUu$+Kvw|ODIn&{K)W#mU(b>`C@9NkE9$6G*XYZSxBG8a`{~fN!=E=NaphY{77%3d* z+VTn&7IKGffxCm>mzkB?_*V?66X=8gm89PbGHylKt~vz{Yf6Q5$nZ8Mi{1`B;0CQB zW)HoaLJG*Ji+H1;$F1Xry>c>70Zn&t&3AB3m!hpYG`Ew7n3o_?*eJDG#I-30v}GD; z@+#<6v(R9+aY)Rp$XyB;`q>wvuoVyq%Z%9e$@%ReA?JB|k(*A(_#r1b`L!9^0>^L@ z8wd-3q1NZZ)$&E)UgAGByFuZJHGBomqB?t5(i&VD^sZ%JDi{!0?Pm|W%<$%csZSYD zc$o{8dqUczaqa@&7sF1?p2X7xHVpoC2l4heu$%kS6P|fA zr=O7V(8Gi#aQRh%yUbd$^7b6j!>KXqKZ|I`4I%(u5~^^E^yGM|MS1;l0gIc{6=LJ; z@t3|5iQTLpQNg;xyWuq#XdnH&%D~WvnL#2tEw^X9sFC+O5gq~8@YlsFu6u8=&E9HL z`>WYF_`rFzb{Ab78}F*nMRUBiZkKAl)v53+NI)R>Oo_$tkKI3qF3}0YKPYp7>v}b6 zLt(g6@mH1wq4wh5-L~NgFTG8|(gr)Bw&2``P0qUVf4o=Z2CE+SCl-ohZ*DYMyM&=b ze%3vN@@<6H_DcAFHiKf&Lxs@y5oJT2;Z&6xIbbGD$lt2|ott-a(>{~nn zIcngK`$~i|N$H_?w8y>s#ERIJtSy!yil)TMM1y>`&GoQvy~b8+PqCi;UlTRbspZk* zytAyX_Tx3KKe#DVBOaBx38&3M!7wMyPO?(DIZ{K{R@PO`zq2kO;B{))q{59J*_GL0 zN3-#tNZ{N?P8Gla+<3@^3v4vR5FdyV{HDYEzFOZ815@cQhnxbQAMEn#(-izXe(#? zpf3YX3Ob8E==u5#+5lwjC(~sxWl_OqWwtZtPnvr<^-vkh+`Mu+v_F{uv_^KA3Mh#`3v@l5 z;@=+LipC?Z6V7c&dVLGJs7?#DXnH~tx&ji%P+xLUH$;H_n4XD3C%azVo(kZdq>m_E z8n$kCQM~bDfgLlVGRjQ!l^zB87s&$C zvoZ*_kz1VUjSi##`0xrBv`>@KxmGC&Mgq)ibM?{|d*mtf;?~Kh!O$m88N6?KUs#vX zuTvs?a$pyl5Q^yCHl?w)e^w_Lwz1T?O!gV(waAg$z9)&&I{n$}^x;A?YV0IZ_caR{ zQOUBtup=Ne{B5x!!bfBa!8EylNuV@Cio!t=!#0+qXLo)8+!R*il!oX|X;hS`3?mf< zs5%Mjg?V3jj?wc#fumPwvkjccPHh!|Z*b*-nYDg5SIil%) zMB7rK!JbcjxGfSNp5)|PE%;^7RlEHrK)3Vm47&*}52PiByW{&CPZjC2*~$OAxA3XI zogJ`rRK7J{j^QGe2iY$pBJqqN#26m#ZyWJEzc$*{N?= zf?{b)7Oa0N)DS6h|LM`%iQ-m)>H3S;y#5fit!s2``}2a;S>)3%TgRW&?!}w5RLy~; zYg?f%1R3z%<>_4sTp|7_%2QDrVPnH6YRh+cj=kX$QpASVUV&E;b=%9dw_P8Q#mR1> z!e&G66QfO9CD=R#5WR5(^D)s?G60+&y10AV?_Fhewhfu(!0Ga6^TB>*p~ z@&iu_D^;c?iNBgO@L;`rs3rd94>Eb z#Sx$W@K1aA-x#5u4f+{6NF!LJUu3-kQP6f)*qWS_G~RP7?B<+C<1(O=jFFDHzsYSq zchASIyHR)i;(TvKN9x-qS(&6TE0K*+39R}X08aWSIxSdu$3z3`|8g$*0ANab`iqM$ zX9uWHAR3-Vix6HnLO63wL$_S;2Fdr}`R<@|3U*GuQIzASreZu}hzB5B%KPt{yK75? zT>u|L5o@0}r!A+ko$T);hbpVE^4*cb;TZsD%biNCZr zu`PC&R~hQ^fD6d^2)pJ#?;l`dDr8xkqI(#!hUwXAY>nQp{~_a`V)O<{IqN?-!8viW zvOHJv@LfXF12Z+%XH3l%%X29J2`z)B?McjQC>X^qSXncFDIHqAPb|wYR({i5D4(TljtNe=Fzr{;V52R+) zTcKL_p^?IH6QZGL***Id`hs=@VDM^7*&oJcyKyfHXx4heGcgoo+C;CVLKpjw$oIfC zN_o&?oFa_P;hp(1;-cGLb9$KZ9Bb83DCBT7diUR-Cn!>1HnK~|_{#i$WY0skBtBws zTHg#_3Rgvp63(N`GFqhMEWwpjSEUn~sL0#p-#dJ(K@ z1!23d99?ztJOb!Rf5w&)()dNFMNEfWPMFZ}(!TgiD1w}vf%`okMvAi#EyG5CK4ug+=>KZD<%iCcPdppM@Nqy|4=IfAdRF3UA4`zZPhF zoR1f=6Iy-*QZ=TNyR6e;47HLR;Fd6j`` zJi0QvasCQX#Oj*gK_2W4EfqIr-|cs}T5(|ykxyjKe15r14!CY3hOm=3+4ysl_TEnJ zjqux~_u3b4B};$#AblLVE{Sf6o9Tg4wTY%jGgdy8`69wYWV2;%r&mn4@1uH7Q{o8S zHO1sBg|0@MK4jfh>kd5b>4xUUEACKNSKk=_*05A;3a{bVoak1EBC+S9sswos`BxO! zH~J4ZTP3{|)7C9O658>lse5_fG2P}m;;*Tb-X=gy@qfys7sY2-3V1YlJ%(}Wk}a+{ zp`Cn3A4SDjIbUFa*AAh z42m!FWX)m1-sR%UL1w{c)%eJ0P)tluZ@Da4z_aKO+x<{Q_gA3~h#A0S12{$)aEPaKCDo~-c-jobuINQiF)Wk(Hh z&`*Iz*s1kz>-)Fnfpg8OR_A@(4EGqLuX6dWwqn5;UXv@GO`ng(E9`t~yyIkJn6Xqy3`0HG5z6YdJ`Qoo#*{jJ2EH0kYPQ zr5{0_?sr%D!ebsfQTqA8;@e1rx`ehaL%eX-!^Wr=N!+&6eFKS3p|&Cj+dKP(#a+CjO8+;nH{1q*Ga z6zLu)q`R9Da%DnWN#BK7yw!*7j|c*XnbSj`$G1C z_`pAB{0(`*PG2|d)<@ZTeq3-}WCdJKBl$Q2QE?AAPaFE)cTZdMl54{0BtGkzHbg7< zqTLI+>j0aPFG)DaGlEkBp154{rIm1+0UIoaV6_GRuI1&L_z?*irdZ~tJK)niUG+y_ z0yie;9H4&TQTsJ>>$z0JFg9u z>{nu{g>}4hW%Oj1lEA$ncX4!l*6=JZpYOKW)|EM7)u5}ET*z*t?=_FIzW5z0vET7>fS7xxu6z$>o9L2VkEMg_u)oa74>SZ z*Fb1K;th1GWO=N=Y0y813f?q6l&Bu7r4o!xGmhMiAb)T8KUr5cWvg=+3ag5DEjp!+ z{77EtNOhDC6HIRU)~Yk#ux9|bKfj;Nn4UUQRfXFWR2HFfqT_fsk{7#!CZ4poeQ6Z? zj_SW2bl|O0XFYsz5ci6~20A^|@2riJW4qm2q>^#qgR)R@m{6~2>FRal@wV$K0ul!S zMZ{BN=zHH)2`Y^#;URiS!a}93kW2W)VWN0Pgv6MX4@Ath5DGv1(F%E(Y4+Csp!O+3 zmAAM3C$X~FqWUvC1q4LLUiHI zZp0A$n_a$2@y`Qn8Me>2|E7_D->(kZ(<%6gJuYw691q+H6I5}bv9h(Pe1bYshqT3W zf_^3k6LNC-vC6t!Lv7s-njBe0736E)YnD$+vS8nK{JyQS9t0ybZ$&HMFYO&~Uo z|5_1l0r(F-ta68*gf{@UGkR2~{RrSI5vKGs9^3$y3% z@a1W(LY{eVW~bhX>PyclFy#3qDWu)&dc60(Ojzr+nI?bV>^o* z%RZ`~}sa47Mof7Sln zZOtWeOpG?)Mx;~h>@(4o5eD2257zH*gLZ@Kg#;$IA zNm7HOG<%PSB43tFrtT9aye>e7x-3N)51Fv6ej@Z?z1}Tat+cfbESbi!Ys*BgSujoI z?9wKP518w)rd$yqMI>=n-vp|DAPT1_RdP4DV%pY~7o_P4rJUWY&I~y_wD6Ug%q5@S zx7HLi-^6w&+i1RK;apMZJQ#3k6X7?QdMM@mS!PE68uqt6N|eKB_G;6+q2>W&J4J9! zOhkY}!Eb3mSEANy8#b3XUaq21Pyo zr$+dHjz(JuLW@AX4DSu&M!$R7SL^&096}y%dBJA?X1S$(h$g(G=M`(^$LM-B;I!YP zg2)EBLD&D8?BTSFmWn?CbdlFLTjfB3hl&eh05OTYuK{u~2#u zWsFxil4(%n+KVXd^l0HyfZ)_$ho4KSP1nKSY3_JcG|)N!Dd|V1pgZ63*^NRh^6^rC zVxRLe;6YoLm@uZnFaGGN+S56wrW@rAunpakh~IU?i{4bi!1;wcnEbEEb@fs+jMoO) zjsHWfpulzt8gouA9_caKKc4mSvRo@gZ-X!BUqj z`bBO!@iGb??rJ&HFS@ z#7#O@i<-VqeRWb#Fjj-Vdc*+h?|F&5*`X-Ezso<>o7^xWTNlLTZ$xu^|Ag+5ZG8|T z&rWIzjPXGpd}Tc1STqL3?IllvI@CzAd4DrPBx4hN?&7bkN1vg0fAYclxR8U>Mma5L zT7MJZ%JS-QVNO;ti$T#Ju9^!1^4!F!4+Sr=bfn@O9#D1in74n+Dw?^!{?QN*?SK6I zAFIff?Ng`s@X~y1B0?He?zaZ%rQBy+X5@=v*GRnU;DibLC-ccse^IbNLwa&G&yOI^ z=iqBE$rqN>;|Y26OKVcQljp}P&W#){sW})b2Y-GPT6>n5^;OG|(qGcQ8j?F`-B6ks zI-H71w{htF%)dYi9~UMP?B$)d|+~ zF)Wt@&FB8Uq&h;Sf+5 zQpS1Ol-Uq$jSuDK5&Ua>FTi5%ZI%=v6Y71MBL)R|qE(TnYM`E9cV#0Km&8XG94vb$ z5gm9by==S=U*=n_vl!+Xq1xe%xrMace7%#M-zb8U*~JzmpH}xI$4hvurj8gRsn9zA zELx&2is_Y}5N;r-3~$*fQU{zkBR1N0!{oMbxDCM>%tJYxYIS5%!PcrhqIDU3_!w-O z>iTU@m@F6dZX*s2V9HcNu_k;hV=@NfXhWv1c%xn_} z#dZ8w)MeLh240hdBgZX?xP;jNf_C`mhtpSW@~JW6w`@OSzFZ}RBfp^!^f{jQsTDIM zObS=M(E}StM2|CH+qev$Zw_a)chfc2)F-*9Rf|VZN7oM@(s0Pjq;TKf_P=}`oJzGk z6j&}dL#-LO*Y~zFK@qOETZs4<6~XdrSM|$R*Wu7-^A|i_!Pi2T4g!B5B~HPPBei2M zIm@RBP@!NXWh31rj#V@Y2iY495f2^U+-(qD$fUYPpYpVkNabsaqDj-tJs zxU;+z-lyKapXsd8e{rYfRjkOnm!u2mwV~tzW01AzhoUUMzSnWtnlG4vy;AQvbPwX+7~Wys$S^r2$T)AIcs*%!?xCXBsY^6NO-MMWH7% z2W*opMBp>5tfX33{RmBN2y)dnmCz)K!PT^K#?|gK-eb~_#oojP6>q9}wvAX1`X-cI zZx1m<(PbPM-2RjloMuK#)|^~W?)ZYc{izzRJ-||jwW8y3{URb;puu7e;6F2T9I*0~ z7EEGvdc{F9=OhSFQX-}|&Ng#neX;fZ5$A}trA#YEOI(ffg|7WfaFcz$Uo&^0({BX( zAdb_R5i$r=Pv!>v~f!M{UrxW^ax?C~xpXw{Zr=Y0S>2iEhzk z7T;Dt<0l?t%ImJ5=M$nn#i@gxHQ}BT-5+kch;P@L!wWNmTjqg^zi#P+V@pPrOY+|% z%-5QkG>$3xEB*?zXcoW=T||n_`8L_4Hdn(fiFU@kjD8E;@+k7>50z)kEO&rKrB*}* zZ2u*}h`{^dJGPeI8N1K5k(-xtc-;FkB zhI6&UF9>A#jdlgP8B3*Ra|b88pSEDs@6PzkbFpgn%E50wB4zXt>ezJ&?fq(-Ew78L zm-Wm5Z2NaV#8II1(nSXA2wd(!Ke-9{^&5PN7QSnA;O(?r+06jJV_Nxh?5BAq6Og(E zX+#Z<9Pvz{$=kSpChjVSDSMg>qqs~$P*mV%G_(oQ5@C~2`LX&d z`U`8XmuqESFqpI4I{YE54k)p2ZQKSMOyJRc+|6>!A%kN16{YZt$h-b}4%KCaG|LN=k}yx`NG<@TpwF z9hw-oq*VMI>vju7NsCf%x*}Hu^m|pFVe_}p(OGV;{x*H9eoe?QkbNppPAdbf&0=xf z!tuG0?d3{9Ul+HPhuI%u z6ISLV-@hCcxlbxYLP<489bv5BTCeTFn01d&xjzi^Z8PKfl~pu;NahNwoJAdD39WmlZ zI)mhlK)OmZgj&pmx2x8X#*Edvwp!bknRQVn{rN_xZ>bFts_7HFCg?6;ql-jq1>b!C_XjDW2&_A8l@=IkL`12dsOZ5{(Uw?hWa4mq45hN3zYf;{zeC|% z`fh)_y^s5JB=2I=SBi4!Q|=$~Gj)^$Z*g6T3Aje_Hp@T{|IAxyudvZHh{*;a;uy&j z{pFN(-U+YlIgi6y&9U$Lqsn==Ax%O@z;aSQs&qM4F58b{v^5~qwCtLBtS|@G1-ONw zC?moQ7W9jmq48mrXJ+1K5i!C_gh0+>G1G1)cfHrAvD9PHCFVftX$W{)2M^NF|<< zRymILmUH%YEEfA8Wi`VgciAZ{7R+easQSEco%edkeG4H0apCcD7Qwj`8QjJ4g$Ms2 zqAHjJ0fn*Vp(f9955~vP->ZI6nAVe|PN4XS9!Y~FX9T;-Kb!drsh=cZv*`8=@=@Ep1Dmt0~DFfM!~4;dg1-r22P6 zss&IeXhC-fH>wEp6zK4hUz0t#a3Z$%?XyPkXB7Kfv5Bht6cS-)c8HbhY$dVs3|0 zyT?jjTkS1*65FlsP?N8O<{n{{Sz;xXvGPJ`%bUr9_O^Kc(2i%etvmqoI0kk+ zaQqt*^ywRoXD{t6^H}QZF*`l_=!4i+N4vFW+Dt5Boz)WZs?3raqAtLe1BFuz`)JEZ z{fD$nAyIF=Ih5??{+`R8cXB%1bW)uCIVh>BJ`L!`14bMkgzi@aC zGA#-Ar|o^B@+sh79KcO>yjK)*oU5%!ki!#pO{@WFg*ELm@qkUZ1B=}<1x!I%I+s;L+9wPnrP5ts=0 zQQt<&kt4{dn$ZR#6W59poh}J{W~;*XmTL7=a&H1ZfsQ17-x5XehjSt0L57Pp#RYC@ z%YPPnj>YzyzA>bJGpSErkfbcadd%;B5ACAaPH65~gF>ZNcI^*sMaxlGn`C2(I8d># z^xpEQdfG|WY))an9hxMI`|v6ptxWxY06T7*xiKMh#Le)UX75JwfB6Neg*r4AO=2EMWM4Nv_q!~H4 z4R5d5D9u(xNVb3aEzI|}FRAgdllF}3ntq%2pQjL~eb&6(cD{bI7C}m8RloWrX(1{n zb65j?rXxQn4uGptL_G-3{vY$6`E+X9kSY?G!^=LxuM2>C!uVQl>k{=y`T#hK3~@F zqABjI*{dzi;HX3A!*#*`eZw)#==|X57)E|T^)?|-*!exj%1PksnJ~-s=Oj)o)6t6h zyGo8$|ACI4GVi`Ix03^RI59pgd0~vVQqMx13jIFOD(7PI(sECJj~|jJw*X7G_7;YG zUqDP)2jCSb^E)T5y?EWAD7%f7^PJbq&(Q1-(<=L2D+1nmDTugG!VzxJ5@`E)m{v zUJWVP|GQ|NCD5Pp4(YVCqX&0uiv%{b{QgMDNdix=c2|#VZ1>wwsC`CeZ?K^8`J7`V zm)2_lR1u%heA7KKzx|%hQD3@JAd(yXR}NkI9Wy33%u962IA5^2*yzKHmJuhxr%3Ia zCGEv>Lg7i%ktG2R)@_IU9i4rx;zPWm;;St`;hzQOVuX|%uC$B%(HKlxgmuqE6%Kh6 zyj7uPHu9VAuvWC{Q@Yp2A}+}LT9Q@RBsFj_V%cAdg4h{~q5VW~>XxejeT@5qmrb9| zo=maQ7T1W_Jwi_Z96>{y7E97c{b|aeTaVd23EKrz@pi}k<7Ryf^F6oSR5nqtZ;@@; zX2dO(ndHnU-ak>JM!%k;SS8e+!y+-+ntwN0+!}-_+lw2gt0T1il@P8?Lt{=*Rdlt_ zsE7NidOx=tw?zc_HaBt(>C@`}8NZ>&MZgo%xV5!JT?_ucv7D z?L)v-zU)A;j+HytbJBKCNdeg?XkIKroQ%n5%i!FC)qA=3y4S)mq%WJ zv%o#EabC=z&gRlh)_G2KV}sEg=Y;qGWlyx3`9-P4 zugH~SUJLqKS`_6&bQId@J%CZvR5|_5Ap#EPWyVpQ^oSmE;;ZfZypMEU@Pc+^NK3gk*nDjZZtMzJb z>p~<*#c=q8rqZSEV+r(G-Gq$fzK+--<3D$3Hd%z)+Zz=+$ZX%5ik+}aVF4z~4bBf* z(>X?SJ2k6B4dL!VT@9Juz2LSOMx8h4RJeqG{_G$mIRFLPXE`}cGjs8~aq?9X;P|3o z_l5GzF?z+|#?Od?6GJ#hxT{C!aKH+sbXH;`FM8ScEc{#IHL86OaRBnvAtc@p_a({? z7mU9S!savD_PhgG)=BC^v%I~{VxbK8W{q|g^xEWOcm0N4=-*1n$GvC(4LSsVLO^q+?f&^%f1_Mx(ri(#05r9Y4 zK!|8Qh&pL8E4p-z)@z80-aGj?4orLvY=MQV3hus~1M=J#L52ZNy;Dp)!tXU`^@)rW z+Tb4ZDX>O!xsEyHt1(K><7ZL(WJ2p6{VeHGF1{AV74rGx^2yEPD`>$0{`4V(ouVlA zXE3fOpUd8PsmFtV-S46<>$l~WJxDJIwL{Uvo)r|UJh8KuPM`7%Wo5Vr3DC+14FpV0 zRQT6UPD-rjytRtKZ_aD^ZwnV8>9!tni;cHLb;_E@8QWGW%BDX}-g(9!a!>Z3ysY_;&-tT^=oSQ+ z(-{rJ>>UIV_74_>ku-V+u3qety_Xm`fbn+HZkryMoyu@LH!DHuD8G}R*LId>t~dXa z<@?E*wPdE50UkTwuX`+qj^?;=C!zx&E(Qn z*75_M13N^B*qUHADL;kufqly!7^M^mV7rG7cSUBAd`Lw= zrf&}Y4t6>Os2+ZyqlnUQf6*C-!hkN z&l}cVnb4ynhwoGv(#630LA(@pYWx%-6@I_&y%!Ia9j{ZmV}0F5&jg4ZoFLY6a5{X&qD6DQA03duuek;TU6eg;(THPrEAfp*~K zC9>^-|5$Qg0_JjP(U`~9t@EA znA#03gxmy293R3a$C4JN&J-y4at22TLIx2-Vr zZ>ylTuTC$|lT=~tIH(y$`ov~_6K#`R9pJdTpJ;)oJu3*Dh@eHO3%`Rryt2|O?xH#Q zDamhcy8kH|Fmsyp`yCPhBPct~K&ED2z|lwsL&J&ZR3)ykcPE=MUjx3vAO8ZL(*YLT z0%IDFUAsgh#gATQYU{pMBel=VaI{E=wDM$#OGa4n$lvjgs)E%(Ll?AvCHdp;oJi^( zr)i%}R5_zHWcIsma^?>09T&BvXJdTfu@njToZ9bEQ;c+n`yYpwv8x}2iF{ik7G)1w z(|exh0SHuo6T=qopQM~e_6kxs{0U|{i9%r>R^;4iYh-RIx*Z2B-75V!N|l6U1PUaX zfcqJTUPl_El&)X3nwI+NuW6mUqfX^anuxoB3Vm_9d$nrBxldfOv%iS{;#bSRyO`PzL8G9iHRQq*;HXRdl?^si+0n5?bOJW%&Q5 zLxCryX^@3u#j}+qK6vV-{JJX6w<&*o!v}2(DRw)bQ=r+wQAg+wE}`Mgn(hq;{gIWA`Bhz=3@DlRXvR3NeU)4pxg`+2~MD9w;vHE-p^>P zY(UiGLm5PkMGqY3LyYwi*msw3W2T%}rdv1z5?7~X8c<*z@O{Apm`V4Z?F!}V$R!#3 zQI@dN;le)`qguBWgU42V@#xUx&7!g~##wOjeBmps_hrJ5@`A?qedg52HwayojOK%g zYUa>>zpEeKZ|gQeR%?;Zk(C!hUm+`V{IMSsXL!mwz}8XS@RjD5`}|IEp@gts zKA%DtWS`F+CD0t6ImLkdqDDzRRji`P@hajoZRq%+(tMA+wZ1#p{zq5vPOo`3$Re{X zq8~Yqrc{=$HM|Jmc*^Ve9uFwfSM|*c0KD-jDF(ZBaGJMmp@ZZHn zasRw{pr?Nd^b0ta9&{0`B0qPSsdgAEUEp z?tTKQVHHC0pJry^*n@?}GholxOHMpCg(Q9{6H8Z?Y;rA9;{hFJBM1A z0u|{QBL?GXJ1}GoVjPA?$!z9aq?-+ zi*ym`i6~pnwvTv=4A?I!uw+ieu=c%;7*uy}U~-$ZYcNX-94BmAtW=H9xQQ}GUhipe zdw#oOJn%|u>6>v#4`7b_oX*C!R`QC`8!bZ-N=A1qIpl0JEl_ebjV|4N>29Iq7Y`zi#^Zigzix z^ze*Nd6)32ii})C0i8GdR?tgSt5NJySYwWlGY`B+!|x@2Cb*z%`MR&=MgyX);Migc zQz2ULb>`A=TbKGXYQi@?@K0v9z~~t**1CjsR-;2>zGfznyyR=30z^#3Rq!i? zx2bjbH9hFXSWvd|pj5Y0qtA7>Os1$G8WYT(*+k`CYH~DEXg$s%oM*MG;!2-;!YV$d@ur zg%MK9ixd!CjP{Be@7Ffex|GPtJ1XHKNVo|+krg)9wK%a;Y5r2Wn?C~C& z|16YD&T)AB+qVK$oY9%o8GtU16t=rUkqA zc(Y^USD8mLUM7fF(#%c9iWci~(M0hp)aM-A#QcTnwwUgJ>%3MDT-RPcC|H%~06cv! zK+Br=b(m|KufqstqO9#%QUSewW4ycbQnYgBXc=l|<96do_XL!sa38)qd%vGvd(35; z2HRzP7)GOk9t)d|2Bx{+>d}AH4p_O!7!Mf{(&1K{MDty>%oGgnWJIhSuAD1?=5&JjF$;;YZoCcUbWwjVMG5jNnTz$bibjUOOaY< zGkc2sZ%w#2OGCxT*3+*g$~*0C8u%V_)iu5tdBEvx*;DP!5$!hszTF`uDFV1fZjFmwu{klwpDlT}k^ujCez*42A3O?G~ zmumjr(4=f0c8@*GnWgk6EwTe`#06FE09f5N&n^)L`2eIrM~8dTM3=}@`{(Me<$8#P zU+XI?xg*BUUQCD3k23t#;+~lCo!d!%>h@;yo8m*k3Bs9l0oI>>y<4G7!Nv3FU$y_{ zZzlzKY8%f(gkC6Oz1_bwxL$4Pk1P`m9QVM#dZy@&GU&Y8lI55EnDu)^LCM$}Yc@kv z3q!wzQgx%d3WRDnnQm4bk9b0%{Y4e)(A?~!b~)VlEm{&IAW`a747}arYVe@Oc@ zBw#KxiuI&!w*KVCinwq158IWTvxT|IEA6bc!mMTl9LI%ClxvT*`6rqUMs$nN1c-nD zn$Kww6@z<3OL{CXX(iFV7nfwxvm5l*&$CgXdn0DE3>oAaO`a}KIc9|<769j1-OERF zi4s4M7ZU64;|kIn|9-8MQW50ZVFi52&FO=5Z+!=-j3--?J(%3(3djoqXpc2P;^f6A zZ6ge|#AQd~P#{syBpG`U8Wzbo@fX6j(gW9Dv(1*c@;>@N7}-Y&{aJx!3Xw11%o7-< zj7vw08OZ(0rd{{)WvD3E-3Ph$vW1Wnil5Rp@tQ-R+87vOB^cBS@PwD}JcB)(Utn*Y zYnd!BX?;p8{}cA6E!1r5>i*yo2lx*t&zH6y$l6w<+#^WoS^@xBiF$sFB)fQ`iK%v3 zU&B%pViD^@LdFXhoBRg`UD+pVxRBS4d?p_FuuL^>O@RD=s63cSubo_h)L9 zod|LVbhf2P&)wCq9fsHW1f8lk0^eI>q8o_GgEYnjRjReDhg6t8JFfi2>n&o^KQv7t zN#QtKE8Gj^1J!JVwiu1bP221+?>zlmdV3rBC&uGi>ojW~;mh8nbMAW38Bh8@kxY(| zTPk7W%W}uhux&Hrel;7=iKHqOC5e5Q|F7y@4?%RBwk{~^#8JJ9_-TG&g5ij_{-=&$ zM2xY?YU?^&2<1su{qtm=`k0*CNj4`d4vt_0Fa)YCmX+$d0;3puSpQ-rJ>g8GhB*zm zo=RIK+bnBCX(u#uY#94q%-Ch0Yo~yxN3gAw9;lHI#MS#I$J=R_Jqf%#l`(LKo*(3H zb}RWhHQ>g<@X{#AEhi6>D?Qp>#?l1Q{#adW6{{kA@Eu^2KbG+F3dViyzoVaf4E)&- zVKQJM)BjO)Cf-oKeH^Y-er2l^*(*sAD#<#g5<-zJSw{(>$T|iy6Dr9v*^(?nND`Ah z+e{)mBimSK>|+@QGiG02?>WzT{($E^=RWs+e?QmfQoM#XAr;nq=Lc;~r52`_bi7*r zOORq#>6c&0i*BwU_1#LwJHmXGx!7COa*&=KM+-Y;xy`j)9CMUyr3LCx~i!fyDBq2 z+P+rIJMJDS@IarJ?*WgRh-|4p#krH+7k4Pp@S_0eOKi>ih21P*jtaxy$Oa|caEmIp z*gSTHS$cexsN_@P35B}yPcE4?09jv^0F?X%-n9#N3<3WEyXgCuqW>yXS!E)lQT2Cu z6H2Ru?|s;7u-~H*l<>-Iq4!7*cK&2Hl+-Br<LL4(3o59;kDpvdT5c3jvGHgFU^;>y?&Ba-7m#hv}Jl_e#2Qoh-Vj(T9<}q+PL)x%rH9V z!ZX_q1Eu-Td;G7|+(e@i8JaSZKRt$kUuJF!W0aLB;3`zao|K(&J#aI2YQjNr2;U&~ zjO>0G_P7>O>HM<0er(*-I|i69kmgoOP7Ppk76spDnHq~l^mb{Rz}s2P(U_U=*BshT zoGdY^F|(Tf0cACp*=&Um{3pG$z%B;Hy}}>%*4Hk?q{F{IN~?k2?jWX$e`jlqnKbwu zz|t-kQ*7mm;`El9P7wN%^$loK*A4XVLTKNr;eMn;%1_;dQZQwq<(yZSfVl-yThF!n5PZ$BxKo`%TBfV;vd|28Jq#A*w|KCurv9x}hzMWJ znmZT5#6&2BZC20S>g3yzpZv9|dEbibd1a0Q$e-OP{Seg(9*%yfwX_ZR{Yd1BohtJ^ z*4|2w)rymgdY~m1?bWk;WIlw5;3~83W)o)dJ}ERSbGVadP7i|Zflw?7w`T$NzQ+A^ znXa?F@9JG^kl>KIN`c4@@9hL}y_o4rJ5zp7*BN;ioiu3hmQJ8$W4o2*KP|Mllu`AK z57BZlVBw~#*qng|i~?V|V55GpVu&viC(Ci2LXKbC@X9<@j2YHXmbVHr=Gk^wE*D5d zRzADnLkY`IsUF_OylB$;*Lhvr0t)zLl^nhH@nd?|f?{;y$Hvd3G0+Mmta8Rzfy{I2Mom(B_Xct|TQ4>~Kl zb#*I!3X*CbO4F?@{`l2yH7k$W^PJXKC8PD9eGeiwN!4F5xXs1qFt$%byi^=DGNh^! zIwaHlrC92@&xN$dlLJv8GI1S>c|`<~p?O3Khhxa*Fbt3igOL=%8$OIK%ioLoF56!@ z;%cqEZpOGwzN{wFwP1&MJ6Blq8y<`ru5;V+tPR+2=+1nk57rdrFwMzUM@H3NLFp#BKc$RcvBxQ4~?5;c< zIR^iUxwYYYu(Ms#N?UxO<`uL&pGa>7(Wj9*sECN)-kzQMAI{}Cn_$mJnr&pjV?&Oi zyqJ07#G~dyWOOp+RO;6mN~!NQgY3 zR67Eq=<*a)e;`g-Jq|eYXv>upEAoWyNADnPS$-#HPLy!$^XJkUiQeZ;B6JY)y7*}saeA}sf<~+XBa7Qd2L@(Gdp>29H~-o!9*Sa&uhO`Pm%w|eP=ts zySBX$JB9PxT*{NYE4I5V%fTMcAh#5RF!}f|V6J(&N8T@7vFHS`$>wxPuB!ANdZdH+ zaU#z}008!tqqI*e-iLxRK*xduc18#uxoQi!7xm*^+`JTsDpto5WlbyEVf8=G8Oj~1 z)^b-lyjfFmQY&>6bQAuik*83HOY@IW9~Ndg5y<19>4>2`%TaId{$V(8CHcyF{W2{nuJ^%@CLz~<4rF9CU}CIZ=0*uRRIKu?fAbsVA{V2x z$zYOVJn`oO()9sQqIEj8V@`Q3&RO2WXdBo{ctHX zotKqzcA^_jT&WfdVQbRu5_kr*BQNxib{IxS&HxTTzevbd=r5D%X;xO^+Xc%1RPSe; zGnI^rVQhJl=;!Sb^||5fywTDy<87mi4I2O;ADYMOOT&DOn%}gpHQjml7C&Aoyf~uq zrW!J;EzrnyG)DQk^hYiyc}&5uYGmK~{Icsb4|}&K#!KZf6H}daxx~%gtIk_zHmK1z z2(^pS748%ewLM9XoJ!6NcoRZC#v0DUi)@~4>2jFhAVOC-p5u@j zZrJk`wttLdUnH|aZ#g~zE2(}K_G{rNaYrC@fJZ)qS|}|I=7?!t{R53#%i&Yn#vdni z#9L{Aer`Q!S!wsaN>;9OdoHw^=9%NCS^iou&(5&LyOG$yH&_)+nr@N8xs8HY5QebX zpRAKB7-28eUmaq@fCgT6HSZKDDY0v_G@#LvuRJgpKL=J+-u=?!!27UCxB+x`+iek+ zm^nb$%BlVm{q+%&!|ljXti*>FMmO^87#ZnDmFcZox{`@ z#L_u*gI8SEP}@ny9ip62ZzCa@TW?H?mtqGXI!nEO?&Ieh?Y+7LsEt{@ab-%B)o3{Dg6-q|YSZ1TYh+c8ksmRfhsUk)!$JzoXKkQI+`Laf_gem4 zQ5F@+jleNJeltczcV+1wW<_PH`vSK