From 2fe369a424de8819272d690250c631857ffe7642 Mon Sep 17 00:00:00 2001 From: sharevb Date: Sat, 3 Feb 2024 12:20:33 +0100 Subject: [PATCH] feat(new tool): IPv4/6 Range To CIDR IPv4/6 Range To CIDR Fix #802 --- components.d.ts | 1 + package.json | 6 + pnpm-lock.yaml | 120 +++++++++++++++++- src/tools/index.ts | 11 +- src/tools/ip-range-to-cidr/index.ts | 12 ++ src/tools/ip-range-to-cidr/ip-bigint.d.ts | 17 +++ .../ip-range-to-cidr/ip-range-to-cidr.vue | 117 +++++++++++++++++ 7 files changed, 280 insertions(+), 4 deletions(-) create mode 100644 src/tools/ip-range-to-cidr/index.ts create mode 100644 src/tools/ip-range-to-cidr/ip-bigint.d.ts create mode 100644 src/tools/ip-range-to-cidr/ip-range-to-cidr.vue diff --git a/components.d.ts b/components.d.ts index fabbe7939..21674d0ea 100644 --- a/components.d.ts +++ b/components.d.ts @@ -112,6 +112,7 @@ declare module '@vue/runtime-core' { IconMdiVideo: typeof import('~icons/mdi/video')['default'] InputCopyable: typeof import('./src/components/InputCopyable.vue')['default'] IntegerBaseConverter: typeof import('./src/tools/integer-base-converter/integer-base-converter.vue')['default'] + IpRangeToCidr: typeof import('./src/tools/ip-range-to-cidr/ip-range-to-cidr.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'] Ipv4SubnetCalculator: typeof import('./src/tools/ipv4-subnet-calculator/ipv4-subnet-calculator.vue')['default'] diff --git a/package.json b/package.json index e0148f879..f116ae1f6 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@vueuse/router": "^10.0.0", "bcryptjs": "^2.4.3", "change-case": "^4.1.2", + "cidr-tools": "^7.0.4", "colord": "^2.9.3", "composerize-ts": "^0.6.2", "country-code-lookup": "^0.1.0", @@ -62,6 +63,11 @@ "highlight.js": "^11.7.0", "iarna-toml-esm": "^3.0.5", "ibantools": "^4.3.3", + "ip-address": "^9.0.5", + "ip-bigint": "^8.0.2", + "ip-cidr": "^4.0.0", + "is-cidr": "^5.0.3", + "is-ip": "^5.0.1", "json5": "^2.2.3", "jwt-decode": "^3.1.2", "libphonenumber-js": "^1.10.28", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dfacabd43..4310a6999 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,6 +44,9 @@ dependencies: change-case: specifier: ^4.1.2 version: 4.1.2 + cidr-tools: + specifier: ^7.0.4 + version: 7.0.4 colord: specifier: ^2.9.3 version: 2.9.3 @@ -86,6 +89,21 @@ dependencies: ibantools: specifier: ^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 + is-cidr: + specifier: ^5.0.3 + version: 5.0.3 + is-ip: + specifier: ^5.0.1 + version: 5.0.1 json5: specifier: ^2.2.3 version: 2.2.3 @@ -3374,7 +3392,7 @@ packages: dependencies: '@unhead/dom': 0.5.1 '@unhead/schema': 0.5.1 - '@vueuse/shared': 10.6.1(vue@3.3.4) + '@vueuse/shared': 10.7.2(vue@3.3.4) unhead: 0.5.1 vue: 3.3.4 transitivePeerDependencies: @@ -4016,8 +4034,8 @@ packages: - vue dev: false - /@vueuse/shared@10.6.1(vue@3.3.4): - resolution: {integrity: sha512-TECVDTIedFlL0NUfHWncf3zF9Gc4VfdxfQc8JFwoVZQmxpONhLxFrlm0eHQeidHj4rdTPL3KXJa0TZCk1wnc5Q==} + /@vueuse/shared@10.7.2(vue@3.3.4): + resolution: {integrity: sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==} dependencies: vue-demi: 0.14.6(vue@3.3.4) transitivePeerDependencies: @@ -4486,6 +4504,20 @@ packages: engines: {node: '>=8'} 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.4: + resolution: {integrity: sha512-bKd6xC01ObuVKvJPGdV9Rz02KFO3mtHwMe/QTlcVuFAmU5n3RN/F3FgppHZaQjM+c/1i9YB9rgKNH/5iVqwCoA==} + engines: {node: '>=18'} + dependencies: + ip-bigint: 8.0.2 + dev: false + /clean-regexp@1.0.0: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} @@ -4513,6 +4545,13 @@ packages: wrap-ansi: 6.2.0 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: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} @@ -4617,6 +4656,11 @@ packages: upper-case: 2.0.2 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: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} dev: true @@ -5761,6 +5805,11 @@ packages: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} 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: resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} engines: {node: '>= 0.4'} @@ -6195,6 +6244,19 @@ packages: sprintf-js: 1.1.2 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: resolution: {integrity: sha512-HUCn4snshEX1P8cja/IyU3qk8FVDW8T5zZcegDFbu4w7NojmAhk5NcOgj3M8+0fmumo1afJTPDtJlzsxLdOjtg==} engines: {node: '>=10.0.0'} @@ -6203,6 +6265,18 @@ packages: jsbn: 1.1.0 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-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: resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==} dev: true @@ -6258,6 +6332,13 @@ packages: engines: {node: '>= 0.4'} 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: resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} dependencies: @@ -6323,6 +6404,14 @@ packages: engines: {node: '>=8'} 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: resolution: {integrity: sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==} dependencies: @@ -6388,6 +6477,11 @@ packages: engines: {node: '>=0.10.0'} 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: resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} dependencies: @@ -8225,6 +8319,10 @@ packages: resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==} dev: false + /sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + dev: false + /sql-formatter@13.0.0: resolution: {integrity: sha512-V21cVvge4rhn9Fa7K/fTKcmPM+x1yee6Vhq8ZwgaWh3VPBqApgsaoFB5kLAhiqRo5AmSaRyLU7LIdgnNwH01/w==} hasBin: true @@ -8355,6 +8453,15 @@ packages: dependencies: 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: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -8447,6 +8554,13 @@ packages: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} 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: resolution: {integrity: sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==} dev: false diff --git a/src/tools/index.ts b/src/tools/index.ts index 2a477ed2d..2a0506b45 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -77,6 +77,7 @@ import { tool as uuidGenerator } from './uuid-generator'; import { tool as macAddressLookup } from './mac-address-lookup'; import { tool as xmlFormatter } from './xml-formatter'; import { tool as yamlViewer } from './yaml-viewer'; +import { tool as ipRangeToCidr } from './ip-range-to-cidr'; export const toolsByCategory: ToolCategory[] = [ { @@ -147,7 +148,15 @@ export const toolsByCategory: ToolCategory[] = [ }, { name: 'Network', - components: [ipv4SubnetCalculator, ipv4AddressConverter, ipv4RangeExpander, macAddressLookup, macAddressGenerator, ipv6UlaGenerator], + components: [ + ipv4SubnetCalculator, + ipv4AddressConverter, + ipv4RangeExpander, + ipRangeToCidr, + macAddressLookup, + macAddressGenerator, + ipv6UlaGenerator, + ], }, { name: 'Math', diff --git a/src/tools/ip-range-to-cidr/index.ts b/src/tools/ip-range-to-cidr/index.ts new file mode 100644 index 000000000..c8a444114 --- /dev/null +++ b/src/tools/ip-range-to-cidr/index.ts @@ -0,0 +1,12 @@ +import { Binary } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'IPv4/6 Range to CIDR(s) Calculator', + path: '/ip-range-to-cidr', + description: 'Calculate CIDR(s) from an IP Range (IPv4/6)', + keywords: ['ip', 'range', 'to', 'cidr'], + component: () => import('./ip-range-to-cidr.vue'), + icon: Binary, + createdAt: new Date('2024-01-10'), +}); diff --git a/src/tools/ip-range-to-cidr/ip-bigint.d.ts b/src/tools/ip-range-to-cidr/ip-bigint.d.ts new file mode 100644 index 000000000..eff260301 --- /dev/null +++ b/src/tools/ip-range-to-cidr/ip-bigint.d.ts @@ -0,0 +1,17 @@ +declare module 'ip-bigint' { + type IPInfo = { + number: bigint; + version: number; + ipv4mapped?: boolean; + scopeid?:string; + }; + type StringifyOptions = { + compress?:boolean; + hexify?:boolean; + }; + + export function normalizeIp(ip: string, options: StringifyOptions = {compress = true, hexify = false} = {}) + export function stringifyIp(ip: IPInfo, options: StringifyOptions = {compress = true, hexify = false}): string; + export function ipVersion(ip: string): number; + export function parseIp(ip): IPInfo; +} \ No newline at end of file diff --git a/src/tools/ip-range-to-cidr/ip-range-to-cidr.vue b/src/tools/ip-range-to-cidr/ip-range-to-cidr.vue new file mode 100644 index 000000000..397b15646 --- /dev/null +++ b/src/tools/ip-range-to-cidr/ip-range-to-cidr.vue @@ -0,0 +1,117 @@ + + +