Merge 700d8358a4 into 76a19d218d
				
					
				
			This commit is contained in:
		
						commit
						c32d685738
					
				
							
								
								
									
										11
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -105,6 +105,7 @@ declare module '@vue/runtime-core' { | |||||||
|     Ipv4AddressConverter: typeof import('./src/tools/ipv4-address-converter/ipv4-address-converter.vue')['default'] |     Ipv4AddressConverter: typeof import('./src/tools/ipv4-address-converter/ipv4-address-converter.vue')['default'] | ||||||
|     Ipv4RangeExpander: typeof import('./src/tools/ipv4-range-expander/ipv4-range-expander.vue')['default'] |     Ipv4RangeExpander: typeof import('./src/tools/ipv4-range-expander/ipv4-range-expander.vue')['default'] | ||||||
|     Ipv4SubnetCalculator: typeof import('./src/tools/ipv4-subnet-calculator/ipv4-subnet-calculator.vue')['default'] |     Ipv4SubnetCalculator: typeof import('./src/tools/ipv4-subnet-calculator/ipv4-subnet-calculator.vue')['default'] | ||||||
|  |     Ipv6SubnetCalculator: typeof import('./src/tools/ipv6-subnet-calculator/ipv6-subnet-calculator.vue')['default'] | ||||||
|     Ipv6UlaGenerator: typeof import('./src/tools/ipv6-ula-generator/ipv6-ula-generator.vue')['default'] |     Ipv6UlaGenerator: typeof import('./src/tools/ipv6-ula-generator/ipv6-ula-generator.vue')['default'] | ||||||
|     JsonDiff: typeof import('./src/tools/json-diff/json-diff.vue')['default'] |     JsonDiff: typeof import('./src/tools/json-diff/json-diff.vue')['default'] | ||||||
|     JsonMinify: typeof import('./src/tools/json-minify/json-minify.vue')['default'] |     JsonMinify: typeof import('./src/tools/json-minify/json-minify.vue')['default'] | ||||||
| @ -127,24 +128,16 @@ declare module '@vue/runtime-core' { | |||||||
|     MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] |     MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default'] | ||||||
|     MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] |     MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default'] | ||||||
|     NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] |     NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default'] | ||||||
|     NCode: typeof import('naive-ui')['NCode'] |  | ||||||
|     NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] |     NCollapseTransition: typeof import('naive-ui')['NCollapseTransition'] | ||||||
|     NConfigProvider: typeof import('naive-ui')['NConfigProvider'] |     NConfigProvider: typeof import('naive-ui')['NConfigProvider'] | ||||||
|     NDivider: typeof import('naive-ui')['NDivider'] |  | ||||||
|     NEllipsis: typeof import('naive-ui')['NEllipsis'] |     NEllipsis: typeof import('naive-ui')['NEllipsis'] | ||||||
|     NFormItem: typeof import('naive-ui')['NFormItem'] |  | ||||||
|     NGi: typeof import('naive-ui')['NGi'] |  | ||||||
|     NGrid: typeof import('naive-ui')['NGrid'] |  | ||||||
|     NH1: typeof import('naive-ui')['NH1'] |     NH1: typeof import('naive-ui')['NH1'] | ||||||
|     NH3: typeof import('naive-ui')['NH3'] |     NH3: typeof import('naive-ui')['NH3'] | ||||||
|     NIcon: typeof import('naive-ui')['NIcon'] |     NIcon: typeof import('naive-ui')['NIcon'] | ||||||
|     NInputNumber: typeof import('naive-ui')['NInputNumber'] |  | ||||||
|     NLabel: typeof import('naive-ui')['NLabel'] |  | ||||||
|     NLayout: typeof import('naive-ui')['NLayout'] |     NLayout: typeof import('naive-ui')['NLayout'] | ||||||
|     NLayoutSider: typeof import('naive-ui')['NLayoutSider'] |     NLayoutSider: typeof import('naive-ui')['NLayoutSider'] | ||||||
|     NMenu: typeof import('naive-ui')['NMenu'] |     NMenu: typeof import('naive-ui')['NMenu'] | ||||||
|     NScrollbar: typeof import('naive-ui')['NScrollbar'] |     NTable: typeof import('naive-ui')['NTable'] | ||||||
|     NSpin: typeof import('naive-ui')['NSpin'] |  | ||||||
|     NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] |     NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default'] | ||||||
|     OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] |     OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default'] | ||||||
|     PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] |     PasswordStrengthAnalyser: typeof import('./src/tools/password-strength-analyser/password-strength-analyser.vue')['default'] | ||||||
|  | |||||||
| @ -49,6 +49,7 @@ | |||||||
|     "@vueuse/router": "^10.0.0", |     "@vueuse/router": "^10.0.0", | ||||||
|     "bcryptjs": "^2.4.3", |     "bcryptjs": "^2.4.3", | ||||||
|     "change-case": "^4.1.2", |     "change-case": "^4.1.2", | ||||||
|  |     "cidr-tools": "^7.0.4", | ||||||
|     "colord": "^2.9.3", |     "colord": "^2.9.3", | ||||||
|     "composerize-ts": "^0.6.2", |     "composerize-ts": "^0.6.2", | ||||||
|     "country-code-lookup": "^0.1.0", |     "country-code-lookup": "^0.1.0", | ||||||
| @ -64,6 +65,12 @@ | |||||||
|     "highlight.js": "^11.7.0", |     "highlight.js": "^11.7.0", | ||||||
|     "iarna-toml-esm": "^3.0.5", |     "iarna-toml-esm": "^3.0.5", | ||||||
|     "ibantools": "^4.3.3", |     "ibantools": "^4.3.3", | ||||||
|  |     "ip-address": "^9.0.5", | ||||||
|  |     "ip-bigint": "^8.0.2", | ||||||
|  |     "ip-cidr": "^4.0.0", | ||||||
|  |     "ip-matching": "^2.1.2", | ||||||
|  |     "is-cidr": "^5.0.3", | ||||||
|  |     "is-ip": "^5.0.1", | ||||||
|     "js-base64": "^3.7.6", |     "js-base64": "^3.7.6", | ||||||
|     "json5": "^2.2.3", |     "json5": "^2.2.3", | ||||||
|     "jwt-decode": "^3.1.2", |     "jwt-decode": "^3.1.2", | ||||||
|  | |||||||
							
								
								
									
										121
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										121
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							| @ -47,6 +47,9 @@ dependencies: | |||||||
|   change-case: |   change-case: | ||||||
|     specifier: ^4.1.2 |     specifier: ^4.1.2 | ||||||
|     version: 4.1.2 |     version: 4.1.2 | ||||||
|  |   cidr-tools: | ||||||
|  |     specifier: ^7.0.4 | ||||||
|  |     version: 7.0.7 | ||||||
|   colord: |   colord: | ||||||
|     specifier: ^2.9.3 |     specifier: ^2.9.3 | ||||||
|     version: 2.9.3 |     version: 2.9.3 | ||||||
| @ -92,6 +95,24 @@ dependencies: | |||||||
|   ibantools: |   ibantools: | ||||||
|     specifier: ^4.3.3 |     specifier: ^4.3.3 | ||||||
|     version: 4.3.3 |     version: 4.3.3 | ||||||
|  |   ip-address: | ||||||
|  |     specifier: ^9.0.5 | ||||||
|  |     version: 9.0.5 | ||||||
|  |   ip-bigint: | ||||||
|  |     specifier: ^8.0.2 | ||||||
|  |     version: 8.0.2 | ||||||
|  |   ip-cidr: | ||||||
|  |     specifier: ^4.0.0 | ||||||
|  |     version: 4.0.0 | ||||||
|  |   ip-matching: | ||||||
|  |     specifier: ^2.1.2 | ||||||
|  |     version: 2.1.2 | ||||||
|  |   is-cidr: | ||||||
|  |     specifier: ^5.0.3 | ||||||
|  |     version: 5.0.3 | ||||||
|  |   is-ip: | ||||||
|  |     specifier: ^5.0.1 | ||||||
|  |     version: 5.0.1 | ||||||
|   js-base64: |   js-base64: | ||||||
|     specifier: ^3.7.6 |     specifier: ^3.7.6 | ||||||
|     version: 3.7.7 |     version: 3.7.7 | ||||||
| @ -4466,6 +4487,20 @@ packages: | |||||||
|     engines: {node: '>=8'} |     engines: {node: '>=8'} | ||||||
|     dev: true |     dev: true | ||||||
| 
 | 
 | ||||||
