diff --git a/config.sample.js b/config.sample.js
index 1166e5f..a46c411 100644
--- a/config.sample.js
+++ b/config.sample.js
@@ -40,8 +40,13 @@ module.exports = {
// Pages to process for the frontend
pages: ['home', 'auth', 'dashboard', 'faq'],
- // Add file extensions here which should be blocked
- blockedExtensions: [
+ /*
+ If set to true, all extensions in "extensionsFilter" array will be blacklisted,
+ otherwise only files with those extensions that can be uploaded.
+ */
+ filterBlacklist: true,
+
+ extensionsFilter: [
'.jar',
'.exe',
'.msi',
@@ -67,15 +72,19 @@ module.exports = {
/*
Chunked uploads.
- If this is enabled, every files uploaded from the home page will forcibly be chunked
- by the size specified in uploads.chunkedUploads.maxSize. People will still be able to
- upload bigger files through the API as long as they don't surpass the limit specified
- in uploads.maxSize though.
- Total size of the whole chunks will still be checked against uploads.maxSize too.
+ If this is enabled, every files uploaded from the homepage uploader will forcibly be chunked
+ by the size specified in "chunkSize". People will still be able to upload bigger files with
+ the API as long as they don't surpass the limit specified in the "maxSize" option above.
+ Total size of the whole chunks will also later be checked against the "maxSize" option.
+ No-JS uploader page will not have chunked uploads support, if you want to change the maximum
+ file size 'displayed' on it, you can change the value of "noJsMaxSize".
+ You can also set it to null (or other falsy values) to inherit the value of "maxSize" option.
+ "chunkSize", and "noJsMaxSize" if set, need to be in MB.
*/
chunkedUploads: {
enabled: true,
- maxSize: '10MB'
+ chunkSize: '10MB',
+ noJsMaxSize: null
},
/*
@@ -84,8 +93,8 @@ module.exports = {
their preferred file name length from the dashboard. The allowed range will
be set by "min" and "max". Otherwise it will use "default".
Technically it's possible to have "default" outside of the "min" and "max" range,
- but please not. Once a user has changed to a number within the range, the user will
- no longer be able to use the default value.
+ but please not. Otherwise, once a user has changed to a value within the range,
+ the user will no longer be able to use the default value.
*/
fileLength: {
min: 4,
@@ -95,10 +104,10 @@ module.exports = {
},
/*
- This option will limit how many times it will try to generate random names
- for uploaded files. If this value is higher than 1, it will help in cases
- where files with the same name already exists (higher chance with shorter file name length).
- */
+ This option will limit how many times it will
+ try to generate a new random name when a collision occurrs.
+ The shorter the file name length is, the higher the chance for a collision to occur.
+ */
maxTries: 1,
/*
diff --git a/controllers/uploadController.js b/controllers/uploadController.js
index 2628260..4e347a8 100644
--- a/controllers/uploadController.js
+++ b/controllers/uploadController.js
@@ -61,17 +61,15 @@ const upload = multer({
fileSize: config.uploads.maxSize
},
fileFilter (req, file, cb) {
- // If there are no blocked extensions
- if (config.blockedExtensions === undefined) {
- return cb(null, true)
- }
+ // If there are extensions that have to be filtered
+ if (config.extensionsFilter && config.extensionsFilter.length) {
+ const extname = path.extname(file.originalname).toLowerCase()
+ const match = config.extensionsFilter.some(extension => extname === extension.toLowerCase())
- // If the extension is blocked
- if (config.blockedExtensions.some(extension => {
- return path.extname(file.originalname).toLowerCase() === extension.toLowerCase()
- })) {
- // eslint-disable-next-line standard/no-callback-literal
- return cb('This file extension is not allowed.')
+ if ((config.filterBlacklist && match) || (!config.filterBlacklist && !match)) {
+ // eslint-disable-next-line standard/no-callback-literal
+ return cb(`Sorry, ${extname.substr(1).toUpperCase()} files are not permitted for security reasons.`)
+ }
}
if (chunkedUploads) {
@@ -83,13 +81,12 @@ const upload = multer({
}
const totalFileSize = parseInt(req.body.totalfilesize)
- if (!isNaN(totalFileSize) && totalFileSize > maxSizeBytes) {
+ if (totalFileSize > maxSizeBytes) {
// eslint-disable-next-line standard/no-callback-literal
- return cb('Chunked upload error. Total file size is larger than maximum file size.')
+ return cb('Chunk error occurred. Total file size is larger than the maximum file size.')
}
}
- // If the extension is not blocked
return cb(null, true)
}
}).array('files[]')
@@ -115,7 +112,7 @@ uploadsController.getUniqueRandomName = (length, extension = '', cb) => {
// If it still haven't reached allowed maximum tries, then try again
if (i < maxTries) { return access(i) }
// eslint-disable-next-line standard/no-callback-literal
- return cb('Could not allocate a unique random name. Try again?')
+ return cb('Sorry, we could not allocate a unique random name. Try again?')
})
}
// Get us a unique random name
@@ -149,17 +146,18 @@ uploadsController.upload = async (req, res, next) => {
uploadsController.actuallyUpload = async (req, res, user, albumid) => {
const erred = error => {
- console.log(error)
+ const isError = error instanceof Error
+ if (isError) { console.log(error) }
res.json({
success: false,
- description: error.toString()
+ description: isError ? error.toString() : `Error: ${error}`
})
}
upload(req, res, async error => {
if (error) { return erred(error) }
- if (req.files.length === 0) { return erred(new Error('No files.')) }
+ if (req.files.length === 0) { return erred('No files.') }
// If chunked uploads is enabled and the uploaded file is a chunk, then just say that it was a success
if (chunkedUploads && req.body.uuid) { return res.json({ success: true }) }
@@ -215,26 +213,28 @@ uploadsController.finishChunks = async (req, res, next) => {
uploadsController.actuallyFinishChunks = async (req, res, user, albumid) => {
const erred = error => {
- console.log(error)
+ const isError = error instanceof Error
+ if (isError) { console.log(error) }
res.json({
success: false,
- description: error.toString()
+ description: isError ? error.toString() : `Error: ${error}`
})
}
const files = req.body.files
- if (!files) { return erred(new Error('Missing files array.')) }
+ if (!files) { return erred('Missing files array.') }
let iteration = 0
const infoMap = []
for (const file of files) {
const { uuid, original, count } = file
- if (!uuid || !count) { return erred(new Error('Missing UUID and/or chunks count.')) }
+ if (!uuid) { return erred('Missing UUID.') }
+ if (!count) { return erred('Missing chunks count.') }
const uuidDir = path.join(chunksDir, uuid)
fs.readdir(uuidDir, async (error, chunkNames) => {
if (error) { return erred(error) }
- if (count < chunkNames.length) { return erred(new Error('Chunks count mismatch.')) }
+ if (count < chunkNames.length) { return erred('Chunks count mismatch.') }
const extension = typeof original === 'string' ? path.extname(original) : ''
const length = uploadsController.getFileNameLength(req)
diff --git a/public/js/home.js b/public/js/home.js
index a28cbeb..a8f9399 100644
--- a/public/js/home.js
+++ b/public/js/home.js
@@ -157,7 +157,7 @@ upload.prepareDropzone = () => {
autoProcessQueue: true,
headers: { token: upload.token },
chunking: upload.chunkedUploads.enabled,
- chunkSize: parseInt(upload.chunkedUploads.maxSize) * 1000000, // 1000000 B = 1 MB,
+ chunkSize: parseInt(upload.chunkedUploads.chunkSize) * 1000000, // 1000000 B = 1 MB,
parallelChunkUploads: false, // when set to true, sometimes it often hangs with hundreds of parallel uploads
chunksUploaded: async (file, done) => {
file.previewElement.querySelector('.progress').setAttribute('value', 100)
diff --git a/routes/album.js b/routes/album.js
index d38ad81..f9a03c2 100644
--- a/routes/album.js
+++ b/routes/album.js
@@ -48,7 +48,6 @@ routes.get('/a/:identifier', async (req, res, next) => {
if (config.uploads.generateZips) { enableDownload = true }
return res.render('album', {
- layout: false,
title: album.name,
count: files.length,
thumb,
diff --git a/routes/nojs.js b/routes/nojs.js
index 1f4d30c..2a209e8 100644
--- a/routes/nojs.js
+++ b/routes/nojs.js
@@ -3,9 +3,8 @@ const routes = require('express').Router()
const uploadController = require('./../controllers/uploadController')
const renderOptions = {
- layout: false,
uploadDisabled: false,
- maxFileSize: config.uploads.maxSize
+ maxFileSize: config.uploads.chunkedUploads.noJsMaxSize || config.uploads.maxSize
}
if (config.private) {
@@ -17,7 +16,7 @@ if (config.private) {
}
routes.get('/nojs', async (req, res, next) => {
- return res.render('nojs', renderOptions)
+ return res.render('nojs', { renderOptions })
})
routes.post('/nojs', (req, res, next) => {
@@ -25,13 +24,12 @@ routes.post('/nojs', (req, res, next) => {
res.json = (...args) => {
const result = args[0]
- const _renderOptions = {}
- Object.assign(_renderOptions, renderOptions)
+ const options = { renderOptions }
- _renderOptions.errorMessage = result.success ? '' : (result.description || 'An unexpected error occurred.')
- _renderOptions.files = result.files || [{}]
+ options.errorMessage = result.success ? '' : (result.description || 'An unexpected error occurred.')
+ options.files = result.files || [{}]
- return res.render('nojs', _renderOptions)
+ return res.render('nojs', options)
}
return uploadController.upload(req, res, next)
diff --git a/views/_globals.njk b/views/_globals.njk
index 2e8e82b..7aa6406 100644
--- a/views/_globals.njk
+++ b/views/_globals.njk
@@ -10,7 +10,7 @@
This will be appended to all CSS and JS files,
and should be changed on every updates to make sure clients load the very latest version of them.
#}
-{% set v = "8HSPG0eoRX" %}
+{% set v = "aSRDjST7cs" %}
{#
These will be the links in the homepage and the No-JS uploader.
diff --git a/views/faq.njk b/views/faq.njk
index 584b820..ba018c7 100644
--- a/views/faq.njk
+++ b/views/faq.njk
@@ -24,8 +24,7 @@
What is safe.fiery.me?
- safe.fiery.me is merely another clone of lolisafe. We accept your files, photos, documents, anything, and give you back a shareable link for you to send to others.
lolisafe itself is an easy to use, open source and completely free file
- upload service.
+ safe.fiery.me is merely another clone of
lolisafe. We accept your files, photos, documents, anything, and give you back a shareable link for you to send to others.
@@ -39,7 +38,8 @@
How can I keep track of my uploads?
- Simply create a user on the site and every upload will be associated with your account, granting you access to your uploaded files through our dashboard.
By having an account, you will also be able to set file name length for your new
+ Simply create a user on the site and every upload will be associated with your account, granting you access to your uploaded files through our dashboard.
+ By having an account, you will also be able to set file name length for your new
uploads!
@@ -47,16 +47,16 @@
Do you have any No-JS uploader?
- Yes, check out
this page.
Unfortunately you will not be able to associate your uploads to your account, if you have any.
Then again, if you want to use the No-JS uploader, then it's very likely
- that you will not use the Dashboard anyways.
+ Yes, check out
this page.
+ Unfortunately you will not be able to associate your uploads to your account, if you have any.
+ Then again, if you want to use the No-JS uploader, then it's very likely that you will not use the Dashboard anyways.
What are albums?
- Albums are a simple way of sorting uploads together. Right now you can create albums through the dashboard, then afterwards you can use them through the homepage uploader or with
our chrome extension, which will enable you to
right click -> send to lolisafe or to a desired album if you have any. You will probably have to change some things involving
https://safe.fiery.me/api/upload if you want to use the extension though.
+ Albums are a simple way of sorting uploads together. Right now you can create albums through the dashboard, then afterwards you can use them through the homepage uploader or with
our chrome extension, which will enable you to
right click -> send to lolisafe or to a desired album if you have any. You will probably have to change some things involving
https://safe.fiery.me/api/upload if you want to use the extension though.
diff --git a/views/nojs.njk b/views/nojs.njk
index 08d63f1..88b9167 100644
--- a/views/nojs.njk
+++ b/views/nojs.njk
@@ -17,7 +17,7 @@
{{ globals.home_subtitle | safe }}
- Maximum upload size per file is {{ maxFileSize }}
+ Maximum upload size per file is {{ renderOptions.maxFileSize }}
@@ -29,8 +29,8 @@
- {% if uploadDisabled -%}
-
{{ uploadDisabled }}
+ {% if renderOptions.uploadDisabled -%}
+
{{ renderOptions.uploadDisabled }}
{%- else -%}