diff options
author | 2023-04-08 21:10:00 +0200 | |
---|---|---|
committer | 2023-04-08 21:13:14 +0200 | |
commit | 28145e0ffeb1f1c97cc503fb1e82ec18e8ebd588 (patch) | |
tree | 65ba60a709e4432f30fd0842bcdf5c080bd30a49 /src | |
parent | 8930e139b28ff165cca2d818199505a727106466 (diff) | |
download | it-tools-28145e0ffeb1f1c97cc503fb1e82ec18e8ebd588.tar.gz it-tools-28145e0ffeb1f1c97cc503fb1e82ec18e8ebd588.tar.zst it-tools-28145e0ffeb1f1c97cc503fb1e82ec18e8ebd588.zip |
feat(new-tool): ipv4 address converter
Diffstat (limited to 'src')
5 files changed, 152 insertions, 1 deletions
diff --git a/src/tools/index.ts b/src/tools/index.ts index 8ea8b54..f1d63b7 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -1,6 +1,7 @@ import { tool as base64FileConverter } from './base64-file-converter'; import { tool as base64StringConverter } from './base64-string-converter'; import { tool as basicAuthGenerator } from './basic-auth-generator'; +import { tool as ipv4AddressConverter } from './ipv4-address-converter'; import { tool as benchmarkBuilder } from './benchmark-builder'; import { tool as userAgentParser } from './user-agent-parser'; import { tool as ipv4SubnetCalculator } from './ipv4-subnet-calculator'; @@ -103,7 +104,7 @@ export const toolsByCategory: ToolCategory[] = [ }, { name: 'Network', - components: [ipv4SubnetCalculator, macAddressLookup], + components: [ipv4SubnetCalculator, ipv4AddressConverter, macAddressLookup], }, { name: 'Math', diff --git a/src/tools/ipv4-address-converter/index.ts b/src/tools/ipv4-address-converter/index.ts new file mode 100644 index 0000000..62d2daf --- /dev/null +++ b/src/tools/ipv4-address-converter/index.ts @@ -0,0 +1,12 @@ +import { Binary } from '@vicons/tabler'; +import { defineTool } from '../tool'; + +export const tool = defineTool({ + name: 'Ipv4 address converter', + path: '/ipv4-address-converter', + description: 'Convert an ip address into decimal, binary, hexadecimal or event in ipv6', + keywords: ['ipv4', 'address', 'converter', 'decimal', 'hexadecimal', 'binary', 'ipv6'], + component: () => import('./ipv4-address-converter.vue'), + icon: Binary, + createdAt: new Date('2023-04-08'), +}); diff --git a/src/tools/ipv4-address-converter/ipv4-address-converter.service.test.ts b/src/tools/ipv4-address-converter/ipv4-address-converter.service.test.ts new file mode 100644 index 0000000..ecdcfa2 --- /dev/null +++ b/src/tools/ipv4-address-converter/ipv4-address-converter.service.test.ts @@ -0,0 +1,36 @@ +import { expect, describe, it } from 'vitest'; +import { isValidIpv4, ipv4ToInt } from './ipv4-address-converter.service'; + +describe('ipv4-address-converter', () => { + describe('ipv4ToInt', () => { + it('should convert an IPv4 address to an integer', () => { + expect(ipv4ToInt({ ip: '192.168.0.1' })).toBe(3232235521); + expect(ipv4ToInt({ ip: '10.0.0.1' })).toBe(167772161); + expect(ipv4ToInt({ ip: '255.255.255.255' })).toBe(4294967295); + }); + }); + + describe('isValidIpv4', () => { + it('should return true for a valid IP address', () => { + expect(isValidIpv4({ ip: '192.168.0.1' })).to.equal(true); + expect(isValidIpv4({ ip: '10.0.0.1' })).to.equal(true); + }); + + it('should return false for an invalid IP address', () => { + expect(isValidIpv4({ ip: '256.168.0.1' })).to.equal(false); + expect(isValidIpv4({ ip: '192.168.0' })).to.equal(false); + expect(isValidIpv4({ ip: '192.168.0.1.2' })).to.equal(false); + expect(isValidIpv4({ ip: '192.168.0.1.' })).to.equal(false); + expect(isValidIpv4({ ip: '.192.168.0.1' })).to.equal(false); + expect(isValidIpv4({ ip: '192.168.0.a' })).to.equal(false); + }); + + it('should return false for crap as input', () => { + expect(isValidIpv4({ ip: '' })).to.equal(false); + expect(isValidIpv4({ ip: ' ' })).to.equal(false); + expect(isValidIpv4({ ip: 'foo' })).to.equal(false); + expect(isValidIpv4({ ip: '-1' })).to.equal(false); + expect(isValidIpv4({ ip: '0' })).to.equal(false); + }); + }); +}); diff --git a/src/tools/ipv4-address-converter/ipv4-address-converter.service.ts b/src/tools/ipv4-address-converter/ipv4-address-converter.service.ts new file mode 100644 index 0000000..ffd5d80 --- /dev/null +++ b/src/tools/ipv4-address-converter/ipv4-address-converter.service.ts @@ -0,0 +1,38 @@ +import _ from 'lodash'; + +export { ipv4ToInt, ipv4ToIpv6, isValidIpv4 }; + +function ipv4ToInt({ ip }: { ip: string }) { + if (!isValidIpv4({ ip })) { + return 0; + } + + return ip + .trim() + .split('.') + .reduce((acc, part, index) => acc + Number(part) * Math.pow(256, 3 - index), 0); +} + +function ipv4ToIpv6({ ip, prefix = '0000:0000:0000:0000:0000:ffff:' }: { ip: string; prefix?: string }) { + if (!isValidIpv4({ ip })) { + return ''; + } + + return ( + prefix + + _.chain(ip) + .trim() + .split('.') + .map((part) => parseInt(part).toString(16).padStart(2, '0')) + .chunk(2) + .map((blocks) => blocks.join('')) + .join(':') + .value() + ); +} + +function isValidIpv4({ ip }: { ip: string }) { + const cleanIp = ip.trim(); + + return /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/.test(cleanIp); +} diff --git a/src/tools/ipv4-address-converter/ipv4-address-converter.vue b/src/tools/ipv4-address-converter/ipv4-address-converter.vue new file mode 100644 index 0000000..2721b1a --- /dev/null +++ b/src/tools/ipv4-address-converter/ipv4-address-converter.vue @@ -0,0 +1,64 @@ +<template> + <div> + <n-form-item label="An ipv4 address:" v-bind="validationAttrs"> + <n-input v-model:value="rawIpAddress" placeholder="An ipv4 address..." /> + </n-form-item> + + <n-divider style="margin-top: 0" mt-0 /> + + <n-form-item + v-for="{ label, value } of convertedSections" + :key="label" + :label="label" + label-placement="left" + label-width="100" + > + <input-copyable + :value="validationAttrs.validationStatus === 'error' ? '' : value" + placeholder="Set a correct ipv4 address" + /> + </n-form-item> + </div> +</template> + +<script setup lang="ts"> +import { useValidation } from '@/composable/validation'; +import { convertBase } from '../integer-base-converter/integer-base-converter.model'; +import { ipv4ToInt, ipv4ToIpv6, isValidIpv4 } from './ipv4-address-converter.service'; + +const rawIpAddress = ref('192.168.1.1'); + +const convertedSections = computed(() => { + const ipInDecimal = ipv4ToInt({ ip: rawIpAddress.value }); + + return [ + { + label: 'Decimal : ', + value: String(ipInDecimal), + }, + { + label: 'Hexadecimal: ', + value: convertBase({ fromBase: 10, toBase: 16, value: String(ipInDecimal) }).toUpperCase(), + }, + { + label: 'Binary: ', + value: convertBase({ fromBase: 10, toBase: 2, value: String(ipInDecimal) }), + }, + { + label: 'Ipv6: ', + value: ipv4ToIpv6({ ip: rawIpAddress.value }), + }, + { + label: 'Ipv6 (short): ', + value: ipv4ToIpv6({ ip: rawIpAddress.value, prefix: '::ffff:' }), + }, + ]; +}); + +const { attrs: validationAttrs } = useValidation({ + source: rawIpAddress, + rules: [{ message: 'Invalid ipv4 address', validator: (ip) => isValidIpv4({ ip }) }], +}); +</script> + +<style lang="less" scoped></style> |