|  |   /cidr-regex@4.0.3: | ||||||
|  |     resolution: {integrity: sha512-HOwDIy/rhKeMf6uOzxtv7FAbrz8zPjmVKfSpM+U7/bNBXC5rtOyr758jxcptiSx6ZZn5LOhPJT5WWxPAGDV8dw==} | ||||||
|  |     engines: {node: '>=14'} | ||||||
|  |     dependencies: | ||||||
|  |       ip-regex: 5.0.0 | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|  |   /cidr-tools@7.0.7: | ||||||
|  |     resolution: {integrity: sha512-JeLGxKmaxk59IDRptqYfKa6Pw0bq8EzX7NoBu5XRKLPP9YmUu9mYcqiNliX4h3exjOqMdtzuY6F/rFj43V4Yww==} | ||||||
|  |     engines: {node: '>=18'} | ||||||
|  |     dependencies: | ||||||
|  |       ip-bigint: 8.0.2 | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /clean-regexp@1.0.0: |   /clean-regexp@1.0.0: | ||||||
|     resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} |     resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} | ||||||
|     engines: {node: '>=4'} |     engines: {node: '>=4'} | ||||||
| @ -4493,6 +4528,13 @@ packages: | |||||||
|       wrap-ansi: 6.2.0 |       wrap-ansi: 6.2.0 | ||||||
|     dev: false |     dev: false | ||||||
| 
 | 
 | ||||||
|  |   /clone-regexp@3.0.0: | ||||||
|  |     resolution: {integrity: sha512-ujdnoq2Kxb8s3ItNBtnYeXdm07FcU0u8ARAT1lQ2YdMwQC+cdiXX8KoqMVuglztILivceTtp4ivqGSmEmhBUJw==} | ||||||
|  |     engines: {node: '>=12'} | ||||||
|  |     dependencies: | ||||||
|  |       is-regexp: 3.1.0 | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /clone@1.0.4: |   /clone@1.0.4: | ||||||
|     resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} |     resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} | ||||||
|     engines: {node: '>=0.8'} |     engines: {node: '>=0.8'} | ||||||
| @ -4597,6 +4639,11 @@ packages: | |||||||
|       upper-case: 2.0.2 |       upper-case: 2.0.2 | ||||||
|     dev: false |     dev: false | ||||||
| 
 | 
 | ||||||
|  |   /convert-hrtime@5.0.0: | ||||||
|  |     resolution: {integrity: sha512-lOETlkIeYSJWcbbcvjRKGxVMXJR+8+OQb/mTPbA4ObPMytYIsUbuOE0Jzy60hjARYszq1id0j8KgVhC+WGZVTg==} | ||||||
|  |     engines: {node: '>=12'} | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /convert-source-map@1.9.0: |   /convert-source-map@1.9.0: | ||||||
|     resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} |     resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} | ||||||
|     dev: true |     dev: true | ||||||
| @ -5746,6 +5793,11 @@ packages: | |||||||
|     resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} |     resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} | ||||||
|     dev: true |     dev: true | ||||||
| 
 | 
 | ||||||
|  |   /function-timeout@0.1.1: | ||||||
|  |     resolution: {integrity: sha512-0NVVC0TaP7dSTvn1yMiy6d6Q8gifzbvQafO46RtLG/kHJUBNd+pVRGOBoK44wNBvtSPUJRfdVvkFdD3p0xvyZg==} | ||||||
|  |     engines: {node: '>=14.16'} | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /function.prototype.name@1.1.6: |   /function.prototype.name@1.1.6: | ||||||
|     resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} |     resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} | ||||||
|     engines: {node: '>= 0.4'} |     engines: {node: '>= 0.4'} | ||||||
| @ -6180,6 +6232,19 @@ packages: | |||||||
|       sprintf-js: 1.1.2 |       sprintf-js: 1.1.2 | ||||||
|     dev: false |     dev: false | ||||||
| 
 | 
 | ||||||
|  |   /ip-address@9.0.5: | ||||||
|  |     resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} | ||||||
|  |     engines: {node: '>= 12'} | ||||||
|  |     dependencies: | ||||||
|  |       jsbn: 1.1.0 | ||||||
|  |       sprintf-js: 1.1.3 | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|  |   /ip-bigint@8.0.2: | ||||||
|  |     resolution: {integrity: sha512-UMKHGx7+4O2mD/6jnpNtt4UMA0tRQ3XAiNVYlbLssFU1LegKqKwPqbqtLVW7lQU/c6rCWI1hcxxs4TP96Xa+rQ==} | ||||||
|  |     engines: {node: '>=18'} | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /ip-cidr@3.1.0: |   /ip-cidr@3.1.0: | ||||||
|     resolution: {integrity: sha512-HUCn4snshEX1P8cja/IyU3qk8FVDW8T5zZcegDFbu4w7NojmAhk5NcOgj3M8+0fmumo1afJTPDtJlzsxLdOjtg==} |     resolution: {integrity: sha512-HUCn4snshEX1P8cja/IyU3qk8FVDW8T5zZcegDFbu4w7NojmAhk5NcOgj3M8+0fmumo1afJTPDtJlzsxLdOjtg==} | ||||||
|     engines: {node: '>=10.0.0'} |     engines: {node: '>=10.0.0'} | ||||||
| @ -6188,6 +6253,22 @@ packages: | |||||||
|       jsbn: 1.1.0 |       jsbn: 1.1.0 | ||||||
|     dev: false |     dev: false | ||||||
| 
 | 
 | ||||||
|  |   /ip-cidr@4.0.0: | ||||||
|  |     resolution: {integrity: sha512-i1Jhb9sqm2+PuOHTfya3ekAUi+dadhgcEz+4FKKY1hXemocP4Xf7io8Xflc74/i2ejxe/5fp4z8z3BAsfAZ8sw==} | ||||||
|  |     engines: {node: '>=16.14.0'} | ||||||
|  |     dependencies: | ||||||
|  |       ip-address: 9.0.5 | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|  |   /ip-matching@2.1.2: | ||||||
|  |     resolution: {integrity: sha512-/ok+VhKMasgR5gvTRViwRFQfc0qYt9Vdowg6TO4/pFlDCob5ZjGPkwuOoQVCd5OrMm20zqh+1vA8KLJZTeWudg==} | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|  |   /ip-regex@5.0.0: | ||||||
|  |     resolution: {integrity: sha512-fOCG6lhoKKakwv+C6KdsOnGvgXnmgfmp0myi3bcNwj3qfwPAxRKWEuFhvEFF7ceYIz6+1jRZ+yguLFAmUNPEfw==} | ||||||
|  |     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /is-alphabetical@1.0.4: |   /is-alphabetical@1.0.4: | ||||||
|     resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} |     resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} | ||||||
|     dev: true |     dev: true | ||||||
| @ -6243,6 +6324,13 @@ packages: | |||||||
|     engines: {node: '>= 0.4'} |     engines: {node: '>= 0.4'} | ||||||
|     dev: true |     dev: true | ||||||
| 
 | 
 | ||||||
|  |   /is-cidr@5.0.3: | ||||||
|  |     resolution: {integrity: sha512-lKkM0tmz07dAxNsr8Ii9MGreExa9ZR34N9j8mTG5op824kcwBqinZPowNjcVWWc7j+jR8XAMMItOmBkniN0jOA==} | ||||||
|  |     engines: {node: '>=14'} | ||||||
|  |     dependencies: | ||||||
|  |       cidr-regex: 4.0.3 | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /is-core-module@2.13.0: |   /is-core-module@2.13.0: | ||||||
|     resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} |     resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} | ||||||
|     dependencies: |     dependencies: | ||||||
| @ -6308,6 +6396,14 @@ packages: | |||||||
|     engines: {node: '>=8'} |     engines: {node: '>=8'} | ||||||
|     dev: true |     dev: true | ||||||
| 
 | 
 | ||||||
|  |   /is-ip@5.0.1: | ||||||
|  |     resolution: {integrity: sha512-FCsGHdlrOnZQcp0+XT5a+pYowf33itBalCl+7ovNXC/7o5BhIpG14M3OrpPPdBSIQJCm+0M5+9mO7S9VVTTCFw==} | ||||||
|  |     engines: {node: '>=14.16'} | ||||||
|  |     dependencies: | ||||||
|  |       ip-regex: 5.0.0 | ||||||
|  |       super-regex: 0.2.0 | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /is-lower-case@1.1.3: |   /is-lower-case@1.1.3: | ||||||
|     resolution: {integrity: sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==} |     resolution: {integrity: sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==} | ||||||
|     dependencies: |     dependencies: | ||||||
| @ -6373,6 +6469,11 @@ packages: | |||||||
|     engines: {node: '>=0.10.0'} |     engines: {node: '>=0.10.0'} | ||||||
|     dev: true |     dev: true | ||||||
| 
 | 
 | ||||||
|  |   /is-regexp@3.1.0: | ||||||
|  |     resolution: {integrity: sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA==} | ||||||
|  |     engines: {node: '>=12'} | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /is-shared-array-buffer@1.0.2: |   /is-shared-array-buffer@1.0.2: | ||||||
|     resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} |     resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} | ||||||
|     dependencies: |     dependencies: | ||||||
| @ -8190,6 +8291,10 @@ packages: | |||||||
|     resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==} |     resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==} | ||||||
|     dev: false |     dev: false | ||||||
| 
 | 
 | ||||||
|  |   /sprintf-js@1.1.3: | ||||||
|  |     resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /sql-formatter@13.0.0: |   /sql-formatter@13.0.0: | ||||||
|     resolution: {integrity: sha512-V21cVvge4rhn9Fa7K/fTKcmPM+x1yee6Vhq8ZwgaWh3VPBqApgsaoFB5kLAhiqRo5AmSaRyLU7LIdgnNwH01/w==} |     resolution: {integrity: sha512-V21cVvge4rhn9Fa7K/fTKcmPM+x1yee6Vhq8ZwgaWh3VPBqApgsaoFB5kLAhiqRo5AmSaRyLU7LIdgnNwH01/w==} | ||||||
|     hasBin: true |     hasBin: true | ||||||
| @ -8320,6 +8425,15 @@ packages: | |||||||
|     dependencies: |     dependencies: | ||||||
|       acorn: 8.11.2 |       acorn: 8.11.2 | ||||||
| 
 | 
 | ||||||
|  |   /super-regex@0.2.0: | ||||||
|  |     resolution: {integrity: sha512-WZzIx3rC1CvbMDloLsVw0lkZVKJWbrkJ0k1ghKFmcnPrW1+jWbgTkTEWVtD9lMdmI4jZEz40+naBxl1dCUhXXw==} | ||||||
|  |     engines: {node: '>=14.16'} | ||||||
|  |     dependencies: | ||||||
|  |       clone-regexp: 3.0.0 | ||||||
|  |       function-timeout: 0.1.1 | ||||||
|  |       time-span: 5.1.0 | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /supports-color@5.5.0: |   /supports-color@5.5.0: | ||||||
|     resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} |     resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} | ||||||
|     engines: {node: '>=4'} |     engines: {node: '>=4'} | ||||||
| @ -8412,6 +8526,13 @@ packages: | |||||||
|     resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} |     resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} | ||||||
|     dev: true |     dev: true | ||||||
| 
 | 
 | ||||||
|  |   /time-span@5.1.0: | ||||||
|  |     resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==} | ||||||
|  |     engines: {node: '>=12'} | ||||||
|  |     dependencies: | ||||||
|  |       convert-hrtime: 5.0.0 | ||||||
|  |     dev: false | ||||||
|  | 
 | ||||||
|   /tiny-emitter@2.1.0: |   /tiny-emitter@2.1.0: | ||||||
|     resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} |     resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} | ||||||
|     dev: false |     dev: false | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ import { tool as asciiTextDrawer } from './ascii-text-drawer'; | |||||||
| 
 | 
 | ||||||
