This commit is contained in:
Marcin Kurczewski 2013-10-25 09:40:33 +02:00
parent 47759adb66
commit d3eaf27bdc
9 changed files with 230 additions and 82 deletions

View file

@ -0,0 +1,26 @@
.tabs ul {
list-style-type: none;
margin: 0 0 1em 0;
padding: 0;
border-bottom: 1px solid #ccc;
}
.tabs li {
display: inline-block;
}
.tabs li a {
display: inline-block;
padding: 0.5em 1em;
margin-bottom: -1px;
}
.tabs li a {
border: 1px solid white;
border-bottom: 1px solid #ccc;
color: silver;
}
.tabs li.selected a {
border: 1px solid #ccc;
border-bottom: 1px solid white;
color: inherit;
}

View file

@ -26,6 +26,11 @@
border-color: firebrick;
}
#url-handler textarea {
width: 50%;
height: 6em;
}
.post .thumbnail {
width: 100px;
height: 100px;
@ -145,3 +150,13 @@ ul.tagit {
.post .form-wrapper {
overflow: hidden;
}
.tab.url {
display: none;
}
.tab {
margin-bottom: 1em;
}
.tab textarea {
margin-bottom: 0.5em;
}

View file

@ -3,33 +3,6 @@
font-size: 90%;
}
.tabs ul {
list-style-type: none;
margin: 0 0 1em 0;
padding: 0;
border-bottom: 1px solid #ccc;
}
.tabs li {
display: inline-block;
}
.tabs li a {
display: inline-block;
padding: 0.5em 1em;
margin-bottom: -1px;
}
.tabs li a {
border: 1px solid white;
border-bottom: 1px solid #ccc;
color: silver;
}
.tabs li.selected a {
border: 1px solid #ccc;
border-bottom: 1px solid white;
color: inherit;
}
.avatar-wrapper {
text-align: center;
}

View file

@ -1,35 +1,36 @@
$(function()
{
$('.tabs nav a').click(function(e)
{
e.preventDefault();
var className = $(this).parents('li').attr('class').replace('selected', '').replace(/^\s+|\s+$/, '');
$('.tabs nav li').removeClass('selected');
$(this).parents('li').addClass('selected');
$('.tab').hide();
$('.tab.' + className).show();
});
var tags = [];
$.getJSON('/tags?json', function(data)
{
tags = data['tags'];
});
var handler = $('#file-handler');
handler.on('dragenter', function(e)
$('#file-handler').on('dragenter', function(e)
{
$(this).addClass('active');
});
handler.on('dragleave', function(e)
}).on('dragleave', function(e)
{
$(this).removeClass('active');
});
handler.on('dragover', function(e)
}).on('dragover', function(e)
{
e.preventDefault();
});
handler.on('drop', function(e)
}).on('drop', function(e)
{
e.preventDefault();
handleFiles(e.originalEvent.dataTransfer.files);
$(this).trigger('dragleave');
});
handler.on('click', function(e)
}).on('click', function(e)
{
$(':file').show().focus().trigger('click').hide();
});
@ -39,6 +40,16 @@ $(function()
handleFiles(this.files);
});
$('#url-handler-wrapper button').click(function(e)
{
var urls = $('#url-handler-wrapper textarea').val().split(/\s+/);
handleURLs(urls);
});
$('.post .move-down-trigger, .post .move-up-trigger').on('click', function()
{
var dir = $(this).hasClass('move-down-trigger') ? 'd' : 'u';
@ -62,6 +73,7 @@ $(function()
});
function sendNextPost()
{
var posts = $('#upload-step2 .post');
@ -73,12 +85,14 @@ $(function()
var postDom = posts.first();
var url = postDom.find('form').attr('action') + '?json';
var file = postDom.data('file');
var sourceFile = postDom.data('file');
var sourceUrl = postDom.data('url');
var tags = postDom.find('[name=tags]').val();
var safety = postDom.find('[name=safety]:checked').val();
var source = postDom.find('[name=source]').val();
var fd = new FormData();
fd.append('file', file);
fd.append('file', sourceFile);
fd.append('url', sourceUrl);
fd.append('tags', tags);
fd.append('safety', safety);
fd.append('source', source);
@ -145,17 +159,54 @@ $(function()
});
function handleFiles(files)
{
handleInputs(files, function(postDom, file)
{
postDom.data('file', file);
$('.file-name strong', postDom).text(file.name);
if (file.type.match('image.*'))
{
var img = postDom.find('img')
var reader = new FileReader();
reader.onload = (function(theFile, img)
{
return function(e)
{
img.css('background-image', 'none');
img.attr('src', e.target.result);
};
})(file, img);
reader.readAsDataURL(file);
}
});
}
function handleURLs(urls)
{
handleInputs(urls, function(postDom, url)
{
postDom.data('url', url);
$('.file-name strong', postDom).text(url);
$('[name=source]', postDom).val(url);
var img = postDom.find('img');
img.css('background-image', 'none');
img.attr('src', url);
});
}
function handleInputs(inputs, callback)
{
$('#upload-step1').fadeOut(function()
{
for (var i = 0; i < files.length; i ++)
for (var i = 0; i < inputs.length; i ++)
{
var file = files[i];
var input = inputs[i];
var postDom = $('#post-template').clone(true);
postDom.find('form').submit(false);
postDom.removeAttr('id');
postDom.data('file', file);
$('.file-name strong', postDom).text(file.name);
$('.posts').append(postDom);
postDom.show();
@ -164,26 +215,7 @@ $(function()
tagItOptions.placeholderText = $('.tags input').attr('placeholder');
$('.tags input', postDom).tagit(tagItOptions);
if (!file.type.match('image.*'))
{
continue;
}
var img = postDom.find('img')
var reader = new FileReader();
reader.onload = (function(theFile, img)
{
return function(e)
{
/*img.css('max-width', img.css('width'));
img.css('max-height', img.css('height'));
img.css('width', 'auto');
img.css('height', 'auto');*/
img.css('background-image', 'none');
img.attr('src', e.target.result);
};
})(file, img);
reader.readAsDataURL(file);
callback(postDom, input);
}
$('#upload-step2').fadeIn(function()
{

View file

@ -197,6 +197,7 @@ class PostController
public function uploadAction()
{
$this->context->stylesheets []= 'upload.css';
$this->context->stylesheets []= 'tabs.css';
$this->context->scripts []= 'upload.js';
$this->context->subTitle = 'upload';
PrivilegesHelper::confirmWithException(Privilege::UploadPost);
@ -206,12 +207,56 @@ class PostController
if (InputHelper::get('submit'))
{
/* file contents */
$suppliedFile = $_FILES['file'];
self::handleUploadErrors($suppliedFile);
if (isset($_FILES['file']))
{
$suppliedFile = $_FILES['file'];
self::handleUploadErrors($suppliedFile);
$origName = basename($suppliedFile['name']);
$sourcePath = $suppliedFile['tmp_name'];
}
elseif (InputHelper::get('url'))
{
$url = InputHelper::get('url');
if (!preg_match('/^https?:\/\//', $url))
throw new SimpleException('Invalid URL "' . $url . '"');
$origName = $url;
$sourcePath = tempnam(sys_get_temp_dir(), 'upload') . '.dat';
//warning: low level sh*t ahead
//download the URL $url into $sourcePath
$maxBytes = TextHelper::stripBytesUnits(ini_get('upload_max_filesize'));
set_time_limit(0);
$urlFP = fopen($url, 'rb');
if (!$urlFP)
throw new SimpleException('Cannot open URL for reading');
$sourceFP = fopen($sourcePath, 'w+b');
if (!$sourceFP)
{
fclose($urlFP);
throw new SimpleException('Cannot open file for writing');
}
try
{
while (!feof($urlFP))
{
$buffer = fread($urlFP, 4 * 1024);
if (fwrite($sourceFP, $buffer) === false)
throw new SimpleException('Cannot write into file');
fflush($sourceFP);
if (ftell($sourceFP) > $maxBytes)
throw new SimpleException('File is too big (maximum allowed size: ' . TextHelper::useBytesUnits($maxBytes) . ')');
}
}
finally
{
fclose($urlFP);
fclose($sourceFP);
}
}
/* file details */
$mimeType = mime_content_type($suppliedFile['tmp_name']);
$mimeType = mime_content_type($sourcePath);
$imageWidth = null;
$imageHeight = null;
switch ($mimeType)
@ -220,17 +265,17 @@ class PostController
case 'image/png':
case 'image/jpeg':
$postType = PostType::Image;
list ($imageWidth, $imageHeight) = getimagesize($suppliedFile['tmp_name']);
list ($imageWidth, $imageHeight) = getimagesize($sourcePath);
break;
case 'application/x-shockwave-flash':
$postType = PostType::Flash;
list ($imageWidth, $imageHeight) = getimagesize($suppliedFile['tmp_name']);
list ($imageWidth, $imageHeight) = getimagesize($sourcePath);
break;
default:
throw new SimpleException('Invalid file type "' . $mimeType . '"');
}
$fileHash = md5_file($suppliedFile['tmp_name']);
$fileHash = md5_file($sourcePath);
$duplicatedPost = R::findOne('post', 'file_hash = ?', [$fileHash]);
if ($duplicatedPost !== null)
throw new SimpleException('Duplicate upload: @' . $duplicatedPost->id);
@ -260,9 +305,9 @@ class PostController
$dbPost = R::dispense('post');
$dbPost->type = $postType;
$dbPost->name = $name;
$dbPost->orig_name = basename($suppliedFile['name']);
$dbPost->orig_name = $origName;
$dbPost->file_hash = $fileHash;
$dbPost->file_size = filesize($suppliedFile['tmp_name']);
$dbPost->file_size = filesize($sourcePath);
$dbPost->mime_type = $mimeType;
$dbPost->safety = $suppliedSafety;
$dbPost->source = $suppliedSource;
@ -274,7 +319,10 @@ class PostController
$dbPost->ownFavoritee = [];
$dbPost->sharedTag = $dbTags;
move_uploaded_file($suppliedFile['tmp_name'], $path);
if (is_uploaded_file($sourcePath))
move_uploaded_file($sourcePath, $path);
else
rename($sourcePath, $path);
R::store($dbPost);
$this->context->transport->success = true;

View file

@ -359,6 +359,7 @@ class UserController
$page = 1;
PrivilegesHelper::confirmWithException(Privilege::ViewUser, PrivilegesHelper::getIdentitySubPrivilege($user));
$this->context->stylesheets []= 'tabs.css';
$this->context->stylesheets []= 'user-view.css';
$this->context->stylesheets []= 'post-list.css';
$this->context->stylesheets []= 'post-small.css';

View file

@ -63,6 +63,18 @@ class TextHelper
return constant($constantName);
}
private static function stripUnits($string, $base, $suffixes)
{
$suffix = substr($string, -1, 1);
$index = array_search($suffix, $suffixes);
if ($index === false)
return $string;
$number = intval($string);
for ($i = 0; $i < $index; $i ++)
$number *= $base;
return $number;
}
private static function useUnits($number, $base, $suffixes)
{
$suffix = array_shift($suffixes);
@ -89,6 +101,16 @@ class TextHelper
return self::useUnits($number, 1000, ['', 'K', 'M']);
}
public static function stripBytesUnits($string)
{
return self::stripUnits($string, 1024, ['B', 'K', 'M', 'G']);
}
public static function stripDecimalUnits($string)
{
return self::stripUnits($string, 1000, ['', 'K', 'M']);
}
public static function removeUnsafeKeys(&$input, $regex)
{
if (is_array($input))

View file

@ -14,11 +14,40 @@
<div id="inner-content">
<div id="upload-step1">
<input type=file multiple style="display: none"/>
<div id="file-handler-wrapper">
<div id="file-handler">
Drop files here!<br>
Or just click on this box.
<div class="tabs">
<nav>
<ul>
<li class="selected file">
<a href="#">
Upload from file
</a>
</li>
<li class="url">
<a href="#">
Upload from URL
</a>
</li>
</ul>
</nav>
</div>
<div class="tab file">
<input type=file multiple style="display: none"/>
<div id="file-handler-wrapper">
<div id="file-handler">
Drop files here!<br>
Or just click on this box.<br><br>
</div>
</div>
</div>
<div class="tab url">
<div id="url-handler-wrapper">
<div id="url-handler">
<textarea placeholder="You can also paste some URLs." name="urls"></textarea>
</div>
<button type="submit">Submit</button>
</div>
</div>

View file

@ -96,7 +96,9 @@
<a href="<?php echo \Chibi\UrlHelper::route('post', 'retrieve', ['name' => $this->context->transport->post->name]) ?>" title="Download">
<i class="icon-dl"></i>
<span class="ext">
<?php echo strtoupper(substr($this->context->transport->post->orig_name, strrpos($this->context->transport->post->orig_name, '.') + 1)) ?>
<?php $mimes = ['image/jpeg' => 'JPG', 'image/gif' => 'GIF', 'image/png' => 'PNG', 'application/x-shockwave-flash' => 'SWF'] ?>
<?php $mime = $this->context->transport->post->mimeType ?>
<?php echo isset($mimes[$mime]) ? $mimes[$mime] : 'unknown' ?>
</span>
<span class="size">
<?php echo TextHelper::useBytesUnits($this->context->transport->post->file_size) ?>