/view.html |
@@ -0,0 +1,258 @@ |
<!DOCTYPE html> |
<html lang="en"> |
<head> |
<meta charset="utf-8"> |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> |
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> |
<meta http-equiv="Pragma" content="no-cache" /> |
<meta http-equiv="Expires" content="0" /> |
<meta name="viewport" content="width=device-width, initial-scale=1"> |
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags --> |
<meta name="description" content="quick asset upload"> |
<meta name="author" content="Wizardry and Steamworks"> |
<link rel="icon" href="favicon.ico"> |
|
<title>scratch</title> |
|
<!-- Bootstrap core CSS --> |
<link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> |
<!-- Font Awesome --> |
<link href="bower_components/font-awesome/css/font-awesome.min.css" rel="stylesheet"> |
<!-- blueimp gallery --> |
<link rel="stylesheet" href="bower_components/blueimp-gallery/css/blueimp-gallery.min.css"> |
<!-- Swiper --> |
<link rel="stylesheet" href="bower_components/swiper/dist/css/swiper.min.css"> |
|
<!-- Site-wide style CCS --> |
<link href="css/style.css" rel="stylesheet"> |
|
<!-- Local style --> |
<link href="css/gallery/style.css" rel="stylesheet"> |
</head> |
|
<body> |
|
<!-- Main component for a primary marketing message or call to action --> |
<div class="paralax-background"></div> |
<div class="jumbotron"> |
<h1>scratch copy</h1> |
<p class="quote">the asset sharer</p> |
</div> |
|
<div class="container"> |
|
<ul class="nav nav-tabs"> |
<li><a href="index.html">Home</a></li> |
<li><a href="file.html">File</a></li> |
<li><a href="text.html">Text</a></li> |
<li><a href="draw.html">Draw</a></li> |
<li><a href="link.html">Link</a></li> |
<li class="active"><a href="#">View</a></li> |
</ul> |
|
<div id="main-panel" class="panel panel-default"> |
<div class="panel-body"> |
<div class="input-group"> |
<input id="URL" type="text" class="form-control" readonly> |
<span class="input-group-btn"> |
<button id="copy-url" class="btn btn-default" type="button" data-clipboard-target="#URL" data-toggle="tooltip" data-placement="auto" title="Copy to clipboard."><i class="glyphicon glyphicon-paperclip"></i></button> |
</span> |
<span class="input-group-btn"> |
<button id="btn-facebook" class="btn btn-default" type="button" disabled><i class="fa fa-facebook"></i></button> |
</span> |
</div> |
|
<!-- The Gallery as inline carousel, can be positioned anywhere on the page --> |
<div id="blueimp-gallery-carousel" class="blueimp-gallery blueimp-gallery-carousel"> |
<div class="slides"></div> |
<h3 class="title"></h3> |
<a class="prev">‹</a> |
<a class="next">›</a> |
<a class="play-pause"></a> |
<!-- <ol class="indicator"></ol> --> |
</div> |
|
<div class="swiper-container"> |
<div id="links" class="swiper-wrapper"> |
</div> |
<!-- If we need navigation buttons --> |
<div class="swiper-button-prev"></div> |
<div class="swiper-button-next"></div> |
</div> |
</div> |
</div> |
|
</div> <!-- /container --> |
|
<div id="footer"> |
<div class="container"> |
<p class="text-muted credit text-center">Copyright <i class="glyphicon glyphicon-copyright-mark"></i> 2017 <a href="http://grimore.org">Wizardry and Steamworks</a>.</p> |
</div> |
</div> |
|
<!-- jQuery --> |
<script src="bower_components/jquery/dist/jquery.min.js"></script> |
<!-- BootStrap --> |
<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script> |
<!-- Bootstrap Validator --> |
<script src="bower_components/bootstrap-validator/dist/validator.min.js"></script> |
<!-- blueimp-gallery --> |
<script src="bower_components/blueimp-gallery/js/blueimp-gallery.min.js"></script> |
<!-- Clipboard --> |
<script src="bower_components/clipboard/dist/clipboard.min.js"></script> |
<!-- YAML --> |
<script src="bower_components/yaml.js/dist/yaml.min.js"></script> |
<!-- Swiper --> |
<script src="bower_components/swiper/dist/js/swiper.min.js"></script> |
<!-- Wizardry and Steamworks --> |
<script src="bower_components/was/dist/was.min.js"></script> |
<script> |
$(document).ready(() => { |
|
// Extend gallery for HTML. |
blueimp.Gallery.prototype.textFactory = function (obj, callback) { |
var $element = $('<div>') |
.addClass('text-content') |
.attr('title', obj.title); |
$.get(obj.href, { |
timestamp: window.performance.now() |
}).done(function (result) { |
$element.html(result); |
callback({ |
type: 'load', |
target: $element[0] |
}); |
}) |
.fail(function () { |
callback({ |
type: 'error', |
target: $element[0] |
}); |
}); |
return $element[0]; |
}; |
|
$.getJSON('gallery.php', { |
timestamp: window.performance.now() |
}).then((data) => { |
// Create slides. |
var indexPage = 0; |
data.chunk(50).forEach((page) => { |
document.getElementById('links') |
.insertAdjacentHTML( |
'beforeend', |
'<div id="swiper-slide-' + indexPage + '" class="swiper-slide"></div>' |
); |
page.forEach((link) => { |
// Generic icon for text / html items. |
switch(link.type) { |
case 'text/plain': |
link.preview ='img/text.png'; |
break; |
} |
document.getElementById('swiper-slide-' + indexPage) |
.insertAdjacentHTML( |
'beforeend', |
'<a href="' + |
link.url + |
'" type="' + |
link.type + |
'"><img src="' + |
link.preview + |
'" width="60" height="40"></a>' |
); |
}); |
|
|
++indexPage; |
}); |
|
// Initialize gallery. |
document.getElementById('links').onclick = function (event) { |
event = event || window.event; |
var target = event.target || event.srcElement, |
link = target.src ? target.parentNode : target, |
options = { |
index: link, |
event: event, |
carousel: true, |
container: '#blueimp-gallery-carousel', |
stretchImages: true, |
startSlideshow: false, |
onslideend: function(index, slide) { |
// Set the URL. |
$('#URL').val( |
location.protocol |
.concat("//") |
.concat(window.location.hostname) |
.concat("/").concat(data[index].url) |
); |
|
// Check if OpenGraph should be enabled. |
switch(data[index].opengraph) { |
case true: |
// Enable the facebook button. |
$('#btn-facebook') |
.prop("disabled", false); |
break; |
default: |
// Disable the facebook button. |
$('#btn-facebook') |
.prop("disabled", true); |
break; |
} |
|
// Change the URL to OpenGraph when the user clicks the button. |
$('#btn-facebook').on('click', () => { |
$('#URL') |
.val( |
location.protocol.concat("//") |
.concat(window.location.hostname) |
.concat("/") |
.concat("og") |
.concat("/") |
.concat(data[index].url) |
); |
}); |
} |
}, |
links = this.getElementsByTagName('a'); |
blueimp.Gallery(links, options); |
}; |
|
new Swiper ('.swiper-container', { |
// Optional parameters |
direction: 'horizontal', |
// Creates duplicate element IDs if set to true. |
loop: false, |
|
// If we need pagination |
//pagination: '.swiper-pagination', |
|
// Navigation arrows |
nextButton: '.swiper-button-next', |
prevButton: '.swiper-button-prev', |
|
// And if we need scrollbar |
//scrollbar: '.swiper-scrollbar', |
}); |
|
// Enable the Clipboard button. |
new Clipboard('#copy-url'); |
}); |
}); |
</script> |
<!-- Jumbotron parallax effect --> |
<script> |
var jumboHeight = $('.jumbotron').outerHeight(); |
function parallax(){ |
var scrolled = $(window).scrollTop(); |
$('.paralax-background').css('height', (jumboHeight-scrolled) + 'px'); |
} |
|
$(window).scroll(function(e){ |
parallax(); |
}); |
</script> |
</body> |
</html> |
/view.php |
@@ -0,0 +1,131 @@ |
<?php |
|
########################################################################### |
## Copyright (C) Wizardry and Steamworks 2017 - License: GNU GPLv3 ## |
########################################################################### |
|
require_once('php/pseudocrypt.php'); |
require_once('php/functions.php'); |
require_once('vendor/autoload.php'); |
require_once('vendor/php-ffmpeg/php-ffmpeg/src/FFMpeg/FFMpeg.php'); |
|
### Load configuration. |
$config = spyc_load_file('config.yaml'); |
|
### Open MIME. |
$finfo = finfo_open(FILEINFO_MIME_TYPE); |
if (!$finfo) { |
http_response_code(500); |
die('Internal server error.'); |
} |
|
echo json_encode( |
array_values( |
array_filter( |
array_map( |
function ($file) use ($config, $finfo) { |
#### Get the file hash. |
$fileHash = array_shift(explode('.', $file)); |
|
#### Build the user path. |
$userPath = join( |
DIRECTORY_SEPARATOR, |
array( |
$config['STORE_FOLDER'], |
$file |
) |
); |
|
#### If the extension is not allowed then skip this file. |
$fileExtension = pathinfo($userPath, PATHINFO_EXTENSION); |
if (!isset($fileExtension) || |
!in_array(strtoupper($fileExtension), |
array_map('strtoupper', $config['ALLOWED_FILE_EXTENSIONS']))) |
return null; |
|
#### Hook for various file extensions. |
$opengraph = FALSE; |
switch (strtoupper($fileExtension)) { |
case "MP4": |
### Generate a hash for the preview image. |
$previewHash = strtolower( |
PseudoCrypt::hash( |
preg_replace( |
'/\D/', |
'', |
hash( |
'sha512', |
$fileHash |
) |
), |
$config['ASSET_HASH_SIZE'] |
) |
); |
|
### Build the user path. |
$previewFile = join( |
DIRECTORY_SEPARATOR, |
array( |
$config['STORE_FOLDER'], |
$previewHash |
) |
); |
|
### Do not re-create the thumbnail if it already exists. |
if (file_exists($previewFile.'.'.'jpg')) { |
break; |
} |
|
### Extract thumbnail. |
$ffmpeg = FFMpeg\FFMpeg::create(); |
$video = $ffmpeg->open($userPath); |
$frame = $video->frame( |
FFMpeg\Coordinate\TimeCode::fromSeconds( |
$config['VIDEO_PREVIEW_IMAGE_FRAME_SECOND'] |
) |
); |
$frame->save($previewFile.'.'.'jpg'); |
$opengraph = TRUE; |
break; |
case "GIF": |
$opengraph = TRUE; |
case "PNG": |
case "HTML": |
case "HTM": |
case "TGA": |
case "SVG": |
case "JPEG": |
case "JPG": |
$previewHash = $fileHash; |
break; |
default: |
return null; |
} |
return array( |
'url' => $fileHash, |
'type' => finfo_file($finfo, $userPath), |
'preview' => $previewHash, |
'opengraph' => $opengraph |
); |
}, |
array_values( |
array_filter(scandir($config['STORE_FOLDER']), |
function ($entry) use ($config) { |
return !is_dir($entry) && filesize( |
join( |
DIRECTORY_SEPARATOR, |
array( |
$config['STORE_FOLDER'], |
$entry |
) |
) |
); |
} |
) |
) |
) |
) |
) |
); |
|
finfo_close($finfo); |