mirror of
https://github.com/sigmasternchen/drnk.me
synced 2025-03-15 01:38:55 +00:00
128 lines
3.3 KiB
PHP
128 lines
3.3 KiB
PHP
<?php
|
|
|
|
require_once(ROOT . "/utils/error.php");
|
|
|
|
const CANDIDATES_PER_ITERATION = 10;
|
|
const MIN_LENGTH = 4;
|
|
const MAX_LENGTH = 20;
|
|
|
|
const DEFAULT_SCHEMA = "http://";
|
|
|
|
function generateCandidate(string $length) {
|
|
//$charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
$charset = "bcdfghklmnpqrstvwxyzBCDFGHKLMNPQRSTVWXYZ256789";
|
|
|
|
return join("",
|
|
array_map(
|
|
fn($_) => $charset[rand(0, strlen($charset) - 1)],
|
|
range(1, $length)
|
|
)
|
|
);
|
|
}
|
|
|
|
function validateInput(string $url) {
|
|
$error = null;
|
|
|
|
if (strpos($url, "://") === false) {
|
|
$url = DEFAULT_SCHEMA . $url;
|
|
}
|
|
|
|
$puny = idn_to_ascii($url);
|
|
|
|
$matches = [];
|
|
preg_match(
|
|
"/^.*?:\/\/([a-zA-Z0-9\-.]+).*$/",
|
|
$puny,
|
|
$matches
|
|
);
|
|
$hostname = $matches[1] ?? null;
|
|
if ($hostname[strlen($hostname) - 1] != ".") {
|
|
// add . so DNS lookup won't fail
|
|
$hostname .= ".";
|
|
}
|
|
|
|
$matches = [];
|
|
preg_match(
|
|
"/^.*?:\/\/([0-9:.]+).*$/",
|
|
$puny,
|
|
$matches
|
|
);
|
|
$ip = $matches[1] ?? null;
|
|
|
|
if ($url == DEFAULT_SCHEMA) {
|
|
setStatusCode(400);
|
|
$error = "Something went wrong. Please try again later.";
|
|
} else if (!filter_var($puny, FILTER_VALIDATE_URL)) {
|
|
setStatusCode(400);
|
|
$error = "That URL doesn't looks right. Please try again.";
|
|
} else if (substr($url, 0, 4) !== "http") {
|
|
setStatusCode(400);
|
|
$error = "Only http:// and https:// URLs are supported.";
|
|
} else if (
|
|
($hostname && !$ip && !dns_get_record($hostname, DNS_A | DNS_AAAA | DNS_CNAME)) ||
|
|
($ip && !filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE))
|
|
) {
|
|
setStatusCode(400);
|
|
$error = "This host doesn't seem to exist. Please use another one.";
|
|
}
|
|
|
|
if ($error) {
|
|
$data = [
|
|
"error" => $error,
|
|
"url" => $url,
|
|
];
|
|
require(ROOT . "/templates/pages/fragments/url-form.php");
|
|
return null;
|
|
} else {
|
|
return $url;
|
|
}
|
|
}
|
|
|
|
function generateSlug(URLs $repository) {
|
|
$candidates = [];
|
|
for ($length = MIN_LENGTH; count($candidates) == 0 || $length > MAX_LENGTH; $length++) {
|
|
$candidates = $repository->getUnusedSlugs(
|
|
array_map(
|
|
fn($_) => generateCandidate($length),
|
|
range(1, CANDIDATES_PER_ITERATION)
|
|
)
|
|
);
|
|
}
|
|
|
|
return $candidates[0];
|
|
}
|
|
|
|
function generateAccessKey(string $slug, string $url) {
|
|
return sha1($url . "-" . $url . "-" . microtime() . "-" . rand());
|
|
}
|
|
|
|
return function (array &$context) {
|
|
$url = $_POST["url"] ?? "";
|
|
$url = validateInput($url);
|
|
if (!$url) {
|
|
return;
|
|
}
|
|
|
|
$repository = $context[REPOSITORIES]->urls;
|
|
|
|
$result = $repository->getByUrl($url);
|
|
if ($result) {
|
|
// don't leak existing access key
|
|
$result->accessKey = "";
|
|
} else {
|
|
$slug = generateSlug($repository);
|
|
$accessKey = generateAccessKey($slug, $url);
|
|
|
|
$result = $repository->add(new URL(
|
|
$slug,
|
|
$url,
|
|
$accessKey
|
|
));
|
|
}
|
|
|
|
$data = [
|
|
"url" => "https://drnk.me/" . $result->slug,
|
|
"accessKey" => $result->accessKey,
|
|
];
|
|
require(ROOT . "/templates/pages/fragments/creation-successful.php");
|
|
};
|