PDO::ERRMODE_WARNING, PDO::ATTR_PERSISTENT=>true]); }catch(PDOException $e){ } if(empty($_GET['id'])){ $style = '.red{color:red}'; send_headers([$style]); echo ''; echo 'URL-Shortener/Redirector'; echo ''; echo ''; echo ''; echo ''; echo '

URL-Shortener/Redirector

'; echo '

Shorten a URL or strip referrers by redirecting via '.CANONICAL_URL.'?r=LINK

'; if(!isset($db)){ echo '

ERROR: No database connection!

'; echo ''; exit; } echo '
'; echo '

Link:

'; echo '

'; echo '
'; echo '

Show info of shortlink-ID:

'; echo '

'; if(!empty($_REQUEST['info'])){ $stmt=$db->prepare("SELECT url FROM link WHERE id=?;"); $stmt->execute([$_REQUEST['info']]); if($url=$stmt->fetch(PDO::FETCH_ASSOC)){ $url=$url['url']; echo '

Short link is: ".CANONICAL_URL."?id=$_REQUEST[info]

"; echo "

Redirects to: $url

"; }else{ echo '

Sorry, this redirect doesn\'t exist.

'; } }elseif($_SERVER['REQUEST_METHOD']==='POST' && !empty($_POST['addr'])){ if(!( // 1. all explicit schemes with whatever xxx://yyyyyyy preg_match('~^(\w*://[^\s<>]+)$~i', $_POST['addr']) // 2. valid URLs without scheme: || preg_match('~^((?:[^\s<>]*:[^\s<>]*@)?[a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?::\d*)?/[^\s<>]*)(?![^<>]*>)$~i', $_POST['addr']) || preg_match('~^((?:[^\s<>]*:[^\s<>]*@)?[a-z0-9\-]+(?:\.[a-z0-9\-]+)+:\d+)(?![^<>]*>)$~i', $_POST['addr']) || preg_match('~^([^\s<>]*:[^\s<>]*@[a-z0-9\-]+(?:\.[a-z0-9\-]+)+(?::\d+)?)(?![^<>]*>)$~i', $_POST['addr']) // 3. likely servers without any hints but not filenames like *.rar zip exe etc. || preg_match('~^((?:[a-z0-9\-]+\.)*[a-z2-7]{16}\.onion)(?![^<>]*>)$~i', $_POST['addr'])// *.onion ) ){ echo '

ERROR: Invalid address given.

'; }else{ $id=$db->query("SELECT COUNT(*) FROM link;")->fetch(PDO::FETCH_NUM); $id=$id[0]+1; $db->prepare("INSERT INTO link (id, url) VALUES (?, ?);")->execute([$id, $_POST['addr']]); echo '

Your link is: ".CANONICAL_URL."?id=$id

"; } } echo ''; }else{ if(!isset($db)){ die('No database connection!'); } settype($_GET['id'], 'int'); $stmt=$db->prepare("SELECT url FROM link WHERE id=?;"); $stmt->execute([$_GET['id']]); if($url=$stmt->fetch(PDO::FETCH_ASSOC)){ $url=$url['url']; } redirect($url); } function redirect(string $url){ preg_match('~^(.*)://~', $url, $match); $url=preg_replace('~^(.*)://~', '', $url); $escaped=htmlspecialchars($url); send_headers(); if(isset($match[1]) && ($match[1]==='http' || $match[1]==='https')){ header("Refresh: 0; URL=$match[0]$url"); echo ''; echo ""; echo ''; echo "

Redirecting to: $match[0]$escaped.

"; echo ''; }else{ if(!isset($match[0])){ $match[0]=''; } echo ''; echo ''; echo "

Non-http link requested: $match[0]$escaped.

"; echo "

If it's not working, try this one: http://$escaped.

"; echo ''; } exit; } function send_headers(array $styles = []){ header('Content-Type: text/html; charset=UTF-8'); header('Pragma: no-cache'); header('Cache-Control: no-cache, no-store, must-revalidate, max-age=0, private'); header('Expires: 0'); header('Referrer-Policy: no-referrer'); header("Permissions-Policy: accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=(), clipboard-read=(), clipboard-write=(), gamepad=(), speaker-selection=(), conversion-measurement=(), focus-without-user-activation=(), hid=(), idle-detection=(), sync-script=(), vertical-scroll=(), serial=(), trust-token-redemption=()"); header("Cross-Origin-Embedder-Policy: require-corp"); header("Cross-Origin-Opener-Policy: same-origin"); header("Cross-Origin-Resource-Policy: same-origin"); $style_hashes = ''; foreach($styles as $style) { $style_hashes .= " 'sha256-".base64_encode(hash('sha256', $style, true))."'"; } header("Content-Security-Policy: base-uri 'self'; default-src 'none'; form-action 'self'; frame-ancestors 'none'; style-src $style_hashes"); header('X-Content-Type-Options: nosniff'); header('X-Frame-Options: deny'); header('X-XSS-Protection: 1; mode=block'); if($_SERVER['REQUEST_METHOD'] === 'HEAD'){ exit; // headers sent, no further processing needed } }