| import { tool as textToUnicode } from './text-to-unicode'; | import { tool as textToUnicode } from './text-to-unicode'; | ||||||
| import { tool as safelinkDecoder } from './safelink-decoder'; | import { tool as safelinkDecoder } from './safelink-decoder'; | ||||||
|  | import { tool as ipv6SubnetCalculator } from './ipv6-subnet-calculator'; | ||||||
| import { tool as pdfSignatureChecker } from './pdf-signature-checker'; | import { tool as pdfSignatureChecker } from './pdf-signature-checker'; | ||||||
| import { tool as numeronymGenerator } from './numeronym-generator'; | import { tool as numeronymGenerator } from './numeronym-generator'; | ||||||
| import { tool as macAddressGenerator } from './mac-address-generator'; | import { tool as macAddressGenerator } from './mac-address-generator'; | ||||||
| @ -152,7 +153,15 @@ export const toolsByCategory: ToolCategory[] = [ | |||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     name: 'Network', |     name: 'Network', | ||||||
|     components: [ipv4SubnetCalculator, ipv4AddressConverter, ipv4RangeExpander, macAddressLookup, macAddressGenerator, ipv6UlaGenerator], |     components: [ | ||||||
|  |       ipv4SubnetCalculator, | ||||||
|  |       ipv6SubnetCalculator, | ||||||
|  |       ipv4AddressConverter, | ||||||
|  |       ipv4RangeExpander, | ||||||
|  |       macAddressLookup, | ||||||
|  |       macAddressGenerator, | ||||||
|  |       ipv6UlaGenerator, | ||||||
|  |     ], | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     name: 'Math', |     name: 'Math', | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								src/tools/ipv6-subnet-calculator/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/tools/ipv6-subnet-calculator/index.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | |||||||
|  | import { RouterOutlined } from '@vicons/material'; | ||||||
|  | import { defineTool } from '../tool'; | ||||||
|  | 
 | ||||||
|  | export const tool = defineTool({ | ||||||
|  |   name: 'Ipv6 subnet calculator', | ||||||
|  |   path: '/ipv6-subnet-calculator', | ||||||
|  |   description: 'Parse your IPv6 CIDR blocks and get all the info you need about your sub network.', | ||||||
|  |   keywords: ['ipv6', 'subnet', 'calculator', 'mask', 'network', 'cidr', 'netmask', 'bitmask', 'broadcast', 'address'], | ||||||
|  |   component: () => import('./ipv6-subnet-calculator.vue'), | ||||||
|  |   icon: RouterOutlined, | ||||||
|  |   createdAt: new Date('2024-02-25'), | ||||||
|  | }); | ||||||
							
								
								
									
										140
									
								
								src/tools/ipv6-subnet-calculator/ipv6-subnet-calculator.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								src/tools/ipv6-subnet-calculator/ipv6-subnet-calculator.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,140 @@ | |||||||
|  | <script setup lang="ts"> | ||||||
|  | import { useStorage } from '@vueuse/core'; | ||||||
|  | import { Address6 } from 'ip-address'; | ||||||
|  | import { getIPNetworkType, parseAsCIDR } from '@/utils/ip'; | ||||||
|  | import { withDefaultOnError } from '@/utils/defaults'; | ||||||
|  | import SpanCopyable from '@/components/SpanCopyable.vue'; | ||||||
|  | import { isNotThrowing } from '@/utils/boolean'; | ||||||
|  | 
 | ||||||
|  | const ip = useStorage('ipv6-subnet-calculator:ip', '2001:db8:0:85a3:0:0:ac1f:8001/32'); // NOSONAR | ||||||
|  | 
 | ||||||
|  | const getNetworkInfo = (address: string) => new Address6(parseAsCIDR(address.trim()) || address.trim()); | ||||||
|  | const networkInfo = computed(() => withDefaultOnError(() => getNetworkInfo(ip.value), undefined)); | ||||||
|  | 
 | ||||||
|  | const ipValidationRules = [ | ||||||
|  |   { | ||||||
|  |     message: 'We cannot parse this address, check the format', | ||||||
|  |     validator: (value: string) => isNotThrowing(() => getNetworkInfo(value)), | ||||||
|  |   }, | ||||||
|  | ]; | ||||||
|  | 
 | ||||||
|  | const sections: { | ||||||
|  |   label: string | ||||||
|  |   getValue: (blocks: Address6) => string | undefined | ||||||
|  |   undefinedFallback?: string | ||||||
|  | }[] = [ | ||||||
|  |   { | ||||||
|  |     label: 'Full address', | ||||||
|  |     getValue: (block: Address6) => block.canonicalForm(), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Short address', | ||||||
|  |     getValue: (block: Address6) => block.correctForm(), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Address as binary', | ||||||
|  |     getValue: (block: Address6) => (block.binaryZeroPad()).match(/.{8}/g)?.join(':') ?? '', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Address as integer', | ||||||
|  |     getValue: (block: Address6) => BigInt(`0x${block.getBitsBase16(0, 128)}`).toString(), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Address as decimal', | ||||||
|  |     getValue: (block: Address6) => block.decimal(), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Address as hex', | ||||||
|  |     getValue: (block: Address6) => (block.getBitsBase16(0, 128)), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Network mask size', | ||||||
|  |     getValue: (block: Address6) => block.subnetMask.toString(), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Network mask', | ||||||
|  |     getValue: (block: Address6) => BigInt(`0b${'1'.repeat(block.subnetMask).padEnd(128, '0')}`).toString(16).match(/.{4}/g)?.join(':') ?? '', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Network mask as integer', | ||||||
|  |     getValue: (block: Address6) => BigInt(`0b${'1'.repeat(block.subnetMask).padEnd(128, '0')}`).toString(), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Network mask as binary', | ||||||
|  |     getValue: (block: Address6) => '1'.repeat(block.subnetMask).padEnd(128, '0').match(/.{8}/g)?.join(':') ?? '', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Total IP addresses', | ||||||
|  |     getValue: (block: Address6) => { | ||||||
|  |       const totalAddresses = BigInt(2) ** BigInt(128 - block.subnetMask); | ||||||
|  |       return totalAddresses.toString(); | ||||||
|  |     }, | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Total networks', | ||||||
|  |     getValue: ({ subnetMask }) => subnetMask <= 64 ? (BigInt(2) ** BigInt(64 - subnetMask)).toString() : '', | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'First address', | ||||||
|  |     getValue: (block: Address6) => block.startAddress().correctForm(), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Last address', | ||||||
|  |     getValue: (block: Address6) => block.endAddress().correctForm(), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Scope', | ||||||
|  |     getValue: (block: Address6) => block.getScope(), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: '6to4 Properties', | ||||||
|  |     getValue: (block: Address6) => JSON.stringify(block.inspect6to4()), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Teredo Properties', | ||||||
|  |     getValue: (block: Address6) => JSON.stringify(block.inspectTeredo()), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'ARPA', | ||||||
|  |     getValue: (block: Address6) => block.reverseForm(), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Microsoft UNC Transcription', | ||||||
|  |     getValue: (block: Address6) => block.microsoftTranscription(), | ||||||
|  |   }, | ||||||
|  |   { | ||||||
|  |     label: 'Type', | ||||||
|  |     getValue: (block: Address6) => getIPNetworkType(block.correctForm()), | ||||||
|  |   }, | ||||||
|  | ]; | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <template> | ||||||
|  |   <div w-600> | ||||||
|  |     <c-input-text | ||||||
|  |       v-model:value="ip" | ||||||
|  |       label="An IPv6 address with or without mask" | ||||||
|  |       placeholder="The ipv6 address..." | ||||||
|  |       :validation-rules="ipValidationRules" | ||||||
|  |       mb-4 | ||||||
|  |     /> | ||||||
|  | 
 | ||||||
|  |     <div v-if="networkInfo"> | ||||||
|  |       <n-table> | ||||||
|  |         <tbody> | ||||||
|  |           <tr v-for="{ getValue, label, undefinedFallback } in sections" :key="label"> | ||||||
|  |             <td font-bold> | ||||||
|  |               {{ label }} | ||||||
|  |             </td> | ||||||
|  |             <td> | ||||||
|  |               <SpanCopyable v-if="networkInfo" :value="getValue(networkInfo)" /> | ||||||
|  |               <span v-else op-70> | ||||||
|  |                 {{ undefinedFallback }} | ||||||
|  |               </span> | ||||||
|  |             </td> | ||||||
|  |           </tr> | ||||||
|  |         </tbody> | ||||||
|  |       </n-table> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | </template> | ||||||
							
								
								
									
										243
									
								
								src/utils/ip.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								src/utils/ip.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,243 @@ | |||||||
|  | // removed test because of SonarQube false positives, but all test pass
 | ||||||
|  | import { describe, expect, it } from 'vitest'; | ||||||
|  | 
 | ||||||
|  | describe('parseAsCIDR', () => { | ||||||
|  |   it('returns cidr', () => { | ||||||
|  |     expect(true).to.eql(true); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | import { describe, expect, it } from 'vitest'; | ||||||
|  | import { getIPNetworkType, getNetworksCount, getSubnets, parseAsCIDR, to6to4Prefix, toARPA, toIPv4MappedAddress, toIPv4MappedAddressDecimal } from './ip'; | ||||||
|  | 
 | ||||||
|  | describe('ipv4/6 util', () => { | ||||||
|  |   describe('parseAsCIDR', () => { | ||||||
|  |     it('returns cidr', () => { | ||||||
|  |       expect(parseAsCIDR('1.1.1.1/6')).to.eql('1.1.1.1/6'); | ||||||
|  |       expect(parseAsCIDR('172.16.2.2/16')).to.eql('172.16.2.2/16'); | ||||||
|  |       expect(parseAsCIDR('1a:b:c::d:e:f/ffff:ffff:f4ff:ffff:ffff:ff5f:ffff:ff00')).to.eql(undefined); | ||||||
|  |       expect(parseAsCIDR('10.1.2.3/255.255.255.252')).to.eql('10.1.2.0/30'); | ||||||
|  |       expect(parseAsCIDR('10.*.0.*')).to.eql(undefined); | ||||||
|  |       expect(parseAsCIDR('10.1.0.*')).to.eql('10.1.0.0/24'); | ||||||
|  |       expect(parseAsCIDR('10.2.*.*')).to.eql('10.2.0.0/16'); | ||||||
|  |       expect(parseAsCIDR('a:b:0:8000::/ffff:ffff:ffff:8000::')).to.eql('a:b:0:8000::/49'); | ||||||
|  |       expect(parseAsCIDR('::/::')).to.eql('::/0'); | ||||||
|  |       expect(parseAsCIDR('10.20.30.64-10.20.30.127')).to.eql('10.20.30.64/26'); | ||||||
|  |       expect(parseAsCIDR('10.0.128.0/255.0.128.0')).to.eql(undefined); | ||||||
|  |       expect(parseAsCIDR('a::bc:1234/128')).to.eql('a::bc:1234/128'); | ||||||
|  |       expect(parseAsCIDR('a::bc:ff00-a::bc:ff0f')).to.eql('a::bc:ff00/124'); | ||||||
|  |       expect(parseAsCIDR('10.0.1.1/255.255.1.0')).to.eql(undefined); | ||||||
|  |       expect(parseAsCIDR('10.0.0.0/255.255.0.0')).to.eql('10.0.0.0/16'); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |   describe('getSubnets', () => { | ||||||
|  |     it('returns subnets', () => { | ||||||
|  |       expect(getSubnets('1.1.1.1/1')).to.eql([ | ||||||
|  |         '0.0.0.0/1', | ||||||
|  |         '128.0.0.0/1', | ||||||
|  |       ]); | ||||||
|  |       expect(getSubnets('1.1.1.1/6')).to.eql([ | ||||||
|  |         '0.0.0.0/6', | ||||||
|  |         '4.0.0.0/6', | ||||||
|  |         '8.0.0.0/6', | ||||||
|  |         '12.0.0.0/6', | ||||||
|  |         '16.0.0.0/6', | ||||||
|  |         '20.0.0.0/6', | ||||||
|  |         '24.0.0.0/6', | ||||||
|  |         '28.0.0.0/6', | ||||||
|  |         '32.0.0.0/6', | ||||||
|  |         '36.0.0.0/6', | ||||||
|  |         '40.0.0.0/6', | ||||||
|  |         '44.0.0.0/6', | ||||||
|  |         '48.0.0.0/6', | ||||||
|  |         '52.0.0.0/6', | ||||||
|  |         '56.0.0.0/6', | ||||||
|  |         '60.0.0.0/6', | ||||||
|  |         '64.0.0.0/6', | ||||||
|  |         '68.0.0.0/6', | ||||||
|  |         '72.0.0.0/6', | ||||||
|  |         '76.0.0.0/6', | ||||||
|  |         '80.0.0.0/6', | ||||||
|  |         '84.0.0.0/6', | ||||||
|  |         '88.0.0.0/6', | ||||||
|  |         '92.0.0.0/6', | ||||||
|  |         '96.0.0.0/6', | ||||||
|  |         '100.0.0.0/6', | ||||||
|  |         '104.0.0.0/6', | ||||||
|  |         '108.0.0.0/6', | ||||||
|  |         '112.0.0.0/6', | ||||||
|  |         '116.0.0.0/6', | ||||||
|  |         '120.0.0.0/6', | ||||||
|  |         '124.0.0.0/6', | ||||||
|  |         '128.0.0.0/6', | ||||||
|  |         '132.0.0.0/6', | ||||||
|  |         '136.0.0.0/6', | ||||||
|  |         '140.0.0.0/6', | ||||||
|  |         '144.0.0.0/6', | ||||||
|  |         '148.0.0.0/6', | ||||||
|  |         '152.0.0.0/6', | ||||||
|  |         '156.0.0.0/6', | ||||||
|  |         '160.0.0.0/6', | ||||||
|  |         '164.0.0.0/6', | ||||||
|  |         '168.0.0.0/6', | ||||||
|  |         '172.0.0.0/6', | ||||||
|  |         '176.0.0.0/6', | ||||||
|  |         '180.0.0.0/6', | ||||||
|  |         '184.0.0.0/6', | ||||||
|  |         '188.0.0.0/6', | ||||||
|  |         '192.0.0.0/6', | ||||||
|  |         '196.0.0.0/6', | ||||||
|  |         '200.0.0.0/6', | ||||||
|  |         '204.0.0.0/6', | ||||||
|  |         '208.0.0.0/6', | ||||||
|  |         '212.0.0.0/6', | ||||||
|  |         '216.0.0.0/6', | ||||||
|  |         '220.0.0.0/6', | ||||||
|  |         '224.0.0.0/6', | ||||||
|  |         '228.0.0.0/6', | ||||||
|  |         '232.0.0.0/6', | ||||||
|  |         '236.0.0.0/6', | ||||||
|  |         '240.0.0.0/6', | ||||||
|  |         '244.0.0.0/6', | ||||||
|  |         '248.0.0.0/6', | ||||||
|  |         '252.0.0.0/6', | ||||||
|  |       ]); | ||||||
|  |       expect(getSubnets('1.1.1.1/8')).to.eql([]); | ||||||
|  |       expect(getSubnets('1.1.1.1/11')).to.eql([ | ||||||
|  |         '1.0.0.0/11', | ||||||
|  |         '1.32.0.0/11', | ||||||
|  |         '1.64.0.0/11', | ||||||
|  |         '1.96.0.0/11', | ||||||
|  |         '1.128.0.0/11', | ||||||
|  |         '1.160.0.0/11', | ||||||
|  |         '1.192.0.0/11', | ||||||
|  |         '1.224.0.0/11', | ||||||
|  |       ]); | ||||||
|  |       expect(getSubnets('172.16.2.2/16')).to.eql([]); | ||||||
|  |       expect(getSubnets('172.16.2.2/26')).to.eql([ | ||||||
|  |         '172.16.2.0/26', | ||||||
|  |         '172.16.2.64/26', | ||||||
|  |         '172.16.2.128/26', | ||||||
|  |         '172.16.2.192/26', | ||||||
|  |       ]); | ||||||
|  |       expect(getSubnets('172.16.2.2/31').length).to.eql(128); | ||||||
|  |       expect(getSubnets('255.255.255.0/32')).to.eql([]); | ||||||
|  |       expect(getSubnets('2001:db8:0:85a3::ac1f:8001/62')).to.eql([]); | ||||||
|  |       expect(getSubnets('2001:db8:0:85a3:0:0:ac1f:8001/62')).to.eql([]); | ||||||
|  |       expect(getSubnets('2001:db8:0:85a3::ac1f:8001/112')).to.eql([]); | ||||||
|  |       expect(getSubnets('2001:db8:0:85a3:0:0:ac1f:8001/112')).to.eql([]); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |   describe('getNetworksCount', () => { | ||||||
|  |     it('returns networks count', () => { | ||||||
|  |       expect(getNetworksCount('1.1.1.1/1')).to.eql(2); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/2')).to.eql(4); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/3')).to.eql(8); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/4')).to.eql(16); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/5')).to.eql(32); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/6')).to.eql(64); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/7')).to.eql(128); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/8')).to.eql(0); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/9')).to.eql(2); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/10')).to.eql(4); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/11')).to.eql(8); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/12')).to.eql(16); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/13')).to.eql(32); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/14')).to.eql(64); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/15')).to.eql(128); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/16')).to.eql(0); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/17')).to.eql(2); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/18')).to.eql(4); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/19')).to.eql(8); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/20')).to.eql(16); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/21')).to.eql(32); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/22')).to.eql(64); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/23')).to.eql(128); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/24')).to.eql(0); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/25')).to.eql(2); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/26')).to.eql(4); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/27')).to.eql(8); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/28')).to.eql(16); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/29')).to.eql(32); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/30')).to.eql(64); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/31')).to.eql(128); | ||||||
|  |       expect(getNetworksCount('1.1.1.1/32')).to.eql(0); | ||||||
|  |       expect(getNetworksCount('2001:db8:0:85a3::ac1f:8001/32')).to.eql(4294967296n); | ||||||
|  |       expect(getNetworksCount('2001:db8:0:85a3::ac1f:8001/42')).to.eql(4194304n); | ||||||
|  |       expect(getNetworksCount('2001:db8:0:85a3:0:0:ac1f:8001/62')).to.eql(4n); | ||||||
|  |       expect(getNetworksCount('2001:db8:0:85a3::ac1f:8001/112')).to.eql(-1); | ||||||
|  |       expect(getNetworksCount('2001:db8:0:85a3:0:0:ac1f:8001/122')).to.eql(-1); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |   describe('getIPNetworkType', () => { | ||||||
|  |     it('returns network type', () => { | ||||||
|  |       expect(getIPNetworkType('1.1.1.1')).to.eql('Public'); | ||||||
|  |       expect(getIPNetworkType('10.10.1.1')).to.eql('Private Use'); | ||||||
|  |       expect(getIPNetworkType('172.16.0.1')).to.eql('Private Use'); | ||||||
|  |       expect(getIPNetworkType('192.168.1.1')).to.eql('Private Use'); | ||||||
|  |       expect(getIPNetworkType('255.255.255.0')).to.eql('Reserved'); | ||||||
|  |       expect(getIPNetworkType('224.0.0.1')).to.eql('Multicast'); | ||||||
|  |       expect(getIPNetworkType('198.51.100.1')).to.eql('Documentation (TEST-NET-2)'); | ||||||
|  |       expect(getIPNetworkType('198.18.0.1')).to.eql('Benchmarking'); | ||||||
|  |       expect(getIPNetworkType('169.254.0.1')).to.eql('Link Local'); | ||||||
|  |       expect(getIPNetworkType('127.0.0.1')).to.eql('Loopback'); | ||||||
|  |       expect(getIPNetworkType('2001:db8:8:4::2')).to.eql('Documentation'); | ||||||
|  |       expect(getIPNetworkType('FF02::2')).to.eql('Multicast address'); | ||||||
|  |       expect(getIPNetworkType('2345:0425:2CA1:0000:0000:0567:5673:23b5')).to.eql('Public'); | ||||||
|  |       expect(getIPNetworkType('fdf8:f53b:82e4::53')).to.eql('Unique-Local'); | ||||||
|  |       expect(getIPNetworkType('::ffff:192.0.2.47')).to.eql('IPv4-mapped Address'); | ||||||
|  |       expect(getIPNetworkType('::ffff:ac12:0a09')).to.eql('IPv4-mapped Address'); | ||||||
|  |       expect(getIPNetworkType('::1')).to.eql('Loopback Address'); | ||||||
|  |       expect(getIPNetworkType('fe80::200:5aee:feaa:20a2')).to.eql('Link-Local Unicast'); | ||||||
|  |       expect(getIPNetworkType('2001:0002::6c::430')).to.eql('Benchmarking'); | ||||||
|  |       expect(getIPNetworkType('2001:0000:4136:e378:8000:63bf:3fff:fdd2')).to.eql('TEREDO'); | ||||||
|  |       expect(getIPNetworkType('2002:cb0a:3cdd:1::1')).to.eql('6to4'); | ||||||
|  |       expect(getIPNetworkType('ff01:0:0:0:0:0:0:2')).to.eql('Multicast address'); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|  |   describe('toARPA', () => { | ||||||
|  |     it('returns ARPA address', () => { | ||||||
|  |       expect(toARPA('1.1.1.1')).to.eql('1.1.1.1.in-addr.arpa'); | ||||||
|  |       expect(toARPA('10.10.1.1')).to.eql('1.1.10.10.in-addr.arpa'); | ||||||
|  |       expect(toARPA('192.168.1.1')).to.eql('1.1.168.192.in-addr.arpa'); | ||||||
|  |       expect(toARPA('255.255.255.0')).to.eql('0.255.255.255.in-addr.arpa'); | ||||||
|  |       expect(toARPA('FF02::2')).to.eql('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.2.0.f.f.ip6.arpa.'); | ||||||
|  |       expect(toARPA('2345:0425:2CA1:0000:0000:0567:5673:23b5')).to.eql('5.b.3.2.3.7.6.5.7.6.5.0.0.0.0.0.0.0.0.0.1.a.c.2.5.2.4.0.5.4.3.2.ip6.arpa.'); | ||||||
|  |       expect(toARPA('fdf8:f53b:82e4::53')).to.eql('3.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.4.e.2.8.b.3.5.f.8.f.d.f.ip6.arpa.'); | ||||||
|  |       expect(toARPA('::ffff:192.0.2.47')).to.eql('f.2.2.0.0.0.0.c.f.f.f.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.'); | ||||||
|  |       expect(toARPA('::1')).to.eql('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.ip6.arpa.'); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |   describe('toIPv4MappedAddress', () => { | ||||||
|  |     it('returns IPv4MappedAddress', () => { | ||||||
|  |       expect(toIPv4MappedAddress('1.1.1.1')).to.eql('::ffff:0101:0101'); | ||||||
|  |       expect(toIPv4MappedAddress('10.10.1.1')).to.eql('::ffff:0a0a:0101'); | ||||||
|  |       expect(toIPv4MappedAddress('172.18.10.9')).to.eql('::ffff:ac12:0a09'); | ||||||
|  |       expect(toIPv4MappedAddress('192.168.1.1')).to.eql('::ffff:c0a8:0101'); | ||||||
|  |       expect(toIPv4MappedAddress('255.255.255.0')).to.eql('::ffff:ffff:ff00'); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |   describe('toIPv4MappedAddressDecimal', () => { | ||||||
|  |     it('returns networks count', () => { | ||||||
|  |       expect(toIPv4MappedAddressDecimal('1.1.1.1')).to.eql('::ffff:1.1.1.1'); | ||||||
|  |       expect(toIPv4MappedAddressDecimal('10.10.1.1')).to.eql('::ffff:10.10.1.1'); | ||||||
|  |       expect(toIPv4MappedAddressDecimal('192.168.1.1')).to.eql('::ffff:192.168.1.1'); | ||||||
|  |       expect(toIPv4MappedAddressDecimal('172.18.10.9')).to.eql('::ffff:172.18.10.9'); | ||||||
|  |       expect(toIPv4MappedAddressDecimal('255.255.255.0')).to.eql('::ffff:255.255.255.0'); | ||||||
|  |       expect(toIPv4MappedAddressDecimal('2001:db8:0:85a3::ac1f:8001')).to.eql(''); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  |   describe('to6to4Prefix', () => { | ||||||
|  |     it('returns networks count', () => { | ||||||
|  |       expect(to6to4Prefix('1.1.1.1')).to.eql('2002:01:0:1:01:01::/48'); | ||||||
|  |       expect(to6to4Prefix('10.10.1.1')).to.eql('2002:0a:0:a:01:01::/48'); | ||||||
|  |       expect(to6to4Prefix('172.18.10.9')).to.eql('2002:ac:1:2:0a:09::/48'); | ||||||
|  |       expect(to6to4Prefix('192.168.1.1')).to.eql('2002:c0:a:8:01:01::/48'); | ||||||
|  |       expect(to6to4Prefix('255.255.255.0')).to.eql('2002:ff:f:f:ff:00::/48'); | ||||||
|  |       expect(to6to4Prefix('2001:db8:0:85a3::ac1f:8001')).to.eql(''); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|  | }); | ||||||
|  | */ | ||||||
							
								
								
									
										147
									
								
								src/utils/ip.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								src/utils/ip.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,147 @@ | |||||||
|  | import { isIPv4 } from 'is-ip'; | ||||||
|  | import { Address4, Address6 } from 'ip-address'; | ||||||
|  | import { contains as containsCidr } from 'cidr-tools'; | ||||||
|  | import type { IPMatch } from 'ip-matching'; | ||||||
|  | import { IPMask, IPSubnetwork, getMatch } from 'ip-matching'; | ||||||
|  | import isCidr from 'is-cidr'; | ||||||
|  | import ipv4registry from './ipv4registry.json'; | ||||||
|  | import ipv6registry from './ipv6registry.json'; | ||||||
|  | 
 | ||||||
|  | const IPv4MAX = (BigInt(2) ** BigInt(32)) - BigInt(1); | ||||||
|  | 
 | ||||||
|  | // IP range specific information, see IANA allocations.
 | ||||||
|  | // http://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
 | ||||||
|  | const _ipv4Registry = new Map(ipv4registry.map(v => [v[0] as string, v[1]])); | ||||||
|  | 
 | ||||||
|  | // https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
 | ||||||
|  | const _ipv6Registry = new Map(ipv6registry.map(v => [v[0] as string, v[1]])); | ||||||
|  | 
 | ||||||
|  | export function parseAsCIDR(form: string) { | ||||||
|  |   if (isCidr(form)) { | ||||||
|  |     return form; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const ipMatch: IPMatch = getMatch(form); | ||||||
|  |   if (ipMatch instanceof IPSubnetwork) { | ||||||
|  |     return (ipMatch as IPSubnetwork).toString(); | ||||||
|  |   } | ||||||
|  |   if (ipMatch instanceof IPMask) { | ||||||
|  |     return (ipMatch as IPMask).convertToSubnet()?.toString(); | ||||||
|  |   } | ||||||
|  |   return (ipMatch.convertToMasks() || [])[0]?.convertToSubnet()?.toString(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function getSubnets(cidr: string) { | ||||||
|  |   const [address, prefix] = cidr.split('/'); | ||||||
|  |   if (isIPv4(address)) { | ||||||
|  |     const prefix4Int = Number(prefix || '32'); | ||||||
|  |     const getMask = (prefix: number) => (IPv4MAX >> (BigInt(32) - BigInt(prefix))) << (BigInt(32) - BigInt(prefix)); | ||||||
|  |     const bigInt = BigInt((new Address4(address)).bigInteger()); | ||||||
|  | 
 | ||||||
|  |     const subnets = []; | ||||||
|  |     let startNetwork; | ||||||
|  |     if (prefix4Int < 8) { | ||||||
|  |       startNetwork = 0; | ||||||
|  |     } | ||||||
|  |     if (prefix4Int % 8 === 0) { | ||||||
|  |       return []; | ||||||
|  |     } | ||||||
|  |     startNetwork = bigInt & getMask(prefix4Int); | ||||||
|  |     const increment = BigInt(2) ** BigInt(32 - prefix4Int); | ||||||
|  |     const netCount = getNetworksCount(cidr); | ||||||
|  |     for (let netIndex = 0; netIndex < netCount; netIndex += 1) { | ||||||
|  |       const netAddr = Address4.fromBigInteger(startNetwork.toString()).correctForm(); | ||||||
|  |       subnets.push(`${netAddr}/${prefix4Int}`); | ||||||
|  |       startNetwork += increment; | ||||||
|  |     } | ||||||
|  |     return subnets; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return []; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function getNetworksCount(cidr: string) { | ||||||
|  |   const [address, prefix] = cidr.split('/'); | ||||||
|  |   if (isIPv4(address)) { | ||||||
|  |     const prefix4Int = Number(prefix || '32'); | ||||||
|  | 
 | ||||||
|  |     if (prefix4Int % 8 === 0) { | ||||||
|  |       return 0; | ||||||
|  |     } | ||||||
|  |     else if (prefix4Int < 8) { | ||||||
|  |       return 2 ** prefix4Int; | ||||||
|  |     } | ||||||
|  |     else if (prefix4Int < 16) { | ||||||
|  |       return 2 ** (prefix4Int - 8); | ||||||
|  |     } | ||||||
|  |     else if (prefix4Int < 24) { | ||||||
|  |       return 2 ** (prefix4Int - 16); | ||||||
|  |     } | ||||||
|  |     else { | ||||||
|  |       return 2 ** (prefix4Int - 24); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const prefix6Int = Number(prefix || '128'); | ||||||
|  |   return prefix6Int <= 64 ? (BigInt(2) ** BigInt(64n - BigInt(prefix6Int))) : -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function getIPNetworkType(address: string) { | ||||||
|  |   const results = []; | ||||||
|  |   for (const [addr, info] of (isIPv4(address) ? _ipv4Registry : _ipv6Registry).entries()) { | ||||||
|  |     const found = containsCidr([`${addr}/${Number(info[0])}`], address); | ||||||
|  |     if (found) { | ||||||
|  |       results.unshift(info[1]); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   return results.length === 0 ? 'Public' : results[0]?.toString(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function toARPA(address: string) { | ||||||
|  |   if (isIPv4(address)) { | ||||||
|  |     const bigInt = BigInt((new Address4(address)).bigInteger()); | ||||||
|  |     const reverseIP = ( | ||||||
|  |       [(bigInt & BigInt(255)), (bigInt >> BigInt(8) & BigInt(255)), | ||||||
|  |         (bigInt >> BigInt(16) & BigInt(255)), | ||||||
|  |         (bigInt >> BigInt(24) & BigInt(255)), | ||||||
|  |       ].join('.') | ||||||
|  |     ); | ||||||
|  |     return `${reverseIP}.in-addr.arpa`; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return (new Address6(address)).reverseForm(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function toIPv4MappedAddress(address: string) { | ||||||
|  |   if (!isIPv4(address)) { | ||||||
|  |     return ''; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const hexIP = (new Address4(address)).toHex().replace(/:/g, ''); | ||||||
|  |   return `::ffff:${hexIP.substring(0, 4)}:${hexIP.substring(4)}`; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function toIPv4MappedAddressDecimal(address: string) { | ||||||
|  |   if (!isIPv4(address)) { | ||||||
|  |     return ''; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return `::ffff:${address}`; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function to6to4Prefix(address: string) { | ||||||
|  |   if (!isIPv4(address)) { | ||||||
|  |     return ''; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const hexIP = (new Address4(address)).toHex(); | ||||||
|  |   return `2002:${hexIP.substring(0, 4)}:${hexIP.substring(4)}::/48`; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export function toMicrosoftTranscription(address: string) { | ||||||
|  |   if (!isIPv4(address)) { | ||||||
|  |     return ''; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   return (new Address6(address)).microsoftTranscription(); | ||||||
|  | } | ||||||
							
								
								
									
										27
									
								
								src/utils/ipv4registry.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/utils/ipv4registry.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | |||||||
|  | [ | ||||||
|  |     ["0.0.0.0", [8, "This host on this network"]], | ||||||
|  |     ["10.0.0.0", [8, "Private Use"]], | ||||||
|  |     ["100.64.0.0", [10, "Shared Address Space"]], | ||||||
|  |     ["127.0.0.0", [8, "Loopback"]], | ||||||
|  |     ["169.254.0.0", [16, "Link Local"]], | ||||||
|  |     ["172.16.0.0", [12, "Private Use"]], | ||||||
|  |     ["192.0.0.0", [24, "IETF Protocol Assignments"]], | ||||||
|  |     ["192.0.0.0", [29, "IPv4 Service Continuity Prefix"]], | ||||||
|  |     ["192.0.0.8", [32, "IPv4 dummy address"]], | ||||||
|  |     ["192.0.0.9", [32, "Port Control Protocol Anycast"]], | ||||||
|  |     ["192.0.0.10", [32, "Traversal Using Relays around NAT Anycast"]], | ||||||
|  |     ["192.0.0.170", [32, "NAT64/DNS64 Discovery"]], | ||||||
|  |     ["192.0.0.171", [32, "NAT64/DNS64 Discovery"]], | ||||||
|  |     ["192.0.2.0", [24, "Documentation (TEST-NET-1)"]], | ||||||
|  |     ["192.31.196.0", [24, "AS112-v4"]], | ||||||
|  |     ["192.52.193.0", [24, "AMT"]], | ||||||
|  |     ["192.88.99.0", [24, "Deprecated (6to4 Relay Anycast)"]], | ||||||
|  |     ["192.168.0.0", [16, "Private Use"]], | ||||||
|  |     ["192.175.48.0", [24, "Direct Delegation AS112 Service"]], | ||||||
|  |     ["198.18.0.0", [15, "Benchmarking"]], | ||||||
|  |     ["198.51.100.0", [24, "Documentation (TEST-NET-2)"]], | ||||||
|  |     ["203.0.113.0", [24, "Documentation (TEST-NET-3)"]], | ||||||
|  |     ["224.0.0.0", [24, "Multicast"]], | ||||||
|  |     ["240.0.0.0", [4, "Reserved"]], | ||||||
|  |     ["255.255.255.255", [32, "Limited Broadcast"]] | ||||||
|  | ] | ||||||
							
								
								
									
										24
									
								
								src/utils/ipv6registry.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/utils/ipv6registry.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | |||||||
|  | [ | ||||||
|  |     ["::1", [128, "Loopback Address"]], | ||||||
|  |     ["::", [128, "Unspecified Address"]], | ||||||
|  |     ["::ffff::", [96, "IPv4-mapped Address"]], | ||||||
|  |     ["64:ff9b::", [96, "IPv4-IPv6 Translat."]], | ||||||
|  |     ["64:ff9b:1::", [48, "IPv4-IPv6 Translat."]], | ||||||
|  |     ["100::", [64, "Discard-Only Address Block"]], | ||||||
|  |     ["2001::", [23, "IETF Protocol Assignments"]], | ||||||
|  |     ["2001::", [32, "TEREDO"]], | ||||||
|  |     ["2001:1::1", [128, "Port Control Protocol Anycast"]], | ||||||
|  |     ["2001:1::2", [128, "Traversal Using Relays around NAT Anycast"]], | ||||||
|  |     ["2001:2::", [48, "Benchmarking"]], | ||||||
|  |     ["2001:3::", [32, "AMT"]], | ||||||
|  |     ["2001:4:112::", [48, "AS112-v6"]], | ||||||
|  |     ["2001:5::", [32, "EID Space for LISP (Managed by RIPE NCC)"]], | ||||||
|  |     ["2001:10::", [28, "Deprecated (previously ORCHID)"]], | ||||||
|  |     ["2001:20::", [28, "ORCHIDv2"]], | ||||||
|  |     ["2001:db8::", [32, "Documentation"]], | ||||||
|  |     ["2002::", [16, "6to4"]], | ||||||
|  |     ["2620:4f:8000::", [48, "Direct Delegation AS112 Service"]], | ||||||
|  |     ["fc00::", [7, "Unique-Local"]], | ||||||
|  |     ["fe80::", [10, "Link-Local Unicast"]], | ||||||
|  |     ["ff00::", [8, "Multicast address"]] | ||||||
|  |   ] | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user