mirror of
https://github.com/Unkn0wnCat/data-toolbox-site.git
synced 2025-04-28 17:46:21 +02:00
Add IPv4SubnettingTool
This commit is contained in:
parent
9ae40093e1
commit
a078555835
9 changed files with 323 additions and 47 deletions
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "kevins-data-toolbox",
|
||||
"version": "2.3.1",
|
||||
"version": "2.4.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@loadable/component": "^5.15.0",
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
"categories": {
|
||||
"everything": "Alles",
|
||||
"cryptography": "Kryptografie",
|
||||
"encodings": "Kodierungen"
|
||||
"encodings": "Kodierungen",
|
||||
"networking": "Netzwerke"
|
||||
},
|
||||
"cryptography": {
|
||||
"common": {
|
||||
|
@ -33,27 +34,40 @@
|
|||
}
|
||||
},
|
||||
"encodings": {
|
||||
"common": {
|
||||
"encoded": "Kodiert",
|
||||
"decoded": "Dekodiert"
|
||||
},
|
||||
"base64": {
|
||||
"title": "Base64",
|
||||
"description": "<wikipedia>Base64-Codierung</wikipedia> wird oft genutzt um beliebige Binärdaten in pure Zeichenfolgen zu schreiben, indem die Daten auf 64 ASCII-Zeichen projeziert werden."
|
||||
},
|
||||
"numberbase": {
|
||||
"title": "Basis-Konverter",
|
||||
"description": "Basis-Konverter konvertiert Zahlen in eine andere Basis (z.B. Binär, Hexadezimal, etc.)",
|
||||
"decimal": "Dezimal",
|
||||
"binary": "Binär",
|
||||
"octal": "Oktal",
|
||||
"hexadecimal": "Hexadezimal",
|
||||
"nanWarning": "Die Eingabe ist keine gültige Zahl!"
|
||||
},
|
||||
"urlencode": {
|
||||
"title": "URL-Kodierung",
|
||||
"description": "Kodiere und dekodiere <wikipedia>URL-kodierte (or Prozent-kodierte)</wikipedia> Zeichenfolgen."
|
||||
}
|
||||
"common": {
|
||||
"encoded": "Kodiert",
|
||||
"decoded": "Dekodiert"
|
||||
},
|
||||
"base64": {
|
||||
"title": "Base64",
|
||||
"description": "<wikipedia>Base64-Codierung</wikipedia> wird oft genutzt um beliebige Binärdaten in pure Zeichenfolgen zu schreiben, indem die Daten auf 64 ASCII-Zeichen projeziert werden."
|
||||
},
|
||||
"numberbase": {
|
||||
"title": "Basis-Konverter",
|
||||
"description": "Basis-Konverter konvertiert Zahlen in eine andere Basis (z.B. Binär, Hexadezimal, etc.)",
|
||||
"decimal": "Dezimal",
|
||||
"binary": "Binär",
|
||||
"octal": "Oktal",
|
||||
"hexadecimal": "Hexadezimal",
|
||||
"nanWarning": "Die Eingabe ist keine gültige Zahl!"
|
||||
},
|
||||
"urlencode": {
|
||||
"title": "URL-Kodierung",
|
||||
"description": "Kodiere und dekodiere <wikipedia>URL-kodierte (or Prozent-kodierte)</wikipedia> Zeichenfolgen."
|
||||
}
|
||||
},
|
||||
"networking": {
|
||||
"ipv4subnetting": {
|
||||
"title": "IPv4-Subnetzrechner",
|
||||
"description": "Der IPv4-Subnetzrechner visualisiert IPv4-Subnetze und berechnet die erste und letzte Adresse aus einem Subnetz nach CIDR-Notation."
|
||||
},
|
||||
"common": {
|
||||
"ipv4addr": "IPv4-Adresse",
|
||||
"firstAddr": "Erste Adresse",
|
||||
"lastAddr": "Letzte Adresse",
|
||||
"subnetMask": "Subnetzmaske",
|
||||
"binary": "Binär"
|
||||
}
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
@ -18,7 +18,8 @@
|
|||
"categories": {
|
||||
"everything": "Everything",
|
||||
"cryptography": "Cryptography",
|
||||
"encodings": "Encodings"
|
||||
"encodings": "Encodings",
|
||||
"networking": "Networking"
|
||||
},
|
||||
"cryptography": {
|
||||
"common": {
|
||||
|
@ -33,27 +34,40 @@
|
|||
}
|
||||
},
|
||||
"encodings": {
|
||||
"common": {
|
||||
"encoded": "Encoded",
|
||||
"decoded": "Decoded"
|
||||
},
|
||||
"base64": {
|
||||
"title": "Base64",
|
||||
"description": "<wikipedia>Base64-encoding</wikipedia> is commonly used for storing arbitrary binary data in pure strings, by mapping it to 64 ASCII characters."
|
||||
},
|
||||
"numberbase": {
|
||||
"title": "Base Converter",
|
||||
"description": "Convert between decimal, binary, octal and hexadecimal numbers.",
|
||||
"decimal": "Decimal",
|
||||
"binary": "Binary",
|
||||
"octal": "Octal",
|
||||
"hexadecimal": "Hexadecimal",
|
||||
"nanWarning": "The input is not a valid number!"
|
||||
},
|
||||
"urlencode": {
|
||||
"title": "URL-Encoding",
|
||||
"description": "Encode and decode strings to and from <wikipedia>URL-encoding (or Percent-encoding)</wikipedia>."
|
||||
}
|
||||
"common": {
|
||||
"encoded": "Encoded",
|
||||
"decoded": "Decoded"
|
||||
},
|
||||
"base64": {
|
||||
"title": "Base64",
|
||||
"description": "<wikipedia>Base64-encoding</wikipedia> is commonly used for storing arbitrary binary data in pure strings, by mapping it to 64 ASCII characters."
|
||||
},
|
||||
"numberbase": {
|
||||
"title": "Base Converter",
|
||||
"description": "Convert between decimal, binary, octal and hexadecimal numbers.",
|
||||
"decimal": "Decimal",
|
||||
"binary": "Binary",
|
||||
"octal": "Octal",
|
||||
"hexadecimal": "Hexadecimal",
|
||||
"nanWarning": "The input is not a valid number!"
|
||||
},
|
||||
"urlencode": {
|
||||
"title": "URL-Encoding",
|
||||
"description": "Encode and decode strings to and from <wikipedia>URL-encoding (or Percent-encoding)</wikipedia>."
|
||||
}
|
||||
},
|
||||
"networking": {
|
||||
"ipv4subnetting": {
|
||||
"title": "IPv4 Subnetter",
|
||||
"description": "The IPv4 subnetter visualizes IPv4 subnets and calculates the first and last address from a CIDR-notated subnet."
|
||||
},
|
||||
"common": {
|
||||
"ipv4addr": "IPv4 address",
|
||||
"firstAddr": "First address",
|
||||
"lastAddr": "Last address",
|
||||
"subnetMask": "Subnet mask",
|
||||
"binary": "Binary"
|
||||
}
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import {Lock, Binary, List} from 'lucide-react';
|
||||
import {Lock, Binary, List, Network} from 'lucide-react';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
|
@ -31,6 +31,7 @@ const ToolsPage = () => {
|
|||
<LinkBox to={"/tools"} text={t("tools.categories.everything")} icon={<List/>} small={true} highlight={category == null} />
|
||||
<LinkBox to={"/tools/cryptography"} text={t("tools.categories.cryptography")} icon={<Lock/>} small={true} highlight={category === "cryptography"} />
|
||||
<LinkBox to={"/tools/encodings"} text={t("tools.categories.encodings")} icon={<Binary/>} small={true} highlight={category === "encodings"} />
|
||||
<LinkBox to={"/tools/networking"} text={t("tools.categories.networking")} icon={<Network/>} small={true} highlight={category === "networking"} />
|
||||
{/*<LinkBox to={"/tools/osm"} text={"OSM"} icon={icons["Map"]} small={true} highlight={category === "osm"} />*/}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ const RotTool = prerenderedLoadable(() => import('./cyphers_and_cryptography/rot
|
|||
const Base64Tool = prerenderedLoadable(() => import('./encodings/base64/Base64Tool'));
|
||||
const NumberBaseTool = prerenderedLoadable(() => import('./encodings/numberbase/NumberBaseTool'));
|
||||
const URLEncodeTool = prerenderedLoadable(() => import('./encodings/urlencode/URLEncodeTool'));
|
||||
const IPv4SubnettingTool = prerenderedLoadable(() => import('./networking/ipv4subnetting/IPv4SubnettingTool'));
|
||||
|
||||
type ErrorBoundaryProps = {
|
||||
resetFunction: () => void
|
||||
|
@ -76,6 +77,9 @@ const ToolLoader = () => {
|
|||
case "urlencode":
|
||||
return <ToolErrorBoundary resetFunction={forceReset} key={key}><URLEncodeTool/></ToolErrorBoundary>;
|
||||
|
||||
case "ipv4subnetting":
|
||||
return <ToolErrorBoundary resetFunction={forceReset} key={key}><IPv4SubnettingTool/></ToolErrorBoundary>;
|
||||
|
||||
default:
|
||||
return <NotFoundPage/>;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
@import "../../../common";
|
||||
|
||||
.fakeLabel {
|
||||
display: block;
|
||||
|
||||
margin-top: $layoutPadding;
|
||||
margin-bottom: (-$layoutPadding + 5px);
|
||||
}
|
||||
|
||||
.fakeField {
|
||||
@include boxStyle;
|
||||
|
||||
display: block;
|
||||
|
||||
width: 368px;
|
||||
opacity: .75;
|
||||
background: rgba(0, 0, 0, .25);
|
||||
|
||||
@media(prefers-color-scheme: dark) {
|
||||
background: rgba(255, 255, 255, .025);
|
||||
}
|
||||
}
|
||||
|
||||
.combiInput {
|
||||
@include boxStyle;
|
||||
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
padding: 0;
|
||||
width: fit-content;
|
||||
overflow: hidden;
|
||||
|
||||
|
||||
input {
|
||||
@include boxStyle;
|
||||
margin: 0;
|
||||
width: 70px;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
background: transparent !important;
|
||||
box-shadow: none;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
7
src/tools/networking/ipv4subnetting/IPv4SubnettingTool.module.scss.d.ts
vendored
Normal file
7
src/tools/networking/ipv4subnetting/IPv4SubnettingTool.module.scss.d.ts
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
export const center: string;
|
||||
export const combiInput: string;
|
||||
export const fakeField: string;
|
||||
export const fakeLabel: string;
|
||||
export const flexList: string;
|
||||
export const layoutBox: string;
|
||||
export const title: string;
|
183
src/tools/networking/ipv4subnetting/IPv4SubnettingTool.tsx
Normal file
183
src/tools/networking/ipv4subnetting/IPv4SubnettingTool.tsx
Normal file
|
@ -0,0 +1,183 @@
|
|||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { useTranslation, Trans } from "react-i18next";
|
||||
import * as styles from "./IPv4SubnettingTool.module.scss"
|
||||
import { Helmet } from "react-helmet";
|
||||
|
||||
const intToIPv4String = (ip: number): string => {
|
||||
let out = ""
|
||||
|
||||
for (let group = 0; group < 4; group++) {
|
||||
let groupBin = ip & 0xff
|
||||
|
||||
out = groupBin.toString()+"."+out
|
||||
|
||||
ip >>= 8;
|
||||
}
|
||||
|
||||
return out.substring(0, out.length-1)
|
||||
}
|
||||
|
||||
const IPv4SubnettingTool = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
let [ipPart1, setIPPart1] = useState("");
|
||||
let [ipPart2, setIPPart2] = useState("");
|
||||
let [ipPart3, setIPPart3] = useState("");
|
||||
let [ipPart4, setIPPart4] = useState("");
|
||||
let [subnet, setSubnet] = useState("");
|
||||
|
||||
let ipInput1 = useRef<HTMLInputElement>(null)
|
||||
let ipInput2 = useRef<HTMLInputElement>(null)
|
||||
let ipInput3 = useRef<HTMLInputElement>(null)
|
||||
let ipInput4 = useRef<HTMLInputElement>(null)
|
||||
let subnetInput = useRef<HTMLInputElement>(null)
|
||||
|
||||
let [ipBinary, setIpBinary] = useState<number|undefined>(undefined);
|
||||
let [subnetNumber, setSubnetMaskNumber] = useState<number|undefined>(undefined);
|
||||
let [subnetBinary, setSubnetMaskBinaryString] = useState<string|undefined>(undefined);
|
||||
let [subnetMask, setSubnetMask] = useState<number|undefined>(undefined);
|
||||
let [firstAddr, setFirstAddr] = useState<number|undefined>(undefined);
|
||||
let [lastAddr, setLastAddr] = useState<number|undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
let myIpPart1 = ipPart1;
|
||||
let myIpPart2 = ipPart2;
|
||||
let myIpPart3 = ipPart3;
|
||||
let myIpPart4 = ipPart4;
|
||||
let mySubnet = subnet;
|
||||
|
||||
|
||||
if(myIpPart1.indexOf(".") !== -1) {
|
||||
let split = myIpPart1.split(".")
|
||||
myIpPart1 = split.shift()!
|
||||
myIpPart2 = split.join(".")
|
||||
ipInput2.current?.focus()
|
||||
}
|
||||
if(myIpPart2.indexOf(".") !== -1) {
|
||||
let split = myIpPart2.split(".")
|
||||
myIpPart2 = split.shift()!
|
||||
myIpPart3 = split.join(".")
|
||||
ipInput3.current?.focus()
|
||||
}
|
||||
if(myIpPart3.indexOf(".") !== -1) {
|
||||
let split = myIpPart3.split(".")
|
||||
myIpPart3 = split.shift()!
|
||||
myIpPart4 = split.join(".")
|
||||
ipInput4.current?.focus()
|
||||
}
|
||||
if(myIpPart4.indexOf("/") !== -1) {
|
||||
let split = myIpPart4.split("/")
|
||||
myIpPart4 = split.shift()!
|
||||
mySubnet = split.join("/")
|
||||
subnetInput.current?.focus()
|
||||
}
|
||||
if(myIpPart4.indexOf(".") !== -1) {
|
||||
let split = myIpPart4.split(".")
|
||||
myIpPart4 = split.shift()!
|
||||
mySubnet = split.join(".")
|
||||
subnetInput.current?.focus()
|
||||
}
|
||||
|
||||
|
||||
let ipPart1Num = parseInt(myIpPart1);
|
||||
let ipPart2Num = parseInt(myIpPart2);
|
||||
let ipPart3Num = parseInt(myIpPart3);
|
||||
let ipPart4Num = parseInt(myIpPart4);
|
||||
let subnetNum = parseInt(mySubnet);
|
||||
|
||||
|
||||
|
||||
|
||||
if(!isNaN(ipPart1Num)) setIPPart1(ipPart1Num.toString());
|
||||
if(!isNaN(ipPart2Num)) setIPPart2(ipPart2Num.toString());
|
||||
if(!isNaN(ipPart3Num)) setIPPart3(ipPart3Num.toString());
|
||||
if(!isNaN(ipPart4Num)) setIPPart4(ipPart4Num.toString());
|
||||
if(!isNaN(subnetNum)) setSubnet(subnetNum.toString());
|
||||
|
||||
setIpBinary(undefined);
|
||||
setFirstAddr(undefined);
|
||||
setLastAddr(undefined);
|
||||
setSubnetMaskBinaryString(undefined);
|
||||
setSubnetMaskNumber(undefined);
|
||||
setSubnetMask(undefined);
|
||||
|
||||
if(!isNaN(ipPart1Num) && !isNaN(ipPart2Num) && !isNaN(ipPart3Num) && !isNaN(ipPart4Num)) {
|
||||
let ipBinary = ipPart1Num * Math.pow(2, 24) + ipPart2Num * Math.pow(2, 16) + ipPart3Num * Math.pow(2, 8) + ipPart4Num;
|
||||
setIpBinary(ipBinary);
|
||||
|
||||
if (!isNaN(subnetNum)) {
|
||||
setSubnetMaskNumber(subnetNum);
|
||||
|
||||
|
||||
let subnetMaskBinary = new Uint32Array(1);
|
||||
|
||||
for (let index = 0; index < 32 - subnetNum; index++) {
|
||||
subnetMaskBinary[0] = (subnetMaskBinary[0] << 1) | 0b1;
|
||||
}
|
||||
|
||||
subnetMaskBinary[0] ^= 0xffffffff
|
||||
|
||||
setSubnetMaskBinaryString(subnetMaskBinary[0].toString(2))
|
||||
setSubnetMask(subnetMaskBinary[0])
|
||||
|
||||
setFirstAddr(ipBinary & subnetMaskBinary[0])
|
||||
setLastAddr(ipBinary | (subnetMaskBinary[0] ^ 0xffffffff))
|
||||
}
|
||||
}
|
||||
}, [ipPart1, ipPart2, ipPart3, ipPart4, subnet])
|
||||
|
||||
return (
|
||||
<main>
|
||||
<Helmet>
|
||||
<title>{t("tools.networking.ipv4subnetting.title")} | {t("site.title")}</title>
|
||||
<meta name="keywords" content="subnetting, networking, ipv4, ip4, ip, internet protocol, subnet, subnetter, netmask, tool" />
|
||||
</Helmet>
|
||||
<div className={styles.layoutBox}>
|
||||
<h1>{t("tools.networking.ipv4subnetting.title")}</h1>
|
||||
|
||||
<p><Trans i18nKey={"tools.networking.ipv4subnetting.description"} components={{}} /></p>
|
||||
|
||||
<label htmlFor="ipv4-input">{t("tools.networking.common.ipv4addr")}</label>
|
||||
<div className={styles.combiInput}>
|
||||
<input ref={ipInput1} id="ipv4-input" placeholder={"192"} onChange={(e) => {setIPPart1(e.currentTarget.value); if((e.currentTarget.value.length >= 3 && e.currentTarget.value.length > ipPart1.length) || e.currentTarget.value[e.currentTarget.value.length - 1] === ".") ipInput2.current?.focus()}} value={ipPart1} />
|
||||
<span>.</span>
|
||||
<input ref={ipInput2} id="ipv4-input2" placeholder={"168"} onChange={(e) => {setIPPart2(e.currentTarget.value); if((e.currentTarget.value.length >= 3 && e.currentTarget.value.length > ipPart2.length) || e.currentTarget.value[e.currentTarget.value.length - 1] === ".") ipInput3.current?.focus()}} value={ipPart2} />
|
||||
<span>.</span>
|
||||
<input ref={ipInput3} id="ipv4-input3" placeholder={"178"} onChange={(e) => {setIPPart3(e.currentTarget.value); if((e.currentTarget.value.length >= 3 && e.currentTarget.value.length > ipPart3.length) || e.currentTarget.value[e.currentTarget.value.length - 1] === ".") ipInput4.current?.focus()}} value={ipPart3} />
|
||||
<span>.</span>
|
||||
<input ref={ipInput4} id="ipv4-input4" placeholder={"1"} onChange={(e) => {setIPPart4(e.currentTarget.value); if((e.currentTarget.value.length >= 3 && e.currentTarget.value.length > ipPart4.length) || e.currentTarget.value[e.currentTarget.value.length - 1] === "/" || e.currentTarget.value[e.currentTarget.value.length - 1] === ".") subnetInput.current?.focus()}} value={ipPart4} />
|
||||
<span>/</span>
|
||||
<input ref={subnetInput} id="subnet-input" placeholder={"24"} onChange={(e) => {setSubnet(e.currentTarget.value);}} value={subnet} />
|
||||
</div>
|
||||
|
||||
<span className={styles.fakeLabel}>{t("tools.networking.common.subnetMask")}</span>
|
||||
<span className={styles.fakeField}>{subnetMask ? intToIPv4String(subnetMask) : "???"}</span>
|
||||
|
||||
<span className={styles.fakeLabel}>{t("tools.networking.common.firstAddr")}</span>
|
||||
<span className={styles.fakeField}>{firstAddr ? intToIPv4String(firstAddr) : "???"}</span>
|
||||
|
||||
<span className={styles.fakeLabel}>{t("tools.networking.common.lastAddr")}</span>
|
||||
<span className={styles.fakeField}>{lastAddr ? intToIPv4String(lastAddr) : "???"}</span>
|
||||
|
||||
<span className={styles.fakeLabel}>{t("tools.networking.common.ipv4addr")} ({t("tools.networking.common.binary")})</span>
|
||||
<span className={styles.fakeField}>
|
||||
{ipBinary ? ipBinary.toString(2).padStart(32, "0").split("").map((bit, index) => {
|
||||
return <span style={{color: (index) >= (subnetNumber||32) ? "red" : undefined}} key={"bit"+index}>{bit}</span>
|
||||
}) : "???"}
|
||||
</span>
|
||||
|
||||
<span className={styles.fakeLabel}>{t("tools.networking.common.subnetMask")} ({t("tools.networking.common.binary")})</span>
|
||||
<span className={styles.fakeField}>
|
||||
{subnetBinary ? subnetBinary.padStart(32, "0").split("").map((bit, index) => {
|
||||
return <span key={"maskbit"+index}>{bit}</span>
|
||||
}) : "???"}
|
||||
</span>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
export default IPv4SubnettingTool;
|
|
@ -1,4 +1,4 @@
|
|||
import {Smile, PlusSquare, Binary, Hash, Globe} from "lucide-react"
|
||||
import {Smile, PlusSquare, Binary, Hash, Globe, Network} from "lucide-react"
|
||||
|
||||
const tools = [
|
||||
{
|
||||
|
@ -44,6 +44,15 @@ const tools = [
|
|||
"category": "encodings",
|
||||
"hidden": false,
|
||||
"keywords": "URL, urlencode, urldecode, URI, uriencode, uridecode, encoding, decoding, encoder, decoder, tool"
|
||||
},
|
||||
{
|
||||
"name": "tools.networking.ipv4subnetting.title",
|
||||
"external": false,
|
||||
"urlname": "ipv4subnetting",
|
||||
"icon": Network,
|
||||
"category": "networking",
|
||||
"hidden": false,
|
||||
"keywords": "subnetting, networking, ipv4, ip4, ip, internet protocol, subnet, subnetter, netmask, tool"
|
||||
}
|
||||
]
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue