Improve pre-post file checks.
Always allow the files to be posted, but provide convienient links to delete the posts in the error messages.
This commit is contained in:
parent
fc98a839bc
commit
77074a9f48
@ -338,93 +338,19 @@ QR =
|
|||||||
@value = null
|
@value = null
|
||||||
return unless files.length
|
return unless files.length
|
||||||
QR.cleanNotifications()
|
QR.cleanNotifications()
|
||||||
for file, i in files
|
for file in files
|
||||||
QR.handleFile file, i, files.length
|
QR.handleFile file, files.length
|
||||||
$.addClass QR.nodes.el, 'dump' unless files.length is 1
|
$.addClass QR.nodes.el, 'dump' unless files.length is 1
|
||||||
|
|
||||||
handleFile: (file, index, nfiles) ->
|
handleFile: (file, nfiles) ->
|
||||||
isSingle = nfiles is 1
|
isText = /^text\//.test file.type
|
||||||
if /^text\//.test file.type
|
if nfiles is 1
|
||||||
if isSingle
|
|
||||||
post = QR.selected
|
|
||||||
else if index isnt 0 or (post = QR.posts[QR.posts.length - 1]).com
|
|
||||||
post = new QR.post()
|
|
||||||
post.pasteText file
|
|
||||||
return
|
|
||||||
unless file.type in QR.mimeTypes
|
|
||||||
QR.error "#{file.name}: Unsupported file type."
|
|
||||||
return unless isSingle
|
|
||||||
max = QR.nodes.fileInput.max
|
|
||||||
max = Math.min(max, QR.max_size_video) if /^video\//.test file.type
|
|
||||||
if file.size > max
|
|
||||||
QR.error "#{file.name}: File too large (file: #{$.bytesToString file.size}, max: #{$.bytesToString max})."
|
|
||||||
return unless isSingle
|
|
||||||
isNewPost = false
|
|
||||||
if isSingle
|
|
||||||
post = QR.selected
|
post = QR.selected
|
||||||
else if index isnt 0 or (post = QR.posts[QR.posts.length - 1]).file
|
|
||||||
isNewPost = true
|
|
||||||
post = new QR.post()
|
|
||||||
QR.checkDimensions file, (pass, el) ->
|
|
||||||
if pass or isSingle
|
|
||||||
post.setFile file, el
|
|
||||||
else if isNewPost
|
|
||||||
post.rm()
|
|
||||||
URL.revokeObjectURL el.src if el
|
|
||||||
|
|
||||||
checkDimensions: (file, cb) ->
|
|
||||||
if /^image\//.test file.type
|
|
||||||
img = new Image()
|
|
||||||
img.onload = ->
|
|
||||||
{height, width} = img
|
|
||||||
pass = true
|
|
||||||
if height > QR.max_height or width > QR.max_width
|
|
||||||
QR.error "#{file.name}: Image too large (image: #{height}x#{width}px, max: #{QR.max_height}x#{QR.max_width}px)"
|
|
||||||
pass = false
|
|
||||||
if height < QR.min_height or width < QR.min_width
|
|
||||||
QR.error "#{file.name}: Image too small (image: #{height}x#{width}px, min: #{QR.min_height}x#{QR.min_width}px)"
|
|
||||||
pass = false
|
|
||||||
cb pass, img
|
|
||||||
img.onerror = ->
|
|
||||||
cb false, null
|
|
||||||
img.src = URL.createObjectURL file
|
|
||||||
else if /^video\//.test file.type
|
|
||||||
video = $.el 'video'
|
|
||||||
$.on video, 'loadeddata', ->
|
|
||||||
return unless cb
|
|
||||||
{videoHeight, videoWidth, duration} = video
|
|
||||||
max_height = Math.min(QR.max_height, QR.max_height_video)
|
|
||||||
max_width = Math.min(QR.max_width, QR.max_width_video)
|
|
||||||
pass = true
|
|
||||||
if videoHeight > max_height or videoWidth > max_width
|
|
||||||
QR.error "#{file.name}: Video too large (video: #{videoHeight}x#{videoWidth}px, max: #{max_height}x#{max_width}px)"
|
|
||||||
pass = false
|
|
||||||
if videoHeight < QR.min_height or videoWidth < QR.min_width
|
|
||||||
QR.error "#{file.name}: Video too small (video: #{videoHeight}x#{videoWidth}px, min: #{QR.min_height}x#{QR.min_width}px)"
|
|
||||||
pass = false
|
|
||||||
unless isFinite duration
|
|
||||||
QR.error "#{file.name}: Video lacks duration metadata (try remuxing)"
|
|
||||||
pass = false
|
|
||||||
else if duration > QR.max_duration_video
|
|
||||||
QR.error "#{file.name}: Video too long (video: #{duration}s, max: #{QR.max_duration_video}s)"
|
|
||||||
pass = false
|
|
||||||
if g.BOARD.ID not in ['gif', 'wsg'] and $.hasAudio video
|
|
||||||
QR.error "#{file.name}: Audio not allowed"
|
|
||||||
pass = false
|
|
||||||
cb pass, video
|
|
||||||
cb = null
|
|
||||||
$.on video, 'error', ->
|
|
||||||
return unless cb
|
|
||||||
if file.type in QR.mimeTypes
|
|
||||||
# only report error here if we should have been able to play the video
|
|
||||||
# otherwise "unsupported type" should already have been shown
|
|
||||||
QR.error "#{file.name}: Video appears corrupt"
|
|
||||||
URL.revokeObjectURL file
|
|
||||||
cb false, null
|
|
||||||
cb = null
|
|
||||||
video.src = URL.createObjectURL file
|
|
||||||
else
|
else
|
||||||
cb true, null
|
post = QR.posts[QR.posts.length - 1]
|
||||||
|
if post[if isText then 'com' else 'file']
|
||||||
|
post = new QR.post()
|
||||||
|
post[if isText then 'pasteText' else 'setFile'] file
|
||||||
|
|
||||||
openFileInput: ->
|
openFileInput: ->
|
||||||
QR.nodes.fileInput.click()
|
QR.nodes.fileInput.click()
|
||||||
|
|||||||
@ -75,6 +75,7 @@ QR.post = class
|
|||||||
delete: ->
|
delete: ->
|
||||||
$.rm @nodes.el
|
$.rm @nodes.el
|
||||||
URL.revokeObjectURL @URL
|
URL.revokeObjectURL @URL
|
||||||
|
@dismissErrors()
|
||||||
|
|
||||||
lock: (lock=true) ->
|
lock: (lock=true) ->
|
||||||
@isLocked = lock
|
@isLocked = lock
|
||||||
@ -151,9 +152,35 @@ QR.post = class
|
|||||||
@save node
|
@save node
|
||||||
return
|
return
|
||||||
|
|
||||||
setFile: (@file, el) ->
|
@rmErrored: ->
|
||||||
|
for post in QR.posts by -1 when errors = post.errors
|
||||||
|
for error in errors when doc.contains error
|
||||||
|
post.rm()
|
||||||
|
break
|
||||||
|
return
|
||||||
|
|
||||||
|
error: (className, message) ->
|
||||||
|
div = $.el 'div', {className}
|
||||||
|
$.extend div, <%= html('${message}<br>[<a href="javascript:;">delete</a>] [<a href="javascript:;">delete all</a>]') %>
|
||||||
|
(@errors or= []).push div
|
||||||
|
[rm, rmAll] = $$ 'a', div
|
||||||
|
$.on rm, 'click', => @rm() if @ in QR.posts
|
||||||
|
$.on rmAll, 'click', QR.post.rmErrored
|
||||||
|
QR.error div
|
||||||
|
|
||||||
|
fileError: (message) ->
|
||||||
|
@error 'file-error', "#{@filename}: #{message}"
|
||||||
|
|
||||||
|
dismissErrors: (test = -> true) ->
|
||||||
|
if @errors
|
||||||
|
for error in @errors when doc.contains(error) and test error
|
||||||
|
error.parentNode.previousElementSibling.click()
|
||||||
|
return
|
||||||
|
|
||||||
|
setFile: (@file) ->
|
||||||
@filename = @file.name
|
@filename = @file.name
|
||||||
@filesize = $.bytesToString @file.size
|
@filesize = $.bytesToString @file.size
|
||||||
|
@checkSize()
|
||||||
@nodes.label.hidden = false if QR.spoiler
|
@nodes.label.hidden = false if QR.spoiler
|
||||||
QR.captcha.onPostChange()
|
QR.captcha.onPostChange()
|
||||||
URL.revokeObjectURL @URL
|
URL.revokeObjectURL @URL
|
||||||
@ -161,10 +188,57 @@ QR.post = class
|
|||||||
@showFileData()
|
@showFileData()
|
||||||
else
|
else
|
||||||
@updateFilename()
|
@updateFilename()
|
||||||
if el
|
@nodes.el.style.backgroundImage = null
|
||||||
|
unless @file.type in QR.mimeTypes
|
||||||
|
@fileError 'Unsupported file type.'
|
||||||
|
else if /^(image|video)\//.test @file.type
|
||||||
|
@readFile()
|
||||||
|
|
||||||
|
checkSize: ->
|
||||||
|
max = QR.nodes.fileInput.max
|
||||||
|
max = Math.min(max, QR.max_size_video) if /^video\//.test @file.type
|
||||||
|
if @file.size > max
|
||||||
|
@fileError "File too large (file: #{@filesize}, max: #{$.bytesToString max})."
|
||||||
|
|
||||||
|
readFile: ->
|
||||||
|
isVideo = /^video\//.test @file.type
|
||||||
|
el = $.el(if isVideo then 'video' else 'img')
|
||||||
|
event = if isVideo then 'loadeddata' else 'load'
|
||||||
|
onload = =>
|
||||||
|
$.off el, event, onload
|
||||||
|
$.off el, 'error', onerror
|
||||||
|
@checkDimensions el
|
||||||
@setThumbnail el
|
@setThumbnail el
|
||||||
|
onerror = =>
|
||||||
|
$.off el, event, onload
|
||||||
|
$.off el, 'error', onerror
|
||||||
|
@fileError "#{if isVideo then 'Video' else 'Image'} appears corrupt"
|
||||||
|
URL.revokeObjectURL el.src
|
||||||
|
$.on el, event, onload
|
||||||
|
$.on el, 'error', onerror
|
||||||
|
el.src = URL.createObjectURL @file
|
||||||
|
|
||||||
|
checkDimensions: (el) ->
|
||||||
|
if el.tagName is 'IMG'
|
||||||
|
{height, width} = el
|
||||||
|
if height > QR.max_height or width > QR.max_width
|
||||||
|
@fileError "Image too large (image: #{height}x#{width}px, max: #{QR.max_height}x#{QR.max_width}px)"
|
||||||
|
if height < QR.min_height or width < QR.min_width
|
||||||
|
@fileError "Image too small (image: #{height}x#{width}px, min: #{QR.min_height}x#{QR.min_width}px)"
|
||||||
else
|
else
|
||||||
@nodes.el.style.backgroundImage = null
|
{videoHeight, videoWidth, duration} = el
|
||||||
|
max_height = Math.min(QR.max_height, QR.max_height_video)
|
||||||
|
max_width = Math.min(QR.max_width, QR.max_width_video)
|
||||||
|
if videoHeight > max_height or videoWidth > max_width
|
||||||
|
@fileError "Video too large (video: #{videoHeight}x#{videoWidth}px, max: #{max_height}x#{max_width}px)"
|
||||||
|
if videoHeight < QR.min_height or videoWidth < QR.min_width
|
||||||
|
@fileError "Video too small (video: #{videoHeight}x#{videoWidth}px, min: #{QR.min_height}x#{QR.min_width}px)"
|
||||||
|
unless isFinite duration
|
||||||
|
@fileError 'Video lacks duration metadata (try remuxing)'
|
||||||
|
else if duration > QR.max_duration_video
|
||||||
|
@fileError "Video too long (video: #{duration}s, max: #{QR.max_duration_video}s)"
|
||||||
|
if g.BOARD.ID not in ['gif', 'wsg'] and $.hasAudio el
|
||||||
|
@fileError 'Audio not allowed'
|
||||||
|
|
||||||
setThumbnail: (el) ->
|
setThumbnail: (el) ->
|
||||||
# Create a redimensioned thumbnail.
|
# Create a redimensioned thumbnail.
|
||||||
@ -185,6 +259,7 @@ QR.post = class
|
|||||||
@URL = el.src
|
@URL = el.src
|
||||||
@nodes.el.style.backgroundImage = "url(#{@URL})"
|
@nodes.el.style.backgroundImage = "url(#{@URL})"
|
||||||
return
|
return
|
||||||
|
|
||||||
if height <= width
|
if height <= width
|
||||||
width = s / height * width
|
width = s / height * width
|
||||||
height = s
|
height = s
|
||||||
@ -211,6 +286,7 @@ QR.post = class
|
|||||||
@nodes.label.hidden = true if QR.spoiler
|
@nodes.label.hidden = true if QR.spoiler
|
||||||
@showFileData()
|
@showFileData()
|
||||||
URL.revokeObjectURL @URL
|
URL.revokeObjectURL @URL
|
||||||
|
@dismissErrors (error) -> $.hasClass error, 'file-error'
|
||||||
|
|
||||||
updateFilename: ->
|
updateFilename: ->
|
||||||
long = "#{@filename} (#{@filesize})"
|
long = "#{@filename} (#{@filesize})"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user