Skip to content

Instantly share code, notes, and snippets.

@jes
Created June 29, 2025 12:03
Show Gist options
  • Save jes/330031f6c28331923a90df96f2555eee to your computer and use it in GitHub Desktop.
Save jes/330031f6c28331923a90df96f2555eee to your computer and use it in GitHub Desktop.
Max's Imagebin
<?php
/* ChangeLog:
21-08-2023:
- added password because someone uploaded a topless image
20-11-2020:
- make thumbnails 600px instead of 200px
- use imagemagick to do resizing instead of PHP GD
- change default host from img.jes.xxx to img.incoherency.co.uk
13-12-2018:
- host bootstrap locally instead of using maxcdn
11-12-2018:
- use exiftool to strip exif data
06-10-2017:
- fix XSS in page param (discovered by cht)
16-12-2014:
- make buttons bigger and increase spacing
21-11-2014:
- Various changes to make it work after move to new VM
- bootstrap ui (bad)
31-01-2012:
- Redirect to the image instead of giving a link after an image is uploaded (idea from Mateusz Kowalczyk)
06-12-2011:
- Add an index.php in images/original/ to redirect people to /imagebin/
16-11-2011:
- Fix check that file is actually an image (which only worked by accident)
04-09-2011:
- Removed "Display a maximum of 9 images per page"
- changed paths to be "/img/N" instead of "/img/N.ext" (see /etc/lighttpd/choose-ext.lua)
16-01-2011:
- changed "Upload Picture!" to "Upload image"
24-08-2010:
- removed all trailing whitespace
- switched to more consistent css
- cleaned up url's with index.php in
- added Max's name
29-07-2010:
- fixed another link to /images/original/
29-05-2010:
- images/original/ in links goes to /img/ now (with alias configured in /etc/lighttpd/lighttpd.conf)
- Now computes the correct hostname instead of assuming aw.eso.me.uk
- Makes sure thumbnails fit inside 200x200 pixels
- Uses 'sort' instead of 'ls -t' so that files are listed in the right order even if timestamps become wrong
- No longer uses separate thumbsarray and orginalarray because this can get confused if there is an extra thumb or extra original
- Image thumbnails are now the same filetype as the originals
- Now limited to 100 uploads per day and 5MB per image (resets upoad_count to 0 at midnight, see /etc/crontab)
- mad css skillz
- alpha channels in png thumbnails
*/
/* compute correct hostname for this client */
if(isset($_SERVER['HTTP_HOST'])) {
$host = $_SERVER['HTTP_HOST'];
} else {
$host = "img.incoherency.co.uk";
}
/* find number of images uploaded today */
$upload_count = (int)file_get_contents("upload_count");
$err_msg = "";
if (isset($_FILES['upload']['tmp_name']) && $_FILES['upload']['size'] > 0){
if ($_POST['password'] != 'password') {
$err_msg .= "<b>Incorrect password.</b><br>";
} else if($upload_count >= 100) {
$err_msg .= "<b>No more uploads allowed today. I apologise for the inconvenience.</b><br>";
} else if($_FILES['upload']['size'] > 16000000) {
$err_msg .= "<b>Sorry, maximum size of 16MB per image.</b><br>";
} else {
ob_start();
passthru("ls images/original | sort -n | tail -n1");
$lastfilename = ob_get_contents();
ob_end_clean();
$lastnum = explode(".", $lastfilename);
$curnum = $lastnum[0] + 1;
$filenameparts = explode(".", $_FILES['upload']['name']);
$imgsize = getimagesize($_FILES['upload']['tmp_name']);
if(!$imgsize) {
$err_msg .= "<b>Sorry, images only.</b><br>";
} else {
$shortfilename = sprintf("%s%s", $curnum, image_type_to_extension($imgsize[2]));
$newfilename = "images/original/$shortfilename";
$thumbfilename = "images/thumbs/$shortfilename";
move_uploaded_file($_FILES['upload']['tmp_name'], $newfilename);
ob_start();
passthru("exiftool -overwrite_original -all= -tagsFromFile @ -orientation $newfilename");
passthru("convert $newfilename -geometry 600x600 $thumbfilename");
ob_end_clean();
/* increment the upload count */
$upload_count += 1;
$fp = fopen("upload_count", "w");
fwrite($fp, $upload_count . "\n");
fclose($fp);
header("Location: /$curnum");
exit();
}
}
}
?>
<!doctype html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<title>imagebin</title>
<link rel="stylesheet" type="text/css" href="bootstrap.min.css">
<style type="text/css">
.btn-file {
position: relative;
overflow: hidden;
}
.btn-file input[type=file] {
position: absolute;
top: 0;
right: 0;
min-width: 100%;
min-height: 100%;
font-size: 100px;
text-align: right;
filter: alpha(opacity=0);
opacity: 0;
outline: none;
background: white;
cursor: inherit;
display: block;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<h1>imagebin</h1>
<br><br><br>
<form action="/" enctype="multipart/form-data" method="post">
Select an image:<br><input type="file" name="upload" style="font-size: 2em" id="selectimg">
<br><br>
<input name="password" type="password" placeholder="Password">
<br><br>
<button class="btn btn-lg btn-primary" style="width:100%" type="submit">Upload</button>
<br><br><br>
<?php
//if(isset($err_msg)) {
echo $err_msg;
//}
echo("</div>");
echo('<div class="row">');
if(!isset($_GET['thumbs']) && !isset($_GET['page'])){
echo('<a href="/?thumbs=1">Show thumbnails.</a>');
}
else{
$curpage = max((int)$_GET['page'], 1);
/* $thumbsarray = array_merge(array_diff(scandir("images/thumbs"), array('.', '..'))); */
ob_start();
passthru("ls images/thumbs/ | sort -nr");
$thumbslist = ob_get_contents();
ob_end_clean();
$thumbsarray = explode("\n", $thumbslist);
$numthumbs = sizeof($thumbsarray) - 1;
$thumbsperpage = 16;
$thumbsperrow = 4;
/* $originalarray = array_merge(array_diff(scandir("images/original"), array('.', '..'))); */
$tdname = array("odd", "even");
$tdstate = 0;
$curpage = max((int)$_GET['page'], 1);
$maxpage = ceil($numthumbs / $thumbsperpage);
$n = $thumbsperpage * ($curpage - 1);
$total = 0;
echo( 'Page ' . $curpage . ' of ' . $maxpage . ' - ');
if($curpage > 1){
echo('<a href="/?page=1">First Page</a>&nbsp&nbsp');
echo('<a href="/?page=' . ($curpage-1) . '">Previous Page</a>&nbsp&nbsp');
}
if($curpage < $maxpage){
echo('<a href="/?page=' . ($curpage+1) . '">Next Page</a>&nbsp&nbsp');
echo('<a href="/?page=' . $maxpage . '">Final Page</a><br><br>');
}
echo('<table style="width: auto; margin: auto">');
while(($n < $numthumbs) && ($total < $thumbsperpage)){
echo('<tr>');
while($i < $thumbsperrow && $n < $numthumbs){
$parts = explode(".", $thumbsarray[$n]);
$number = $parts[0];
echo( '<td class="' . $tdname[$tdstate] . '"><a href="/' . $number . '"><img style="max-width:200px;max-height:200px" src="images/thumbs/' . $thumbsarray[$n] .'"></a></td>');
$total++;
$i++;
$n++;
$tdstate = !$tdstate;
}
echo('</tr>');
$i = 0;
}
echo( '</table><br>Page ' . $curpage . ' of ' . $maxpage . ' - ');
if($curpage > 1){
echo('<a href="/?page=1">First Page</a>&nbsp&nbsp');
echo('<a href="/?page=' . ($curpage-1) . '">Previous Page</a>&nbsp&nbsp');
}
if($curpage < $maxpage){
echo('<a href="/?page=' . ($curpage+1) . '">Next Page</a>&nbsp&nbsp');
echo('<a href="/?page=' . $maxpage . '">Final Page</a>&nbsp&nbsp');
}
}
if($upload_count == 1) { $plural = " image "; }
else { $plural = " images "; }
echo('<br><i>' . $upload_count . $plural . 'uploaded today.</i>');
?>
<br><br>
imagebin by Maximilian of #maximilian (irc.freenode.net)
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment