Add Linux Permission-Tool

This commit is contained in:
Kevin Kandlbinder 2022-09-03 20:58:58 +02:00
parent 50fe48826f
commit 7a30770f73
9 changed files with 191 additions and 6 deletions

View file

@ -19,7 +19,7 @@
"i18next-browser-languagedetector": "^6.1.0",
"i18next-http-backend": "^1.2.1",
"lodash": "^4.17.21",
"lucide-react": "^0.35.0",
"lucide-react": "^0.88.0",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-helmet": "^6.1.0",

View file

@ -55,6 +55,13 @@
"urlencode": {
"title": "URL-Kodierung",
"description": "Kodiere und dekodiere <wikipedia>URL-kodierte (or Prozent-kodierte)</wikipedia> Zeichenfolgen."
},
"linux_permissions": {
"title": "Linux Berechtigungen",
"description": "Linux (und andere UNIX-artige Systeme) verwenden 4 Gruppen von je 3 Bits um grundlegende Dateiberechtigungen darzustellen. Die erste Gruppe setzt die Flags set UID, set GID, und sticky. Die letzten 3 Gruppen setzen die Dateiberechtigunen für den besitzenden Benutzer, die besitzende Gruppe, und jeden anderen in dieser Reihenfolge. Die 3 Bits stehen hierbei jeweils für Lesen, Schreiben, und Ausführen. Bei Ordnern steht Ausführen für Öffnen bzw. hinein Navigieren.",
"octal": "Oktal-Wert",
"bits": "Berechtigungsbits",
"umask": "umask-Wert"
}
},
"networking": {

View file

@ -55,6 +55,13 @@
"urlencode": {
"title": "URL-Encoding",
"description": "Encode and decode strings to and from <wikipedia>URL-encoding (or Percent-encoding)</wikipedia>."
},
"linux_permissions": {
"title": "Linux File-Permissions",
"description": "Linux (or other UNIX-ish systems) use 4 groups of 3 bits to represent basic file permissions. The first group sets the flags set UID, set GID, and sticky. The last three groups set the file-permissions for the owner user, the owner group, and everyone else in that order. Here the 3 bits stand for read, write, and execute. On directories execute stands for open / navigate into.",
"octal": "Octal Value",
"bits": "Permission-Bits",
"umask": "umask-Value"
}
},
"networking": {

View file

@ -16,6 +16,7 @@ const Base64Tool = prerenderedLoadable(() => import('./encodings/base64/Base64To
const NumberBaseTool = prerenderedLoadable(() => import('./encodings/numberbase/NumberBaseTool'));
const URLEncodeTool = prerenderedLoadable(() => import('./encodings/urlencode/URLEncodeTool'));
const IPv4SubnettingTool = prerenderedLoadable(() => import('./networking/ipv4subnetting/IPv4SubnettingTool'));
const LinuxPermissionsTool = prerenderedLoadable(() => import('./encodings/linux_permissions/LinuxPermissionsTool'));
type ErrorBoundaryProps = {
resetFunction: () => void
@ -80,6 +81,9 @@ const ToolLoader = () => {
case "ipv4subnetting":
return <ToolErrorBoundary resetFunction={forceReset} key={key}><IPv4SubnettingTool/></ToolErrorBoundary>;
case "linux_permissions":
return <ToolErrorBoundary resetFunction={forceReset} key={key}><LinuxPermissionsTool/></ToolErrorBoundary>;
default:
return <NotFoundPage/>;
}

View file

@ -0,0 +1,10 @@
@import "../../../common";
.inputTable {
@include boxStyle;
border-collapse: separate;
.gap {
width: 20px;
}
}

View file

@ -0,0 +1,6 @@
export const center: string;
export const flexList: string;
export const gap: string;
export const inputTable: string;
export const layoutBox: string;
export const title: string;

View file

@ -0,0 +1,142 @@
import React, { useEffect, useState } from "react";
import { useTranslation, Trans } from "react-i18next";
import * as styles from "./LinuxPermissionsTool.module.scss"
import { Helmet } from "react-helmet";
const LinuxPermissionsTool = () => {
const { t } = useTranslation();
let [octal, setOctal] = useState("0766");
let [umask, setUmask] = useState("");
let [octet1, setOctet1] = useState(0)
let [octet2, setOctet2] = useState(0)
let [octet3, setOctet3] = useState(0)
let [octet4, setOctet4] = useState(0)
let [input, setInput] = useState<"octal"|"checkbox"|"umask">("octal")
useEffect(() => {
if(input === "octal") {
let digits = [0, 0, 0, 0];
const baseOffset = 4 - octal.length;
for(let i = 0; i < digits.length && i+baseOffset < 4; i++) {
digits[i+baseOffset] = parseInt(octal.charAt(i), 8)
}
setUmask(`0${digits[1]^0b111}${digits[2]^0b111}${digits[3]^0b111}`)
setOctet1(digits[0])
setOctet2(digits[1])
setOctet3(digits[2])
setOctet4(digits[3])
}
if(input === "umask") {
let digits = [0, 0, 0, 0];
const baseOffset = 4 - umask.length;
for(let i = 0; i < digits.length && i+baseOffset < 4; i++) {
digits[i+baseOffset] = parseInt(umask.charAt(i), 8)
}
setOctal(`0${digits[1]^0b111}${digits[2]^0b111}${digits[3]^0b111}`)
setOctet1(digits[0]^0b111)
setOctet2(digits[1]^0b111)
setOctet3(digits[2]^0b111)
setOctet4(digits[3]^0b111)
}
if(input === "checkbox") {
setOctal(`${octet1}${octet2}${octet3}${octet4}`)
setUmask(`0${octet2^0b111}${octet3^0b111}${octet4^0b111}`)
}
}, [octal, input, octet1, octet2, octet3, octet4, umask])
return (
<main>
<Helmet>
<title>{t("tools.encodings.linux_permissions.title")} | {t("site.title")}</title>
<meta name="keywords" content="Linux, Permissions, octet, octets, rwx, encoding, decoding, encoder, decoder, base, 64, binary, tool" />
</Helmet>
<div className={styles.layoutBox}>
<h1>{t("tools.encodings.linux_permissions.title")}</h1>
<p><Trans i18nKey={"tools.encodings.linux_permissions.description"} components={{pre: <pre/>}} /></p>
<label htmlFor="octal-input">{t("tools.encodings.linux_permissions.octal")}</label>
<input id="octal-input" type="text" placeholder={t("tools.encodings.linux_permissions.octal")} onChange={(e) => {setOctal(e.currentTarget.value); setInput("octal")}} value={octal} />
<label htmlFor="table-input">{t("tools.encodings.linux_permissions.bits")}</label>
<table className={styles.inputTable} id="table-input">
<colgroup>
<col span={3}/>
<col span={1} className={styles.gap}/>
<col span={3}/>
<col span={1} className={styles.gap}/>
<col span={3}/>
<col span={1} className={styles.gap}/>
<col span={3}/>
</colgroup>
<thead>
<tr>
<th colSpan={3}>Flags</th>
<th></th>
<th colSpan={3}>User</th>
<th></th>
<th colSpan={3}>Group</th>
<th></th>
<th colSpan={3}>Other</th>
</tr>
<tr>
<th title="Set UID">U</th>
<th title="Set GID">G</th>
<th title="Sticky">S</th>
<th></th>
<th title="Read">R</th>
<th title="Write">W</th>
<th title="Execute">X</th>
<th></th>
<th title="Read">R</th>
<th title="Write">W</th>
<th title="Execute">X</th>
<th></th>
<th title="Read">R</th>
<th title="Write">W</th>
<th title="Execute">X</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked={(octet1 & 0b100) === 0b100} onChange={() => {setOctet1(prev => prev ^ 0b100); setInput("checkbox")}}/></td>
<td><input type="checkbox" checked={(octet1 & 0b010) === 0b010} onChange={() => {setOctet1(prev => prev ^ 0b010); setInput("checkbox")}}/></td>
<td><input type="checkbox" checked={(octet1 & 0b001) === 0b001} onChange={() => {setOctet1(prev => prev ^ 0b001); setInput("checkbox")}}/></td>
<td></td>
<td><input type="checkbox" checked={(octet2 & 0b100) === 0b100} onChange={() => {setOctet2(prev => prev ^ 0b100); setInput("checkbox")}}/></td>
<td><input type="checkbox" checked={(octet2 & 0b010) === 0b010} onChange={() => {setOctet2(prev => prev ^ 0b010); setInput("checkbox")}}/></td>
<td><input type="checkbox" checked={(octet2 & 0b001) === 0b001} onChange={() => {setOctet2(prev => prev ^ 0b001); setInput("checkbox")}}/></td>
<td></td>
<td><input type="checkbox" checked={(octet3 & 0b100) === 0b100} onChange={() => {setOctet3(prev => prev ^ 0b100); setInput("checkbox")}}/></td>
<td><input type="checkbox" checked={(octet3 & 0b010) === 0b010} onChange={() => {setOctet3(prev => prev ^ 0b010); setInput("checkbox")}}/></td>
<td><input type="checkbox" checked={(octet3 & 0b001) === 0b001} onChange={() => {setOctet3(prev => prev ^ 0b001); setInput("checkbox")}}/></td>
<td></td>
<td><input type="checkbox" checked={(octet4 & 0b100) === 0b100} onChange={() => {setOctet4(prev => prev ^ 0b100); setInput("checkbox")}}/></td>
<td><input type="checkbox" checked={(octet4 & 0b010) === 0b010} onChange={() => {setOctet4(prev => prev ^ 0b010); setInput("checkbox")}}/></td>
<td><input type="checkbox" checked={(octet4 & 0b001) === 0b001} onChange={() => {setOctet4(prev => prev ^ 0b001); setInput("checkbox")}}/></td>
</tr>
</tbody>
</table>
<label htmlFor="umask-input">{t("tools.encodings.linux_permissions.umask")}</label>
<input id="umask-input" type="text" placeholder={t("tools.encodings.linux_permissions.umask")} onChange={(e) => {setUmask(e.currentTarget.value); setInput("umask")}} value={umask} />
</div>
</main>
)
}
export default LinuxPermissionsTool;

View file

@ -1,4 +1,4 @@
import {Smile, PlusSquare, Binary, Hash, Globe, Network} from "lucide-react"
import {Smile, PlusSquare, Binary, Hash, Globe, Network, FileCog} from "lucide-react"
const tools = [
{
@ -53,6 +53,15 @@ const tools = [
"category": "networking",
"hidden": false,
"keywords": "subnetting, networking, ipv4, ip4, ip, internet protocol, subnet, subnetter, netmask, tool"
},
{
"name": "tools.encodings.linux_permissions.title",
"external": false,
"urlname": "linux_permissions",
"icon": FileCog,
"category": "encodings",
"hidden": false,
"keywords": "Linux, Permissions, octet, octets, rwx, encoding, decoding, encoder, decoder, base, 64, binary, tool"
}
]

View file

@ -7494,10 +7494,10 @@ lru-cache@^6.0.0:
dependencies:
yallist "^4.0.0"
lucide-react@^0.35.0:
version "0.35.0"
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.35.0.tgz#73526e95fca41c9d937a949f908661b847d1fc5d"
integrity sha512-hxhpRRFRt9GGfgjPDDlYeTGQtW0Znj5aTUkbbdZNco0R89ClTE604GQpWOkDWNof8cWfMMlcVrw58tGdpOQKXg==
lucide-react@^0.88.0:
version "0.88.0"
resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.88.0.tgz#6269fad9e52cfbae036b7b4b95e04335f040bb6d"
integrity sha512-DiLZ0uqqt4Qpe7bc+RvJMMI7z3gWlMOnst+TtNFUH6XfQ12APMQDx+/fHsmMlIkyCs/pPo3UKZpYbZ5i1iMOuA==
lz-string@^1.4.4:
version "1.4.4"