Compare commits

..

3 Commits

Author SHA1 Message Date
6d676d5221 Added html-head.php 2025-06-25 17:48:52 +02:00
db02992ee9 Added tools 2025-06-25 17:48:30 +02:00
9ec73e7e86 Added studium 2025-06-25 17:48:22 +02:00
14 changed files with 1076 additions and 0 deletions

35
html-head.php Normal file
View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="de" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="author" content="Elias Fink">
<meta name="copyright" content="Copyright © <?php echo date("Y"); ?> Elias Fink">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, nofollow">
<link rel="shortcut icon" href="https://static.eliasfink.de/img/favicons/favicon.ico">
<link rel="manifest" href="https://static.eliasfink.de/img/favicons/site.webmanifest">
<link rel="apple-touch-icon" sizes="180x180" href="https://static.eliasfink.de/img/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="https://static.eliasfink.de/img/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="https://static.eliasfink.de/img/favicons/favicon-16x16.png">
<meta name="msapplication-config" content="https://static.eliasfink.de/img/favicons/browserconfig.xml">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="theme-color" content="#ffffff">
<style>
:root {
--blue-1: #001A33;
--blue-2: #004D99;
--blue-3: #0080FF;
--blue-4: #66B3FF;
--blue-5: #CCE6FF;
--grey-1: #161A1D;
--grey-2: #434D56;
--grey-3: #708090;
--grey-4: #A9B3BC;
--grey-5: #E2E6E9;
}
</style>

BIN
studium/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

0
studium/index.html Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,12 @@
<svg id="ef-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
<circle cx="500" cy="500" r="500" fill="#FFFFFF"/>
<g fill="#0080FF">
<rect x="430" y="240" width="50" height="520"/>
<rect x="190" y="240" width="265" height="50" />
<rect x="190" y="475" width="265" height="50" />
<rect x="190" y="710" width="265" height="50" />
<rect x="520" y="240" width="50" height="520"/>
<rect x="545" y="240" width="265" height="50" />
<rect x="545" y="475" width="265" height="50" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 570 B

View File

@@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="1000"
height="100"
viewBox="0 0 264.58333 26.458333"
version="1.1"
id="svg5"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
sodipodi:docname="symbols.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="px"
showgrid="true"
units="px"
gridtolerance="10"
inkscape:zoom="4.6726229"
inkscape:cx="918.43492"
inkscape:cy="46.440726"
inkscape:window-width="1920"
inkscape:window-height="1057"
inkscape:window-x="1016"
inkscape:window-y="1"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
<inkscape:grid
type="xygrid"
id="grid824"
empspacing="100" />
</sodipodi:namedview>
<defs
id="defs2">
<linearGradient
inkscape:collect="always"
id="linearGradient17492">
<stop
style="stop-color:#fffaff;stop-opacity:1"
offset="0"
id="stop17488" />
<stop
style="stop-color:#000000;stop-opacity:1"
offset="1"
id="stop17490" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient17492"
id="radialGradient17534"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.01185507,-0.00474077,0.00509163,0.01253756,245.5889,24.86303)"
cx="684.98218"
cy="-755.83978"
fx="684.98218"
fy="-755.83978"
r="399.74589" />
</defs>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
style="font-weight:bold;font-size:25.4px;line-height:15.875px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono Bold';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="5.4673328"
y="23.171078"
id="text2764"><tspan
sodipodi:role="line"
id="tspan2762"
style="font-size:25.4px;stroke-width:0.264583"
x="5.4673328"
y="23.171078">1</tspan></text>
<text
xml:space="preserve"
style="font-weight:bold;font-size:25.4px;line-height:15.875px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono Bold';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="31.925665"
y="23.171078"
id="text2764-6"><tspan
sodipodi:role="line"
id="tspan2762-7"
style="font-size:25.4px;stroke-width:0.264583"
x="31.925665"
y="23.171078">2</tspan></text>
<text
xml:space="preserve"
style="font-weight:bold;font-size:25.4px;line-height:15.875px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono Bold';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="58.383999"
y="23.171078"
id="text2764-4"><tspan
sodipodi:role="line"
id="tspan2762-6"
style="font-size:25.4px;stroke-width:0.264583"
x="58.383999"
y="23.171078">3</tspan></text>
<text
xml:space="preserve"
style="font-weight:bold;font-size:25.4px;line-height:15.875px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono Bold';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="84.581985"
y="23.171078"
id="text2764-67"><tspan
sodipodi:role="line"
id="tspan2762-3"
style="font-size:25.4px;stroke-width:0.264583"
x="84.581985"
y="23.171078">4</tspan></text>
<text
xml:space="preserve"
style="font-weight:bold;font-size:25.4px;line-height:15.875px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono Bold';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="137.75899"
y="23.171078"
id="text2764-9"><tspan
sodipodi:role="line"
id="tspan2762-2"
style="font-size:25.4px;stroke-width:0.264583"
x="137.75899"
y="23.171078">6</tspan></text>
<text
xml:space="preserve"
style="font-weight:bold;font-size:25.4px;line-height:15.875px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono Bold';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="112.24477"
y="23.171078"
id="text2764-5"><tspan
sodipodi:role="line"
id="tspan2762-0"
style="font-size:25.4px;stroke-width:0.264583"
x="112.24477"
y="23.171078">5</tspan></text>
<text
xml:space="preserve"
style="font-weight:bold;font-size:25.4px;line-height:15.875px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono Bold';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="164.21733"
y="23.171078"
id="text2764-8"><tspan
sodipodi:role="line"
id="tspan2762-37"
style="font-size:25.4px;stroke-width:0.264583"
x="164.21733"
y="23.171078">7</tspan></text>
<text
xml:space="preserve"
style="font-weight:bold;font-size:25.4px;line-height:15.875px;font-family:'DejaVu Sans Mono';-inkscape-font-specification:'DejaVu Sans Mono Bold';letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="190.67566"
y="23.171078"
id="text2764-56"><tspan
sodipodi:role="line"
id="tspan2762-78"
style="font-size:25.4px;stroke-width:0.264583"
x="190.67566"
y="23.171078">8</tspan></text>
<rect
style="opacity:0.94;fill:#000000;fill-opacity:1;stroke-width:0.159074;stroke-linejoin:round"
id="rect13458"
width="3.0269053"
height="23.409332"
x="216.61328"
y="1.4898645" />
<path
sodipodi:type="star"
style="opacity:0.94;fill:#c80000;fill-opacity:1;stroke-width:1.88976;stroke-linejoin:round"
id="path13598"
inkscape:flatsided="true"
sodipodi:sides="3"
sodipodi:cx="830.13611"
sodipodi:cy="17.592884"
sodipodi:r1="31.913498"
sodipodi:r2="15.956749"
sodipodi:arg1="0"
sodipodi:arg2="1.0471976"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 862.04961,17.592884 -47.87025,27.6379 v -55.2758 z"
transform="matrix(0.26458333,0,0,0.26458333,4.4504611,4.7744104)"
inkscape:transform-center-x="-2.1109449" />
<path
id="path15198"
style="opacity:0.94;fill:url(#radialGradient17534);fill-opacity:1;stroke:none;stroke-width:0.0611019;stroke-linejoin:round"
d="m 255.02903,18.922636 -2.38443,0.980073 -1.29044,6.689887 -1.29044,-6.689887 -2.38442,-0.980073 -2.81674,0.984166 0.99178,-2.795106 -0.98766,-2.366105 -6.74168,-1.280528 6.74168,-1.280527 0.98766,-2.3661053 -0.99178,-2.7951042 2.81674,0.9841643 2.38442,-0.9800724 1.29044,-6.6898862 1.29044,6.6898862 2.38443,0.9800733 2.81675,-0.9841652 -0.99178,2.7951042 0.98766,2.3661063 6.74167,1.280526 -6.74167,1.280528 -0.98766,2.366105 0.99178,2.795106 z"
sodipodi:nodetypes="ccccccccccccccccccccccccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.5 KiB

25
studium/it-lab/index.html Normal file
View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="de" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="author" content="Elias Fink">
<meta name="copyright" content="Copyright © 2024 Elias Fink">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex, nofollow">
<link rel="icon" href="images/favicon.ico">
<link rel="stylesheet" href="styles.css">
<script src="script.js"></script>
<title>Minesweeper by Elias Fink</title>
</head>
<body>
</body>
</html>

306
studium/it-lab/script.js Normal file
View File

@@ -0,0 +1,306 @@
window.addEventListener('load', () => {
minesweeper.init();
});
const minesweeper = {
init() {
this.logic = remoteLogic;
this.generateBody();
this.newGame('small');
},
// ------------------------------------ //
// ----- Basic Body Structure ----- //
// ------------------------------------ //
generateBody() {
const body = document.body;
const container = document.createElement('div');
container.id = 'container';
body.appendChild(container);
container.append(this.getHeader(), this.getMain(), this.getButtons(), this.getFooter());
},
getHeader() {
const header = document.createElement('header');
const title = document.createElement('div');
title.id = 'title';
header.appendChild(title);
const heading = document.createElement('h1');
heading.innerText = 'Minesweeper';
const subheading = document.createElement('p');
subheading.innerText = 'by Elias Fink';
title.append(heading, subheading);
return header;
},
getMain() {
const main = document.createElement('main');
return main;
},
getButtons() {
const buttons = document.createElement('div');
buttons.id = 'buttons';
const smallButton = this.createButton('small');
const mediumButton = this.createButton('medium');
const largeButton = this.createButton('large');
buttons.append(smallButton, mediumButton, largeButton);
return buttons;
},
getFooter() {
const footer = document.createElement('footer');
const copyright = document.createElement('span');
copyright.innerHTML = 'Copyright &copy; 2024 Elias Fink';
const webLink = document.createElement('span');
webLink.innerHTML = '<a href="https://studium.eliasfink.de/it-lab/" target="_blank" rel="noopener noreferrer">Web Version</a>';
const gitLink = document.createElement('span');
gitLink.innerHTML = '<a href="https://github.com/eliasfnk/it-lab.git" target="_blank" rel="noopener noreferrer">Git Repository</a>';
footer.append(copyright, webLink, gitLink);
return footer;
},
// ---------------------------------- //
// ----- Buttons and Fields ----- //
// ---------------------------------- //
createButton(type) {
const button = document.createElement('button');
button.id = type;
button.innerText = type;
button.addEventListener('click', () => {
this.newGame(type);
});
return button;
},
generatePlayfield(size) {
const playfield = document.querySelector('main');
playfield.innerText = '';
for (let row = 0; row < size; row++) {
for (let col = 0; col < size; col++) {
playfield.appendChild(this.createCell(row, col));
}
}
},
createCell(row, col) {
const cell = document.createElement('div');
cell.classList.add('cell', 'covered');
cell.dataset.x = col;
cell.dataset.y = row;
cell.style.width = `calc(100% / ${this.size} - 2px)`;
cell.style.height = `calc(100% / ${this.size} - 2px)`;
this.cellEventListeners(cell);
return cell;
},
cellEventListeners(cell) {
cell.addEventListener('click', (event) => {
this.cellLeftClickHandler(event);
});
cell.addEventListener('contextmenu', (event) => {
this.cellRightClickHandler(event);
});
cell.addEventListener('touchstart', (event) => {
this.cellTouchStartHandler(event);
});
cell.addEventListener('touchend', (event) => {
this.cellTouchEndHandler(event);
});
},
// -------------------------- //
// ----- Game Start ----- //
// -------------------------- //
gameModes: [
{
name: 'small',
size: 9,
mines: 10
},
{
name: 'medium',
size: 16,
mines: 40
},
{
name: 'large',
size: 24,
mines: 150
},
],
async newGame(gameMode) {
for (const mode of this.gameModes) {
if (mode.name == gameMode) {
this.size = mode.size;
this.mines = mode.mines;
}
}
this.generatePlayfield(this.size);
await this.logic.init(this.size, this.mines);
},
// ------------------------------------ //
// ----- Click/Touch Handling ----- //
// ------------------------------------ //
async cellLeftClickHandler(event) {
event.preventDefault();
const x = event.target.dataset.x;
const y = event.target.dataset.y;
const result = await this.logic.sweep(x, y);
if (result.minehit) {
this.logic.gameLost(event, result.mines);
} else {
this.logic.uncoverCell(x, y, result.minesAround);
for (const cell of result.emptyCells) {
this.logic.uncoverCell(cell.x, cell.y, cell.minesAround);
}
if (result.userwins) {
this.logic.gameWon();
}
}
},
cellRightClickHandler(event) {
event.preventDefault();
event.target.classList.toggle('symbol-f');
},
cellTouchStartHandler(event) {
event.preventDefault();
this.touchStartTime = new Date().getTime();
},
cellTouchEndHandler(event) {
event.preventDefault();
const touchDuration = new Date().getTime() - this.touchStartTime;
if (touchDuration < 500) {
this.cellLeftClickHandler(event);
} else {
this.cellRightClickHandler(event);
}
}
};
// -------------------------------------------------- //
// -------------------------------------------------- //
// -------------------------------------------------- //
const remoteLogic = {
// ----------------------------- //
// ----- Field Filling ----- //
// ----------------------------- //
async init(size, mines) {
this.serverUrl = 'https://www2.hs-esslingen.de/~melcher/it/minesweeper/?';
const request = `request=init&size=${size}&mines=${mines}&userid=elfiit00`;
const response = await this.fetchAndDecode(request);
this.token = response.token;
},
async fetchAndDecode(request) {
return fetch(this.serverUrl + request).then(response => response.json());
},
// ------------------------------- //
// ----- Move Processing ----- //
// ------------------------------- //
async sweep(x, y) {
const request = `request=sweep&token=${this.token}&x=${x}&y=${y}`;
return this.fetchAndDecode(request);
},
// ------------------------------- //
// ----- Cell Uncovering ----- //
// ------------------------------- //
getCell(x, y) {
return document.querySelector(`[data-x="${x}"][data-y="${y}"]`);
},
uncoverCell(x, y, symbol) {
this.getCell(x, y).classList.remove('covered');
if (symbol) {
this.getCell(x, y).classList.add(`symbol-${symbol}`);
}
},
// ------------------------ //
// ----- Game End ----- //
// ------------------------ //
gameLost(event, mines) {
event.target.id = 'mine-hit';
for (const m of mines) {
this.uncoverCell(m.x, m.y, 'm');
}
this.displayOverlay('Game Over');
},
gameWon() {
this.displayOverlay('Victory');
},
displayOverlay(text) {
const overlay = document.createElement('div');
overlay.id = 'overlay';
const div = document.createElement('div');
div.innerText = text;
overlay.appendChild(div);
const main = document.querySelector('main');
main.appendChild(overlay);
}
};

231
studium/it-lab/styles.css Normal file
View File

@@ -0,0 +1,231 @@
/* ------------------------- */
/* General */
/* ------------------------- */
:root {
--blue-1: #001A33;
--blue-2: #004D99;
--blue-3: #0080FF;
--blue-4: #66B3FF;
--blue-5: #CCE6FF;
--grey-1: #161A1D;
--grey-2: #434D56;
--grey-3: #708090;
--grey-4: #A9B3BC;
--grey-5: #E2E6E9;
--peach-fuzz: #ffbe98;
}
* {
margin: 0;
padding: 0;
}
html, body {
height: 100%;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
#container {
width: min(100vw, 55.555vh);
height: min(100vh, 180vw);
margin: 0 auto;
}
/* ------------------------ */
/* Header */
/* ------------------------ */
header {
height: calc(4 * 100% / 18);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
background-color: var(--blue-3);
color: #fff;
}
#title h1 {
font-size: 40px;
margin-bottom: 5px;
}
#title p {
font-size: 20px;
}
@media (min-width: 420px) {
header {
background-image: url(images/logo.svg);
background-size: 100px;
background-position: right 20px center;
background-repeat: no-repeat;
}
}
/* ------------------------------- */
/* Playing Field */
/* ------------------------------- */
main {
position: relative;
height: calc(10 * 100% / 18);
display: flex;
flex-wrap: wrap;
align-content: space-between;
justify-content: space-between;
border: 1px solid var(--grey-3);
}
.cell {
flex-shrink: 0;
background-color: var(--blue-5);
border: 1px solid var(--grey-3);
}
.covered {
background-color: var(--grey-4);
}
.symbol-1, .symbol-2, .symbol-3, .symbol-4, .symbol-5, .symbol-6, .symbol-7, .symbol-8, .symbol-f.covered, .symbol-m {
background-size: 1000%;
background-image: url(images/symbols.svg);
}
.symbol-1 {
background-position: calc(100% * 0 / 9);
}
.symbol-2 {
background-position: calc(100% * 1 / 9);
}
.symbol-3 {
background-position: calc(100% * 2 / 9);
}
.symbol-4 {
background-position: calc(100% * 3 / 9);
}
.symbol-5 {
background-position: calc(100% * 4 / 9);
}
.symbol-6 {
background-position: calc(100% * 5 / 9);
}
.symbol-7 {
background-position: calc(100% * 6 / 9);
}
.symbol-8 {
background-position: calc(100% * 7 / 9);
}
.symbol-f.covered {
background-position: calc(100% * 8 / 9);
}
.symbol-m {
background-position: calc(100% * 9 / 9);
}
#mine-hit {
background-color: var(--peach-fuzz);
}
#overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.4);
}
#overlay div {
padding: 16px 32px;
border-radius: 16px;
background-color: var(--blue-4);
font-size: 48px;
}
#overlay div:hover {
opacity: 0.2;
transition: 0.2s;
}
/* ------------------------- */
/* Buttons */
/* ------------------------- */
#buttons {
height: calc(3 * 100% / 18);
display: flex;
align-items: center;
justify-content: space-around;
padding: 0 20px;
background-color: var(--grey-5);
}
button {
font-size: 16px;
text-transform: capitalize;
padding: 15px 30px;
margin: 0 2px;
color: #fff;
background-color: var(--blue-3);
border: 2px solid var(--blue-3);
cursor: pointer;
transition: 0.2s;
}
button:hover {
color: var(--blue-3);
background-color: transparent;
}
/* ------------------------ */
/* Footer */
/* ------------------------ */
footer {
height: calc(100% / 18);
display: flex;
align-items: center;
justify-content: space-around;
padding: 0 20px;
background-color: var(--grey-2);
color: #fff;
}
footer a {
color: #fff;
text-decoration: none;
border-bottom: 1px solid #fff;
}
footer a:hover {
border-bottom: 0;
}
@media (max-width: 480px) {
footer span:not(:first-child) {
display: none;
}
}

40
tools/discord-webhook.php Normal file
View File

@@ -0,0 +1,40 @@
<?php include "html-head.php"; ?>
<title>Discord Webhook API</title>
</head>
<body>
<label for="username">Name:</label><br>
<input type="text" id="username" name="username" required>
<br><br>
<label for="avatar_url">Avatar URL:</label><br>
<input type="text" id="avatar_url" name="avatar_url" required>
<br><br>
<label for="message">Nachricht:</label><br>
<textarea id="message" name="message" required></textarea>
<br><br>
<button onclick="sendMessage()">Nachricht senden</button>
<script>
function sendMessage() {
var request = new XMLHttpRequest();
var username = document.getElementById("username").value;
var avatar_url = document.getElementById("avatar_url").value;
var message = document.getElementById("message").value;
request.open("POST", "https://discord.com/api/webhooks/810505594678280203/mnxaBTlCwZJstK_mXevDJ21PbdJdu0a0VtqEv2cyCEMNdO0zXzLnqW8Dk2yRmzl7V67w");
request.setRequestHeader('Content-type', 'application/json');
var paramaters = {
username: username,
avatar_url: avatar_url,
content: message
}
request.send(JSON.stringify(paramaters));
alert("Nachricht gesendet");
}
</script>
</body>
</html>

29
tools/discord-widget.php Normal file
View File

@@ -0,0 +1,29 @@
<?php include "../html-head.php"; ?>
<style>
* {
margin: 0;
padding: 0;
}
body {
margin: 0;
overflow: hidden;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
}
iframe {
width: 100vw;
height: 100vh;
}
</style>
<title>Discord Widget &ndash; Tools &ndash; Elias Fink</title>
</head>
<body>
<iframe src="https://discord.com/widget?id=788054095800827944&theme=dark" frameborder="0" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"></iframe>
</body>
</html>

44
tools/index.php Normal file
View File

@@ -0,0 +1,44 @@
<?php include "../html-head.php"; ?>
<link rel="stylesheet" href="https://static.eliasfink.de/fonts/montserrat/montserrat.css">
<style>
body {
margin: 0;
background-color: var(--blue-1);
}
h1 {
top: 50%;
left: 50%;
margin: 0;
color: #FFFFFF;
font-size: 48px;
font-weight: 300;
position: absolute;
transform: translate(-50%, -50%);
font-family: "Montserrat", sans-serif;
}
span {
color: var(--blue-3);
}
@media (max-width: 767px) {
h1 {
font-size: 32px;
}
}
</style>
<title>Tools &ndash; eliasfink.de</title>
</head>
<body>
<h1><span>tools</span>.eliasfink.de</h1>
</body>
</html>

116
tools/mail.php Normal file
View File

@@ -0,0 +1,116 @@
<?php include "html-head.php"; ?>
<style>
body {
margin: 0;
font-size: 18px;
font-weight: 400;
line-height: 1.5;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
}
#container {
padding: 25px;
}
.spacer-10 {
height: 10px;
}
</style>
<title>PHP Mail GUI &ndash; Elias Fink</title>
</head>
<body>
<?php
if ( $_POST ) {
$from_name = filter_var ( $_POST['from_name'], FILTER_SANITIZE_STRING );
$from_email = filter_var ( $_POST['from_email'], FILTER_SANITIZE_STRING );
$to = filter_var ( $_POST['to'], FILTER_SANITIZE_STRING );
$subject = filter_var ( $_POST['subject'], FILTER_SANITIZE_STRING );
$message = '<div>' . nl2br ( htmlspecialchars ( $_POST['message'] ) ) . '</div>';
$cc = filter_var ( $_POST['cc'], FILTER_SANITIZE_STRING );
$bcc = filter_var ( $_POST['bcc'], FILTER_SANITIZE_STRING );
$reply_to = filter_var ( $_POST['reply_to'], FILTER_SANITIZE_STRING );
$headers = 'MIME-Version: 1.0' . "\r\n"
.'Content-type: text/html; charset=utf-8' . "\r\n"
.'From: ' . $from_name . ' <' . $from_email . '>' . "\r\n"
.'Cc: ' . $cc . "\r\n"
.'Bcc: ' . $bcc . "\r\n"
.'Reply-To: ' . $reply_to . "\r\n";
if ( mail ( $to, $subject, $message, $headers ) ) {
echo '<h1 style="color:#0c0;">Nachricht erfolgreich gesendet</h1>';
echo '<p><b>Von:</b> ' . $from_name . ' &lt;' . $from_email . '&gt;</p>';
echo '<p><b>An:</b> ' . $to . '</p>';
echo '<p><b>Betreff:</b> ' . $subject . '</p>';
echo '<p><b>Nachricht:</b></p>' . $message;
echo '<p><b>Cc:</b> ' . $cc . '</p>';
echo '<p><b>Bcc:</b> ' . $bcc . '</p>';
echo '<p><b>Antwort an:</b> ' . $reply_to . '</p>';
} else {
echo '<h1 style="color:red;">Senden der Nachricht fehlgeschlagen</h1>';
}
}
?>
<div id="container">
<form action="mail.php" method="post">
<div id="form-left">
<label for="from_name">Von:</label>
<input type="text" id="from_name" name="from_name" placeholder="Name" required>
<input type="text" id="from_email" name="from_email" placeholder="E-Mail" required>
<div class="spacer-10"></div>
<label for="to">An:</label>
<input type="text" id="to" name="to" required>
<div class="spacer-10"></div>
<label for="subject">Betreff:</label><div class="spacer-10"></div>
<input type="text" id="subject" name="subject" required>
<div class="spacer-10"></div>
<label for="message">Nachricht:</label><div class="spacer-10"></div>
<textarea id="message" name="message" required></textarea>
</div>
<div id="form-right">
<label for="cc">Cc:</label>
<input type="text" id="cc" name="cc">
<div class="spacer-10"></div>
<label for="bcc">Bcc:</label>
<input type="text" id="bcc" name="bcc">
<div class="spacer-10"></div>
<label for="reply_to">Antwort an:</label>
<input type="text" id="reply_to" name="reply_to">
</div>
<input type="submit" value="E-Mail senden">
</form>
</div>
</body>
</html>

47
tools/tools.css Normal file
View File

@@ -0,0 +1,47 @@
body {
margin: 0;
color: #fff;
overflow: hidden;
text-align: center;
font-family: "Montserrat";
background-color: #001A33;
}
#container {
top: 50%;
left: 50%;
position: absolute;
transform: translate(-50%, -50%);
}
#title {
margin-top: 0;
font-size: 40px;
font-weight: 300;
margin-bottom: 50px;
}
#title span {
color: #168eff;
}
.button {
color: #fff;
cursor: pointer;
font-size: 18px;
background: none;
transition: 0.25s;
padding: 15px 30px;
border-radius: 5px;
border: 2px solid #fff;
}
.button:hover {
color: #001A33;
background-color: #fff;
}
.button a {
color: inherit;
text-decoration: none;
}