340 lines
13 KiB
PHP

<?php declare(strict_types=1);
include_once('src/storage.php');
include_once('src/telegram.php');
if (empty($_GET['id'])) {
$newId = time() . rand(1000, 9999);
header("Location: ?id=$newId");
exit;
}
$id = htmlspecialchars($_GET['id']);
if (!is_numeric($id)) {
$newId = time() . rand(1000, 9999);
header("Location: ?id=$newId");
exit;
}
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$bookmark = $protocol . '://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
$alerts = [
'primary' => [],
'success' => [],
'warning' => [],
'danger' => []
];
try {
$data = Storage::get($id);
}
catch(Exception $ex) {
$alerts['danger'][] = '❌ Error reading database';
}
if (empty($data)) {
$data = [
'img' => '',
'name' => '',
'url' => '',
'desc' => ''
];
}
$gallery = [];
if (file_exists("uppies/$id/gallery")) {
foreach(scandir("uppies/$id/gallery") as $g) {
if (in_array($g, ['.', '..', '.thumbs', '.DS_Store']))
continue;
$gallery[] = $g;
}
}
if ($_SERVER["REQUEST_METHOD"] === 'POST' && isset($_GET['upload'])) {
$upload = htmlspecialchars($_GET['upload']);
http_response_code(202); # 202 is abused for errors, because uikit requires 2xx responses
$targetDir = "uppies/${id}/${upload}/";
$file = $_FILES["files"];
$fileName = basename($file["name"][0]);
// Create the uploads directory if it doesn't exist
if (!is_dir($targetDir)) {
mkdir($targetDir, 0775, true);
}
// check if the file is actually an image
if (getimagesize($file["tmp_name"][0]) === false) {
exit("❌ Error: File is not a valid image.");
}
// allow only specific image extensions
if (!in_array(strtolower(pathinfo($fileName, PATHINFO_EXTENSION)), ["psd", "tiff", "jpg", "jpeg", "png", "gif"])) {
exit("❌ Error: Only JPG, JPEG, PNG and GIF files allowed.");
}
// limit file size
if ($file["size"][0] > 200 * 1024 * 1024) {
exit("❌ Error: File too large (max. 200 MB)");
}
// Move uploaded file to the target directory
if (move_uploaded_file($file["tmp_name"][0], $targetDir . $fileName)) {
$data['img'] = $targetDir . $fileName;
try {
Storage::set($id, $data);
}
catch(Exception $ex) {
exit("❌ Database error.");
}
http_response_code(200);
exit(($upload === 'avatar'? $targetDir : '') . $fileName);
}
else {
exit("❌ Write Error.");
}
exit("❌ General error.");
}
else if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['desc']) && isset($_POST['name']) && isset($_POST['url'])) {
$data['name'] = htmlspecialchars(trim($_POST['name']));
$data['url'] = htmlspecialchars(trim($_POST['url']));
$data['desc'] = htmlspecialchars(trim($_POST['desc']));
if (!empty($data['name']) && !empty($data['desc']) && !empty($data['url'])) {
try {
Storage::set($id, $data);
Telegram::report("EF Conbook Artist Credits Submission\nname: ". $data['name'] ."\nurl: ". $data['url'] ."\ntext:\n". $data['desc']);
$alerts['success'][] = '✅ Entry saved';
}
catch(Exception $ex) {
$alerts['danger'][] = $ex;
}
}
}
?>
<!DOCTYPE html>
<html prefix="og: http://ogp.me/ns#" lang="en">
<head>
<title>Artist Credits</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Submit Artist Credits to the Eurofurence Conbook Team" />
<meta name="keywords" content="eurofurence, Conbook, artist credits" />
<meta name="robots" content="index, follow, noodp" />
<meta name="author" content="The Eurofurence Conbook Team" />
<meta name="rating" content="general" />
<link rel="shortcut icon" href="favicon.ico">
<meta property="og:image" content="img/ogp.jpg" />
<meta property="og:image:secure_url" content="img/ogp.jpg" />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:image:width" content="344" />
<meta property="og:image:height" content="247" />
<meta property="og:image:alt" content="Conbook Art Credits" />
<meta property="og:title" content="Conbook Art Credits" />
<meta property="og:description" content="Submit Artist Credits to the Eurofurence Conbook Team" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://dogpixels.net/ef/conbook-artist-credits" />
<meta property="og:site_name" content="Conbook Art Credits" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Conbook Art Credits" />
<meta name="twitter:description" content="Submit Artist Credits to the Eurofurence Conbook Team" />
<meta name="twitter:image" content="img/ogp.jpg" />
<link rel="stylesheet" href="css/uikit.min.css" type="text/css" />
<link rel="stylesheet" href="css/style.css" type="text/css" />
<script src="js/uikit.min.js"></script>
<script src="js/uikit-icons.min.js"></script>
</head>
<body>
<header>
<h1>Conbook Art Submission Form</h1>
<p>
A place for you to submit art to the Eurofurence Conbook and provide crediting information.<br />
<span uk-icon="clock"></span> Deadline: <strong>End of July</strong>!
</p>
<p><span uk-icon="image"></span> Please make sure your images are large enough for DIN A4 printing. Don't worry about cropping or aspect ratio, we will adjust them into the layout ourselves.</p>
</header>
<main>
<section>
<h3>Personal Link</h3>
<p>Bookmark or save it to edit your entry at a later time. Do not share it, unless with people you want to enable editing your information:</p>
<div class="uk-width-1-1 uk-grid-collapse" uk-grid>
<div class="uk-width-3-4@m">
<input type="text" id="bookmark" disabled value="<?= $bookmark ?>" class="uk-input" />
</div>
<div class="uk-width-1-4@m">
<button type="button" id="copyUrl" class="uk-button uk-button-primary uk-width-1-1" title="✅ Copied">Copy to Clipboard</button>
</div>
</div>
</section>
<section>
<progress id="js-progressbar" class="uk-progress" value="0" max="100" hidden></progress>
<div class="uk-child-width-1-2@m uk-grid-small uk-grid-match" uk-grid>
<div>
<h3>Your Credits Entry</h3>
<div class="upload-avatar uk-placeholder uk-position-relative">
<div id="img"></div>
<span uk-icon="icon: cloud-upload"></span>
<span class="uk-text-middle">Upload Your Profile Image<br />PNG, JPG or GIF<br />min. 500 x 500 @ 300 dpi<br /></span>
<div uk-form-custom>
<input type="file">
<span class="uk-link">SELECT FILE</span>
</div>
</div>
<form action="" method="POST">
<input type="text" name="name" id="name" maxlength="80" value="<?= $data['name'] ?>" placeholder="Your nickname (max. 80 characters)" class="uk-input" required />
<input type="text" name="url" id="url" maxlength="256" value="<?= $data['url'] ?>" placeholder="Your gallery link / homepage (max. 256 characters)" class="uk-input uk-margin-top" required />
<input type="text" name="desc" id="desc" maxlength="400" value="<?= $data['desc'] ?>" placeholder="Your description (max. 400 characters)" class="uk-input uk-margin-top" required />
<input type="submit" value="Save" class="uk-button uk-button-primary uk-margin-top" />
</form>
</div>
<div>
<h3>Your Contribution</h3>
<div class="height-100-75 upload-gallery uk-placeholder uk-text-center">
<span uk-icon="icon: cloud-upload"></span>
<span class="uk-text-middle">Drop Your Contribution Here<br />PNG, PSD, TIFF, JPG or GIF<br />highest possible resolution, ideally 300 dpi<br /></span>
<div uk-form-custom>
<input type="file">
<span class="uk-link">SELECT FILE</span>
</div>
<ul id="gallery" class="uk-text-left">
<?php foreach ($gallery as $g) {
// echo "<li>$g <a href=\"$bookmark&delete=$g\">[delete]</a></li>";
echo "<li>$g </li>";
}
?>
</ul>
</div>
</div>
</div>
</section>
</main>
<footer>
<p>Your input is being stored until September, then wiped. If you need assistance, please contact <a href="https://help.eurofurence.org/contact/conbook" target="_blank">The Conbook Department</a>.</p>
</footer>
<script>
document.getElementById('copyUrl').addEventListener('click', (e) => {
var furl = document.getElementById('bookmark');
furl.setSelectionRange(0, furl.value.length);
navigator.clipboard.writeText(furl.value);
furl.setSelectionRange(0, 0);
e.target.innerText = "✅ copied";
// setTimeout(() => {e.target.innerText = "Copy to Clipboard"}, 3000);
});
</script>
<script>
<?php
foreach ($alerts as $status => $msgs) {
foreach ($msgs as $msg) {
echo 'UIkit.notification("' . $msg . '", "' . $status . '");';
}
}
?>
</script>
<?php if ($data['img'] !== '') { ?>
<script>
document.getElementById('img').style.backgroundImage = 'url(<?= $data['img'] ?>?' + new Date().getTime() + ')';
</script>
<?php } ?>
<script>
var bar = document.getElementById('js-progressbar');
UIkit.upload('.upload-avatar', {
url: '<?= $bookmark ?>&upload=avatar',
loadStart: function (e) {
bar.removeAttribute('hidden');
bar.max = e.total;
bar.value = e.loaded;
},
progress: function (e) {
bar.max = e.total;
bar.value = e.loaded;
},
loadEnd: function (e) {
bar.max = e.total;
bar.value = e.loaded;
},
completeAll: function (r) {
if (r.status == 200) {
document.getElementById('img').style.backgroundImage = 'url(' + r.responseText + '?' + new Date().getTime() + ')';
UIkit.notification('✅ Image saved', 'success');
}
else {
UIkit.notification(r.responseText, 'danger');
}
setTimeout(function () {
bar.setAttribute('hidden', 'hidden');
}, 1000);
}
});
UIkit.upload('.upload-gallery', {
url: '<?= $bookmark ?>&upload=gallery',
multiple: true,
loadStart: function (e) {
bar.removeAttribute('hidden');
bar.max = e.total;
bar.value = e.loaded;
},
progress: function (e) {
bar.max = e.total;
bar.value = e.loaded;
},
loadEnd: function (e) {
bar.max = e.total;
bar.value = e.loaded;
},
completeAll: function (r) {
if (r.status == 200) {
const li = document.createElement('li');
li.innerText = r.responseText + ' ';
// const a = document.createElement('a');
// a.href="<?= $bookmark ?>&delete=" + r.responseText;
// a.innerText = '[delete]';
// li.appendChild(a);
document.getElementById('gallery').appendChild(li);
UIkit.notification('✅ Image saved', 'success');
}
else {
UIkit.notification(r.responseText, 'danger');
}
setTimeout(function () {
bar.setAttribute('hidden', 'hidden');
}, 1000);
}
});
</script>
</body>
</html>