mirror of
https://github.com/BobbyWibowo/lolisafe.git
synced 2025-01-18 17:21:33 +00:00
Implemented stripping tags from images
... and optionally videos using ffmpeg (still experimental). Users can choose whether to strip tags of their uploads or not from the home uploader's Config tab (safe.fiery.me will have it disabled by default). The behavior will also be applied to the downloadable ShareX config. Server owners can choose to force either behavior. Make sure to add the new config from config.sample.js. --- Fixed all instances of "e.i." to "e.g.". My English sucks okay. Bumped v1 version string.
This commit is contained in:
parent
337a0a61ff
commit
d9ddfe8e9a
2
TODO.md
2
TODO.md
@ -39,7 +39,7 @@ Low priority:
|
|||||||
* [x] Delete user feature.
|
* [x] Delete user feature.
|
||||||
* [ ] Bulk delete user feature.
|
* [ ] Bulk delete user feature.
|
||||||
* [ ] Bulk disable user feature.
|
* [ ] Bulk disable user feature.
|
||||||
* [ ] Strip EXIF from images. [#51](https://github.com/BobbyWibowo/lolisafe/issues/51)
|
* [x] Strip EXIF from images. [#51](https://github.com/BobbyWibowo/lolisafe/issues/51)
|
||||||
* [ ] DMCA request logs (bare text file will do), and link it in FAQ.
|
* [ ] DMCA request logs (bare text file will do), and link it in FAQ.
|
||||||
This should also include list of files that also had to be manually deleted due to triggering Google's SafeSearch (harmful downloads, etc).
|
This should also include list of files that also had to be manually deleted due to triggering Google's SafeSearch (harmful downloads, etc).
|
||||||
|
|
||||||
|
@ -325,7 +325,7 @@ module.exports = {
|
|||||||
Cache file identifiers.
|
Cache file identifiers.
|
||||||
|
|
||||||
They will be used for stricter collision checks, such that a single identifier
|
They will be used for stricter collision checks, such that a single identifier
|
||||||
may not be used by more than a single file (e.i. if "abcd.jpg" already exists, a new PNG
|
may not be used by more than a single file (e.g. if "abcd.jpg" already exists, a new PNG
|
||||||
file may not be named as "abcd.png").
|
file may not be named as "abcd.png").
|
||||||
|
|
||||||
If this is enabled, the safe will query files from the database during first launch,
|
If this is enabled, the safe will query files from the database during first launch,
|
||||||
@ -333,11 +333,11 @@ module.exports = {
|
|||||||
Its downside is that it will use a bit more memory.
|
Its downside is that it will use a bit more memory.
|
||||||
|
|
||||||
If this is disabled, collision check will become less strict.
|
If this is disabled, collision check will become less strict.
|
||||||
As in, the same identifier may be used by multiple different extensions (e.i. if "abcd.jpg"
|
As in, the same identifier may be used by multiple different extensions (e.g. if "abcd.jpg"
|
||||||
already exists, new files can be possibly be named as "abcd.png", "abcd.mp4", etc).
|
already exists, new files can be possibly be named as "abcd.png", "abcd.mp4", etc).
|
||||||
Its downside will be, in the rare chance that multiple image/video files are sharing the same
|
Its downside will be, in the rare chance that multiple image/video files are sharing the same
|
||||||
identifier, they will end up with the same thumbnail in dashboard, since thumbnails will
|
identifier, they will end up with the same thumbnail in dashboard, since thumbnails will
|
||||||
only be saved as PNG in storage (e.i. "abcd.jpg" and "abcd.png" will share a single thumbnail
|
only be saved as PNG in storage (e.g. "abcd.jpg" and "abcd.png" will share a single thumbnail
|
||||||
named "abcd.png" in thumbs directory, in which case, the file that's uploaded the earliest will
|
named "abcd.png" in thumbs directory, in which case, the file that's uploaded the earliest will
|
||||||
be the source for the thumbnail).
|
be the source for the thumbnail).
|
||||||
|
|
||||||
@ -369,6 +369,28 @@ module.exports = {
|
|||||||
placeholder: null
|
placeholder: null
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/*
|
||||||
|
Strip tags (e.g. EXIF).
|
||||||
|
|
||||||
|
"default" decides whether to strip tags or not by default,
|
||||||
|
as the behavior can be configured by users from home uploader's Config tab.
|
||||||
|
If "force" is set to true, the default behavior will be enforced.
|
||||||
|
|
||||||
|
"video" decides whether to also strip tags of vidoe files
|
||||||
|
(of course only if the default behavior is to strip tags).
|
||||||
|
However, this also requires ffmpeg (see option's note above),
|
||||||
|
and still experimental (thus use at your own risk).
|
||||||
|
|
||||||
|
NOTE: Other than setting both "default" and "force" to false,
|
||||||
|
you can also set stripTags itself to any falsy value to completely
|
||||||
|
disable this feature.
|
||||||
|
*/
|
||||||
|
stripTags: {
|
||||||
|
default: false,
|
||||||
|
video: false,
|
||||||
|
force: false
|
||||||
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Allow users to download a ZIP archive of all files in an album.
|
Allow users to download a ZIP archive of all files in an album.
|
||||||
The file is generated when the user clicks the download button in the view
|
The file is generated when the user clicks the download button in the view
|
||||||
|
@ -26,7 +26,7 @@ const maxFilesPerUpload = 20
|
|||||||
|
|
||||||
const chunkedUploads = Boolean(config.uploads.chunkSize)
|
const chunkedUploads = Boolean(config.uploads.chunkSize)
|
||||||
const chunksData = {}
|
const chunksData = {}
|
||||||
// Hard-coded min chunk size of 1 MB (e.i. 50 MB = max 50 chunks)
|
// Hard-coded min chunk size of 1 MB (e.g. 50 MB = max 50 chunks)
|
||||||
const maxChunksCount = maxSize
|
const maxChunksCount = maxSize
|
||||||
|
|
||||||
const extensionsFilter = Array.isArray(config.extensionsFilter) &&
|
const extensionsFilter = Array.isArray(config.extensionsFilter) &&
|
||||||
@ -106,7 +106,7 @@ const executeMulter = multer({
|
|||||||
.catch(error => cb(error))
|
.catch(error => cb(error))
|
||||||
}
|
}
|
||||||
|
|
||||||
// index.extension (e.i. 0, 1, ..., n - will prepend zeros depending on the amount of chunks)
|
// index.extension (i.e. 0, 1, ..., n - will prepend zeros depending on the amount of chunks)
|
||||||
const digits = req.body.totalchunkcount !== undefined ? `${req.body.totalchunkcount - 1}`.length : 1
|
const digits = req.body.totalchunkcount !== undefined ? `${req.body.totalchunkcount - 1}`.length : 1
|
||||||
const zeros = new Array(digits + 1).join('0')
|
const zeros = new Array(digits + 1).join('0')
|
||||||
const name = (zeros + req.body.chunkindex).slice(-digits)
|
const name = (zeros + req.body.chunkindex).slice(-digits)
|
||||||
@ -183,6 +183,16 @@ self.parseUploadAge = age => {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.parseStripTags = stripTags => {
|
||||||
|
if (!config.uploads.stripTags)
|
||||||
|
return false
|
||||||
|
|
||||||
|
if (config.uploads.stripTags.force || stripTags === undefined)
|
||||||
|
return config.uploads.stripTags.default
|
||||||
|
|
||||||
|
return Boolean(parseInt(stripTags))
|
||||||
|
}
|
||||||
|
|
||||||
self.upload = async (req, res, next) => {
|
self.upload = async (req, res, next) => {
|
||||||
let user
|
let user
|
||||||
if (config.private === true) {
|
if (config.private === true) {
|
||||||
@ -273,6 +283,8 @@ self.actuallyUploadFiles = async (req, res, user, albumid, age) => {
|
|||||||
if (scanResult) throw scanResult
|
if (scanResult) throw scanResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await self.stripTags(req, infoMap)
|
||||||
|
|
||||||
const result = await self.storeFilesToDb(req, res, user, infoMap)
|
const result = await self.storeFilesToDb(req, res, user, infoMap)
|
||||||
await self.sendUploadResponse(req, res, result)
|
await self.sendUploadResponse(req, res, result)
|
||||||
}
|
}
|
||||||
@ -471,6 +483,8 @@ self.actuallyFinishChunks = async (req, res, user) => {
|
|||||||
if (scanResult) throw scanResult
|
if (scanResult) throw scanResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await self.stripTags(req, infoMap)
|
||||||
|
|
||||||
const result = await self.storeFilesToDb(req, res, user, infoMap)
|
const result = await self.storeFilesToDb(req, res, user, infoMap)
|
||||||
await self.sendUploadResponse(req, res, result)
|
await self.sendUploadResponse(req, res, result)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -552,10 +566,31 @@ self.scanFiles = async (req, user, infoMap) => {
|
|||||||
return results
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.stripTags = async (req, infoMap) => {
|
||||||
|
if (!self.parseStripTags(req.headers.striptags))
|
||||||
|
return
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Promise.all(infoMap.map(info =>
|
||||||
|
utils.stripTags(info.data.filename, info.data.extname)
|
||||||
|
))
|
||||||
|
} catch (error) {
|
||||||
|
// Unlink all files when at least one threat is found OR any errors occurred
|
||||||
|
// Should continue even when encountering errors
|
||||||
|
await Promise.all(infoMap.map(info =>
|
||||||
|
utils.unlinkFile(info.data.filename).catch(logger.error)
|
||||||
|
))
|
||||||
|
|
||||||
|
// Re-throw error
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.storeFilesToDb = async (req, res, user, infoMap) => {
|
self.storeFilesToDb = async (req, res, user, infoMap) => {
|
||||||
const files = []
|
const files = []
|
||||||
const exists = []
|
const exists = []
|
||||||
const albumids = []
|
const albumids = []
|
||||||
|
|
||||||
await Promise.all(infoMap.map(async info => {
|
await Promise.all(infoMap.map(async info => {
|
||||||
// Create hash of the file
|
// Create hash of the file
|
||||||
const hash = await new Promise((resolve, reject) => {
|
const hash = await new Promise((resolve, reject) => {
|
||||||
|
@ -308,6 +308,52 @@ self.generateThumbs = async (name, extname, force) => {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.stripTags = async (name, extname) => {
|
||||||
|
const fullpath = path.join(paths.uploads, name)
|
||||||
|
|
||||||
|
if (self.imageExts.includes(extname)) {
|
||||||
|
const tmpfile = path.join(paths.uploads, `tmp-${name}`)
|
||||||
|
await paths.rename(fullpath, tmpfile)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sharp(tmpfile)
|
||||||
|
.toFile(fullpath)
|
||||||
|
await paths.unlink(tmpfile)
|
||||||
|
} catch (error) {
|
||||||
|
await paths.unlink(tmpfile)
|
||||||
|
// Re-throw error
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
} else if (config.uploads.stripTags.video && self.videoExts.includes(extname)) {
|
||||||
|
const tmpfile = path.join(paths.uploads, `tmp-${name}`)
|
||||||
|
await paths.rename(fullpath, tmpfile)
|
||||||
|
|
||||||
|
try {
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
ffmpeg(tmpfile)
|
||||||
|
.output(fullpath)
|
||||||
|
.outputOptions([
|
||||||
|
// Experimental.
|
||||||
|
'-c copy',
|
||||||
|
'-map_metadata:g -1:g',
|
||||||
|
'-map_metadata:s:v -1:g',
|
||||||
|
'-map_metadata:s:a -1:g'
|
||||||
|
])
|
||||||
|
.on('error', error => reject(error))
|
||||||
|
.on('end', () => resolve(true))
|
||||||
|
.run()
|
||||||
|
})
|
||||||
|
await paths.unlink(tmpfile)
|
||||||
|
} catch (error) {
|
||||||
|
await paths.unlink(tmpfile)
|
||||||
|
// Re-throw error
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
self.unlinkFile = async (filename, predb) => {
|
self.unlinkFile = async (filename, predb) => {
|
||||||
try {
|
try {
|
||||||
await paths.unlink(path.join(paths.uploads, filename))
|
await paths.unlink(path.join(paths.uploads, filename))
|
||||||
|
2
dist/css/style.css
vendored
2
dist/css/style.css
vendored
@ -1,2 +1,2 @@
|
|||||||
html{background-color:#000;overflow-y:auto}body{color:#eff0f1;-webkit-animation:fadeInOpacity .5s;animation:fadeInOpacity .5s}@-webkit-keyframes fadeInOpacity{0%{opacity:0}to{opacity:1}}@keyframes fadeInOpacity{0%{opacity:0}to{opacity:1}}a{color:#209cee}a:hover{color:#67c3ff}hr{background-color:#585858}.message-body code,code{background-color:#000;border-radius:5px}.title{color:#eff0f1}.subtitle,.subtitle strong{color:#bdc3c7}.input,.select select,.textarea{color:#eff0f1;border-color:#585858;background-color:#000}.input::-moz-placeholder,.textarea::-moz-placeholder{color:#bdc3c7}.input::-webkit-input-placeholder,.textarea::-webkit-input-placeholder{color:#bdc3c7}.input:-moz-placeholder,.textarea:-moz-placeholder{color:#bdc3c7}.input:-ms-input-placeholder,.textarea:-ms-input-placeholder{color:#bdc3c7}.input.is-active,.input.is-focused,.input:active,.input:focus,.input:not([disabled]):hover,.select fieldset:not([disabled]) select:hover,.select select:not([disabled]):hover,.textarea.is-active,.textarea.is-focused,.textarea:active,.textarea:focus,.textarea:not([disabled]):hover,fieldset:not([disabled]) .input:hover,fieldset:not([disabled]) .select select:hover,fieldset:not([disabled]) .textarea:hover{border-color:#209cee}.input[disabled],.select fieldset[disabled] select,.select select[disabled],.textarea[disabled],fieldset[disabled] .input,fieldset[disabled] .select select,fieldset[disabled] .textarea{border-color:#585858;background-color:#2f2f2f}.label{color:#eff0f1;font-weight:400}.help{color:#bdc3c7}.progress{background-color:#585858}.button.is-info.is-hovered [class*=" icon-"]:before,.button.is-info.is-hovered [class^=icon-]:before,.button.is-info:hover [class*=" icon-"]:before,.button.is-info:hover [class^=icon-]:before{fill:#fff}.checkbox:hover,.radio:hover{color:#7f8c8d}.select:not(.is-multiple):not(.is-loading):after,.select:not(.is-multiple):not(.is-loading):hover:after{border-color:#eff0f1}.message{background-color:#2f2f2f}.message-body{color:#eff0f1;border:0}.hero.is-fullheight>.hero-body{min-height:100vh;height:100%}.hero.is-fullheight>.hero-body>.container{width:100%}
|
html{background-color:#000;overflow-y:auto}body{color:#eff0f1;-webkit-animation:fadeInOpacity .5s;animation:fadeInOpacity .5s}@-webkit-keyframes fadeInOpacity{0%{opacity:0}to{opacity:1}}@keyframes fadeInOpacity{0%{opacity:0}to{opacity:1}}a{color:#209cee}a:hover{color:#67c3ff}hr{background-color:#585858}.message-body code,code{background-color:#000;border-radius:5px}.title{color:#eff0f1}.subtitle,.subtitle strong{color:#bdc3c7}.input,.select select,.textarea{color:#eff0f1;border-color:#585858;background-color:#000}.input::-moz-placeholder,.textarea::-moz-placeholder{color:#bdc3c7}.input::-webkit-input-placeholder,.textarea::-webkit-input-placeholder{color:#bdc3c7}.input:-moz-placeholder,.textarea:-moz-placeholder{color:#bdc3c7}.input:-ms-input-placeholder,.textarea:-ms-input-placeholder{color:#bdc3c7}.input.is-active,.input.is-focused,.input:active,.input:focus,.input:not([disabled]):hover,.select fieldset:not([disabled]) select:hover,.select select:not([disabled]):hover,.textarea.is-active,.textarea.is-focused,.textarea:active,.textarea:focus,.textarea:not([disabled]):hover,fieldset:not([disabled]) .input:hover,fieldset:not([disabled]) .select select:hover,fieldset:not([disabled]) .textarea:hover{border-color:#209cee}.input[disabled],.select fieldset[disabled] select,.select select[disabled],.textarea[disabled],fieldset[disabled] .input,fieldset[disabled] .select select,fieldset[disabled] .textarea{border-color:#585858;background-color:#2f2f2f}.label{color:#eff0f1;font-weight:400}.help{color:#bdc3c7}.progress{background-color:#585858}.button.is-info.is-hovered [class*=" icon-"]:before,.button.is-info.is-hovered [class^=icon-]:before,.button.is-info:hover [class*=" icon-"]:before,.button.is-info:hover [class^=icon-]:before{fill:#fff}.checkbox:hover,.radio:hover{color:#7f8c8d}.select:not(.is-multiple):not(.is-loading):after,.select:not(.is-multiple):not(.is-loading):hover:after{border-color:#eff0f1}.select select[disabled]:hover,fieldset[disabled] .select select:hover{border-color:#585858}.message{background-color:#2f2f2f}.message-body{color:#eff0f1;border:0}.hero.is-fullheight>.hero-body{min-height:100vh;height:100%}.hero.is-fullheight>.hero-body>.container{width:100%}
|
||||||
/*# sourceMappingURL=style.css.map */
|
/*# sourceMappingURL=style.css.map */
|
||||||
|
2
dist/css/style.css.map
vendored
2
dist/css/style.css.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"sources":["css/style.css"],"names":[],"mappings":"AAAA,KACE,qBAAsB,CACtB,eACF,CAEA,KACE,aAAc,CACd,mCAA4B,CAA5B,2BACF,CAEA,iCACE,GACE,SACF,CAEA,GACE,SACF,CACF,CAEA,yBACE,GACE,SACF,CAEA,GACE,SACF,CACF,CAEA,EACE,aACF,CAEA,QACE,aACF,CAEA,GACE,wBACF,CAEA,wBAEE,qBAAsB,CACtB,iBACF,CAEA,OACE,aACF,CAMA,2BACE,aACF,CAEA,gCAGE,aAAc,CACd,oBAAqB,CACrB,qBACF,CAEA,qDAEE,aACF,CAEA,uEAEE,aACF,CAEA,mDAEE,aACF,CAEA,6DAEE,aACF,CAYA,qZAQE,oBACF,CAEA,yLAOE,oBAAqB,CACrB,wBACF,CAEA,OACE,aAAc,CACd,eACF,CAEA,MACE,aACF,CAEA,UACE,wBACF,CAEA,gMAIE,SACF,CAEA,6BAEE,aACF,CAMA,wGACE,oBACF,CAEA,SACE,wBACF,CAEA,cACE,aAAc,CACd,QACF,CAGA,+BACE,gBAAiB,CACjB,WACF,CAGA,0CACE,UACF","file":"style.css","sourcesContent":["html {\n background-color: #000;\n overflow-y: auto\n}\n\nbody {\n color: #eff0f1;\n animation: fadeInOpacity 0.5s\n}\n\n@-webkit-keyframes fadeInOpacity {\n 0% {\n opacity: 0\n }\n\n 100% {\n opacity: 1\n }\n}\n\n@keyframes fadeInOpacity {\n 0% {\n opacity: 0\n }\n\n 100% {\n opacity: 1\n }\n}\n\na {\n color: #209cee\n}\n\na:hover {\n color: #67c3ff\n}\n\nhr {\n background-color: #585858\n}\n\ncode,\n.message-body code {\n background-color: #000;\n border-radius: 5px\n}\n\n.title {\n color: #eff0f1\n}\n\n.subtitle {\n color: #bdc3c7\n}\n\n.subtitle strong {\n color: #bdc3c7\n}\n\n.input,\n.select select,\n.textarea {\n color: #eff0f1;\n border-color: #585858;\n background-color: #000\n}\n\n.input::-moz-placeholder,\n.textarea::-moz-placeholder {\n color: #bdc3c7\n}\n\n.input::-webkit-input-placeholder,\n.textarea::-webkit-input-placeholder {\n color: #bdc3c7\n}\n\n.input:-moz-placeholder,\n.textarea:-moz-placeholder {\n color: #bdc3c7\n}\n\n.input:-ms-input-placeholder,\n.textarea:-ms-input-placeholder {\n color: #bdc3c7\n}\n\n.input:not([disabled]):hover,\n.select fieldset:not([disabled]) select:hover,\n.select select:not([disabled]):hover,\n.textarea:not([disabled]):hover,\nfieldset:not([disabled]) .input:hover,\nfieldset:not([disabled]) .select select:hover,\nfieldset:not([disabled]) .textarea:hover {\n border-color: #209cee\n}\n\n.input.is-active,\n.input.is-focused,\n.input:active,\n.input:focus,\n.textarea.is-active,\n.textarea.is-focused,\n.textarea:active,\n.textarea:focus {\n border-color: #209cee\n}\n\n.input[disabled],\n.select fieldset[disabled] select,\n.select select[disabled],\n.textarea[disabled],\nfieldset[disabled] .input,\nfieldset[disabled] .select select,\nfieldset[disabled] .textarea {\n border-color: #585858;\n background-color: #2f2f2f\n}\n\n.label {\n color: #eff0f1;\n font-weight: normal\n}\n\n.help {\n color: #bdc3c7\n}\n\n.progress {\n background-color: #585858\n}\n\n.button.is-info.is-hovered [class^=\"icon-\"]::before,\n.button.is-info.is-hovered [class*=\" icon-\"]::before,\n.button.is-info:hover [class^=\"icon-\"]::before,\n.button.is-info:hover [class*=\" icon-\"]::before {\n fill: #fff\n}\n\n.checkbox:hover,\n.radio:hover {\n color: #7f8c8d\n}\n\n.select:not(.is-multiple):not(.is-loading)::after {\n border-color: #eff0f1\n}\n\n.select:not(.is-multiple):not(.is-loading):hover::after {\n border-color: #eff0f1\n}\n\n.message {\n background-color: #2f2f2f\n}\n\n.message-body {\n color: #eff0f1;\n border: 0\n}\n\n/* https://github.com/philipwalton/flexbugs#flexbug-3 */\n.hero.is-fullheight > .hero-body {\n min-height: 100vh;\n height: 100%\n}\n\n/* https://github.com/philipwalton/flexbugs#flexbug-2 */\n.hero.is-fullheight > .hero-body > .container {\n width: 100%\n}\n"]}
|
{"version":3,"sources":["css/style.css"],"names":[],"mappings":"AAAA,KACE,qBAAsB,CACtB,eACF,CAEA,KACE,aAAc,CACd,mCAA4B,CAA5B,2BACF,CAEA,iCACE,GACE,SACF,CAEA,GACE,SACF,CACF,CAEA,yBACE,GACE,SACF,CAEA,GACE,SACF,CACF,CAEA,EACE,aACF,CAEA,QACE,aACF,CAEA,GACE,wBACF,CAEA,wBAEE,qBAAsB,CACtB,iBACF,CAEA,OACE,aACF,CAMA,2BACE,aACF,CAEA,gCAGE,aAAc,CACd,oBAAqB,CACrB,qBACF,CAEA,qDAEE,aACF,CAEA,uEAEE,aACF,CAEA,mDAEE,aACF,CAEA,6DAEE,aACF,CAYA,qZAQE,oBACF,CAEA,yLAOE,oBAAqB,CACrB,wBACF,CAEA,OACE,aAAc,CACd,eACF,CAEA,MACE,aACF,CAEA,UACE,wBACF,CAEA,gMAIE,SACF,CAEA,6BAEE,aACF,CAMA,wGACE,oBACF,CAEA,uEAEE,oBACF,CAEA,SACE,wBACF,CAEA,cACE,aAAc,CACd,QACF,CAGA,+BACE,gBAAiB,CACjB,WACF,CAGA,0CACE,UACF","file":"style.css","sourcesContent":["html {\n background-color: #000;\n overflow-y: auto\n}\n\nbody {\n color: #eff0f1;\n animation: fadeInOpacity 0.5s\n}\n\n@-webkit-keyframes fadeInOpacity {\n 0% {\n opacity: 0\n }\n\n 100% {\n opacity: 1\n }\n}\n\n@keyframes fadeInOpacity {\n 0% {\n opacity: 0\n }\n\n 100% {\n opacity: 1\n }\n}\n\na {\n color: #209cee\n}\n\na:hover {\n color: #67c3ff\n}\n\nhr {\n background-color: #585858\n}\n\ncode,\n.message-body code {\n background-color: #000;\n border-radius: 5px\n}\n\n.title {\n color: #eff0f1\n}\n\n.subtitle {\n color: #bdc3c7\n}\n\n.subtitle strong {\n color: #bdc3c7\n}\n\n.input,\n.select select,\n.textarea {\n color: #eff0f1;\n border-color: #585858;\n background-color: #000\n}\n\n.input::-moz-placeholder,\n.textarea::-moz-placeholder {\n color: #bdc3c7\n}\n\n.input::-webkit-input-placeholder,\n.textarea::-webkit-input-placeholder {\n color: #bdc3c7\n}\n\n.input:-moz-placeholder,\n.textarea:-moz-placeholder {\n color: #bdc3c7\n}\n\n.input:-ms-input-placeholder,\n.textarea:-ms-input-placeholder {\n color: #bdc3c7\n}\n\n.input:not([disabled]):hover,\n.select fieldset:not([disabled]) select:hover,\n.select select:not([disabled]):hover,\n.textarea:not([disabled]):hover,\nfieldset:not([disabled]) .input:hover,\nfieldset:not([disabled]) .select select:hover,\nfieldset:not([disabled]) .textarea:hover {\n border-color: #209cee\n}\n\n.input.is-active,\n.input.is-focused,\n.input:active,\n.input:focus,\n.textarea.is-active,\n.textarea.is-focused,\n.textarea:active,\n.textarea:focus {\n border-color: #209cee\n}\n\n.input[disabled],\n.select fieldset[disabled] select,\n.select select[disabled],\n.textarea[disabled],\nfieldset[disabled] .input,\nfieldset[disabled] .select select,\nfieldset[disabled] .textarea {\n border-color: #585858;\n background-color: #2f2f2f\n}\n\n.label {\n color: #eff0f1;\n font-weight: normal\n}\n\n.help {\n color: #bdc3c7\n}\n\n.progress {\n background-color: #585858\n}\n\n.button.is-info.is-hovered [class^=\"icon-\"]::before,\n.button.is-info.is-hovered [class*=\" icon-\"]::before,\n.button.is-info:hover [class^=\"icon-\"]::before,\n.button.is-info:hover [class*=\" icon-\"]::before {\n fill: #fff\n}\n\n.checkbox:hover,\n.radio:hover {\n color: #7f8c8d\n}\n\n.select:not(.is-multiple):not(.is-loading)::after {\n border-color: #eff0f1\n}\n\n.select:not(.is-multiple):not(.is-loading):hover::after {\n border-color: #eff0f1\n}\n\n.select select[disabled]:hover,\nfieldset[disabled] .select select:hover {\n border-color: #585858\n}\n\n.message {\n background-color: #2f2f2f\n}\n\n.message-body {\n color: #eff0f1;\n border: 0\n}\n\n/* https://github.com/philipwalton/flexbugs#flexbug-3 */\n.hero.is-fullheight > .hero-body {\n min-height: 100vh;\n height: 100%\n}\n\n/* https://github.com/philipwalton/flexbugs#flexbug-2 */\n.hero.is-fullheight > .hero-body > .container {\n width: 100%\n}\n"]}
|
2
dist/js/home.js
vendored
2
dist/js/home.js
vendored
File diff suppressed because one or more lines are too long
2
dist/js/home.js.map
vendored
2
dist/js/home.js.map
vendored
File diff suppressed because one or more lines are too long
2
dist/js/misc/utils.js
vendored
2
dist/js/misc/utils.js
vendored
@ -1,2 +1,2 @@
|
|||||||
lsKeys.siBytes="siBytes",page.prepareShareX=function(){var e=page.token?{token:page.token||"",albumid:page.album||""}:{};e.filelength=page.fileLength||"",e.age=page.uploadAge||"";for(var t=[],a=Object.keys(e),n=0;n<a.length;n++)t.push(' "'+a[n]+'": "'+e[a[n]]+'"');var o=(location.hostname+location.pathname).replace(/\/(dashboard)?$/,""),r=o.replace(/\//g,"_"),i=document.querySelector("#ShareX"),l='{\n "Name": "'+r+'",\n "DestinationType": "ImageUploader, FileUploader",\n "RequestMethod": "POST",\n "RequestURL": "'+location.protocol+"//"+o+'/api/upload",\n "Headers": {\n'+t.join(",\n")+'\n },\n "Body": "MultipartFormData",\n "FileFormName": "files[]",\n "URL": "$json:files[0].url$",\n "ThumbnailURL": "$json:files[0].url$"\n}',s=new Blob([l],{type:"application/octet-binary"});i.setAttribute("href",URL.createObjectURL(s)),i.setAttribute("download",r+".sxcu")},page.getPrettyDate=function(e){return e.getFullYear()+"-"+(e.getMonth()<9?"0":"")+(e.getMonth()+1)+"-"+(e.getDate()<10?"0":"")+e.getDate()+" "+(e.getHours()<10?"0":"")+e.getHours()+":"+(e.getMinutes()<10?"0":"")+e.getMinutes()+":"+(e.getSeconds()<10?"0":"")+e.getSeconds()},page.getPrettyBytes=function(e){if("number"!=typeof e&&!isFinite(e))return e;var t="0"!==localStorage[lsKeys.siBytes],a=e<0?"-":"",n=t?1e3:1024;if(a&&(e=-e),e<n)return""+a+e+" B";var o=Math.min(Math.floor(Math.log(e)*Math.LOG10E/3),8);return""+a+Number((e/Math.pow(n,o)).toPrecision(3))+" "+((t?"kMGTPEZY":"KMGTPEZY").charAt(o-1)+(t?"":"i"))+"B"};
|
lsKeys.siBytes="siBytes",page.prepareShareX=function(){var e=page.token?{token:page.token||"",albumid:page.album||""}:{};e.filelength=page.fileLength||"",e.age=page.uploadAge||"",e.striptags=page.stripTags||"";for(var t=[],a=Object.keys(e),n=0;n<a.length;n++)t.push(' "'+a[n]+'": "'+e[a[n]]+'"');var o=(location.hostname+location.pathname).replace(/\/(dashboard)?$/,""),r=o.replace(/\//g,"_"),i=document.querySelector("#ShareX"),s='{\n "Name": "'+r+'",\n "DestinationType": "ImageUploader, FileUploader",\n "RequestMethod": "POST",\n "RequestURL": "'+location.protocol+"//"+o+'/api/upload",\n "Headers": {\n'+t.join(",\n")+'\n },\n "Body": "MultipartFormData",\n "FileFormName": "files[]",\n "URL": "$json:files[0].url$",\n "ThumbnailURL": "$json:files[0].url$"\n}',l=new Blob([s],{type:"application/octet-binary"});i.setAttribute("href",URL.createObjectURL(l)),i.setAttribute("download",r+".sxcu")},page.getPrettyDate=function(e){return e.getFullYear()+"-"+(e.getMonth()<9?"0":"")+(e.getMonth()+1)+"-"+(e.getDate()<10?"0":"")+e.getDate()+" "+(e.getHours()<10?"0":"")+e.getHours()+":"+(e.getMinutes()<10?"0":"")+e.getMinutes()+":"+(e.getSeconds()<10?"0":"")+e.getSeconds()},page.getPrettyBytes=function(e){if("number"!=typeof e&&!isFinite(e))return e;var t="0"!==localStorage[lsKeys.siBytes],a=e<0?"-":"",n=t?1e3:1024;if(a&&(e=-e),e<n)return""+a+e+" B";var o=Math.min(Math.floor(Math.log(e)*Math.LOG10E/3),8);return""+a+Number((e/Math.pow(n,o)).toPrecision(3))+" "+((t?"kMGTPEZY":"KMGTPEZY").charAt(o-1)+(t?"":"i"))+"B"};
|
||||||
//# sourceMappingURL=utils.js.map
|
//# sourceMappingURL=utils.js.map
|
||||||
|
2
dist/js/misc/utils.js.map
vendored
2
dist/js/misc/utils.js.map
vendored
@ -1 +1 @@
|
|||||||
{"version":3,"sources":["utils.js"],"names":["lsKeys","siBytes","page","prepareShareX","const","values","token","albumid","album","filelength","fileLength","age","uploadAge","headers","keys","Object","i","length","push","origin","location","hostname","pathname","replace","originClean","sharexElement","document","querySelector","sharexFile","join","sharexBlob","Blob","type","setAttribute","URL","createObjectURL","getPrettyDate","date","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","getPrettyBytes","num","isFinite","si","localStorage","neg","scale","exponent","Math","min","floor","log","LOG10E","Number","pow","toPrecision","charAt"],"mappings":"AAGAA,OAAOC,QAAU,UAEjBC,KAAKC,cAAa,WAChBC,IAAMC,EAASH,KAAKI,MAAQ,CAC1BA,MAAOJ,KAAKI,OAAS,GACrBC,QAASL,KAAKM,OAAS,IACrB,GACJH,EAAOI,WAAaP,KAAKQ,YAAc,GACvCL,EAAOM,IAAMT,KAAKU,WAAa,GAI/B,IAFAR,IAAMS,EAAU,GACVC,EAAOC,OAAOD,KAAKT,GAChBW,EAAI,EAAGA,EAAIF,EAAKG,OAAQD,IAE/BH,EAAQK,KAAK,QAAQJ,EAAKE,GAAE,OAAOX,EAAOS,EAAKE,IAAG,KAEpDZ,IAAMe,GAAUC,SAASC,SAAWD,SAASE,UAAUC,QAAQ,kBAAmB,IAC5EC,EAAcL,EAAOI,QAAQ,MAAO,KAEpCE,EAAgBC,SAASC,cAAc,WACvCC,EAAa,iBACRJ,EAAW,yGAGLJ,SAAS,SAAQ,KAAKD,EAAM,kCAE7CN,EAAQgB,KAAK,OAAM,oJAQbC,EAAa,IAAIC,KAAK,CAACH,GAAa,CAAEI,KAAM,6BAElDP,EAAcQ,aAAa,OAAQC,IAAIC,gBAAgBL,IACvDL,EAAcQ,aAAa,WAAeT,EAAW,UAGvDtB,KAAKkC,cAAa,SAAGC,GACnB,OAAOA,EAAKC,cAAgB,KACzBD,EAAKE,WAAa,EAAI,IAAM,KAC5BF,EAAKE,WAAa,GAAK,KACvBF,EAAKG,UAAY,GAAK,IAAM,IAC7BH,EAAKG,UAAY,KAChBH,EAAKI,WAAa,GAAK,IAAM,IAC9BJ,EAAKI,WAAa,KACjBJ,EAAKK,aAAe,GAAK,IAAM,IAChCL,EAAKK,aAAe,KACnBL,EAAKM,aAAe,GAAK,IAAM,IAChCN,EAAKM,cAGTzC,KAAK0C,eAAc,SAAGC,GAGpB,GAAmB,iBAARA,IAAqBC,SAASD,GAAM,OAAOA,EAEtDzC,IAAM2C,EAAsC,MAAjCC,aAAahD,OAAOC,SACzBgD,EAAMJ,EAAM,EAAI,IAAM,GACtBK,EAAQH,EAAK,IAAO,KAE1B,GADIE,IAAKJ,GAAOA,GACZA,EAAMK,EAAO,MAAO,GAAGD,EAAMJ,EAAG,KAEpCzC,IAAM+C,EAAWC,KAAKC,IAAID,KAAKE,MAAOF,KAAKG,IAAIV,GAAOO,KAAKI,OAAU,GAAI,GAGzE,MAAO,GAAGP,EAFKQ,QAAQZ,EAAMO,KAAKM,IAAIR,EAAOC,IAAWQ,YAAY,IAE9C,MADTZ,EAAK,WAAa,YAAYa,OAAOT,EAAW,IAAMJ,EAAK,GAAK,MAChD","file":"utils.js","sourcesContent":["/* global lsKeys, page */\n\n// keys for localStorage\nlsKeys.siBytes = 'siBytes'\n\npage.prepareShareX = () => {\n const values = page.token ? {\n token: page.token || '',\n albumid: page.album || ''\n } : {}\n values.filelength = page.fileLength || ''\n values.age = page.uploadAge || ''\n\n const headers = []\n const keys = Object.keys(values)\n for (let i = 0; i < keys.length; i++)\n // Pad by 4 space\n headers.push(` \"${keys[i]}\": \"${values[keys[i]]}\"`)\n\n const origin = (location.hostname + location.pathname).replace(/\\/(dashboard)?$/, '')\n const originClean = origin.replace(/\\//g, '_')\n\n const sharexElement = document.querySelector('#ShareX')\n const sharexFile = `{\n \"Name\": \"${originClean}\",\n \"DestinationType\": \"ImageUploader, FileUploader\",\n \"RequestMethod\": \"POST\",\n \"RequestURL\": \"${location.protocol}//${origin}/api/upload\",\n \"Headers\": {\n${headers.join(',\\n')}\n },\n \"Body\": \"MultipartFormData\",\n \"FileFormName\": \"files[]\",\n \"URL\": \"$json:files[0].url$\",\n \"ThumbnailURL\": \"$json:files[0].url$\"\n}`\n\n const sharexBlob = new Blob([sharexFile], { type: 'application/octet-binary' })\n /* eslint-disable-next-line compat/compat */\n sharexElement.setAttribute('href', URL.createObjectURL(sharexBlob))\n sharexElement.setAttribute('download', `${originClean}.sxcu`)\n}\n\npage.getPrettyDate = date => {\n return date.getFullYear() + '-' +\n (date.getMonth() < 9 ? '0' : '') + // month's index starts from zero\n (date.getMonth() + 1) + '-' +\n (date.getDate() < 10 ? '0' : '') +\n date.getDate() + ' ' +\n (date.getHours() < 10 ? '0' : '') +\n date.getHours() + ':' +\n (date.getMinutes() < 10 ? '0' : '') +\n date.getMinutes() + ':' +\n (date.getSeconds() < 10 ? '0' : '') +\n date.getSeconds()\n}\n\npage.getPrettyBytes = num => {\n // MIT License\n // Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n if (typeof num !== 'number' && !isFinite(num)) return num\n\n const si = localStorage[lsKeys.siBytes] !== '0'\n const neg = num < 0 ? '-' : ''\n const scale = si ? 1000 : 1024\n if (neg) num = -num\n if (num < scale) return `${neg}${num} B`\n\n const exponent = Math.min(Math.floor((Math.log(num) * Math.LOG10E) / 3), 8) // 8 is count of KMGTPEZY\n const numStr = Number((num / Math.pow(scale, exponent)).toPrecision(3))\n const pre = (si ? 'kMGTPEZY' : 'KMGTPEZY').charAt(exponent - 1) + (si ? '' : 'i')\n return `${neg}${numStr} ${pre}B`\n}\n"]}
|
{"version":3,"sources":["utils.js"],"names":["lsKeys","siBytes","page","prepareShareX","const","values","token","albumid","album","filelength","fileLength","age","uploadAge","striptags","stripTags","headers","keys","Object","i","length","push","origin","location","hostname","pathname","replace","originClean","sharexElement","document","querySelector","sharexFile","join","sharexBlob","Blob","type","setAttribute","URL","createObjectURL","getPrettyDate","date","getFullYear","getMonth","getDate","getHours","getMinutes","getSeconds","getPrettyBytes","num","isFinite","si","localStorage","neg","scale","exponent","Math","min","floor","log","LOG10E","Number","pow","toPrecision","charAt"],"mappings":"AAGAA,OAAOC,QAAU,UAEjBC,KAAKC,cAAa,WAChBC,IAAMC,EAASH,KAAKI,MAAQ,CAC1BA,MAAOJ,KAAKI,OAAS,GACrBC,QAASL,KAAKM,OAAS,IACrB,GACJH,EAAOI,WAAaP,KAAKQ,YAAc,GACvCL,EAAOM,IAAMT,KAAKU,WAAa,GAC/BP,EAAOQ,UAAYX,KAAKY,WAAa,GAIrC,IAFAV,IAAMW,EAAU,GACVC,EAAOC,OAAOD,KAAKX,GAChBa,EAAI,EAAGA,EAAIF,EAAKG,OAAQD,IAE/BH,EAAQK,KAAK,QAAQJ,EAAKE,GAAE,OAAOb,EAAOW,EAAKE,IAAG,KAEpDd,IAAMiB,GAAUC,SAASC,SAAWD,SAASE,UAAUC,QAAQ,kBAAmB,IAC5EC,EAAcL,EAAOI,QAAQ,MAAO,KAEpCE,EAAgBC,SAASC,cAAc,WACvCC,EAAa,iBACRJ,EAAW,yGAGLJ,SAAS,SAAQ,KAAKD,EAAM,kCAE7CN,EAAQgB,KAAK,OAAM,oJAQbC,EAAa,IAAIC,KAAK,CAACH,GAAa,CAAEI,KAAM,6BAElDP,EAAcQ,aAAa,OAAQC,IAAIC,gBAAgBL,IACvDL,EAAcQ,aAAa,WAAeT,EAAW,UAGvDxB,KAAKoC,cAAa,SAAGC,GACnB,OAAOA,EAAKC,cAAgB,KACzBD,EAAKE,WAAa,EAAI,IAAM,KAC5BF,EAAKE,WAAa,GAAK,KACvBF,EAAKG,UAAY,GAAK,IAAM,IAC7BH,EAAKG,UAAY,KAChBH,EAAKI,WAAa,GAAK,IAAM,IAC9BJ,EAAKI,WAAa,KACjBJ,EAAKK,aAAe,GAAK,IAAM,IAChCL,EAAKK,aAAe,KACnBL,EAAKM,aAAe,GAAK,IAAM,IAChCN,EAAKM,cAGT3C,KAAK4C,eAAc,SAAGC,GAGpB,GAAmB,iBAARA,IAAqBC,SAASD,GAAM,OAAOA,EAEtD3C,IAAM6C,EAAsC,MAAjCC,aAAalD,OAAOC,SACzBkD,EAAMJ,EAAM,EAAI,IAAM,GACtBK,EAAQH,EAAK,IAAO,KAE1B,GADIE,IAAKJ,GAAOA,GACZA,EAAMK,EAAO,MAAO,GAAGD,EAAMJ,EAAG,KAEpC3C,IAAMiD,EAAWC,KAAKC,IAAID,KAAKE,MAAOF,KAAKG,IAAIV,GAAOO,KAAKI,OAAU,GAAI,GAGzE,MAAO,GAAGP,EAFKQ,QAAQZ,EAAMO,KAAKM,IAAIR,EAAOC,IAAWQ,YAAY,IAE9C,MADTZ,EAAK,WAAa,YAAYa,OAAOT,EAAW,IAAMJ,EAAK,GAAK,MAChD","file":"utils.js","sourcesContent":["/* global lsKeys, page */\n\n// keys for localStorage\nlsKeys.siBytes = 'siBytes'\n\npage.prepareShareX = () => {\n const values = page.token ? {\n token: page.token || '',\n albumid: page.album || ''\n } : {}\n values.filelength = page.fileLength || ''\n values.age = page.uploadAge || ''\n values.striptags = page.stripTags || ''\n\n const headers = []\n const keys = Object.keys(values)\n for (let i = 0; i < keys.length; i++)\n // Pad by 4 space\n headers.push(` \"${keys[i]}\": \"${values[keys[i]]}\"`)\n\n const origin = (location.hostname + location.pathname).replace(/\\/(dashboard)?$/, '')\n const originClean = origin.replace(/\\//g, '_')\n\n const sharexElement = document.querySelector('#ShareX')\n const sharexFile = `{\n \"Name\": \"${originClean}\",\n \"DestinationType\": \"ImageUploader, FileUploader\",\n \"RequestMethod\": \"POST\",\n \"RequestURL\": \"${location.protocol}//${origin}/api/upload\",\n \"Headers\": {\n${headers.join(',\\n')}\n },\n \"Body\": \"MultipartFormData\",\n \"FileFormName\": \"files[]\",\n \"URL\": \"$json:files[0].url$\",\n \"ThumbnailURL\": \"$json:files[0].url$\"\n}`\n\n const sharexBlob = new Blob([sharexFile], { type: 'application/octet-binary' })\n /* eslint-disable-next-line compat/compat */\n sharexElement.setAttribute('href', URL.createObjectURL(sharexBlob))\n sharexElement.setAttribute('download', `${originClean}.sxcu`)\n}\n\npage.getPrettyDate = date => {\n return date.getFullYear() + '-' +\n (date.getMonth() < 9 ? '0' : '') + // month's index starts from zero\n (date.getMonth() + 1) + '-' +\n (date.getDate() < 10 ? '0' : '') +\n date.getDate() + ' ' +\n (date.getHours() < 10 ? '0' : '') +\n date.getHours() + ':' +\n (date.getMinutes() < 10 ? '0' : '') +\n date.getMinutes() + ':' +\n (date.getSeconds() < 10 ? '0' : '') +\n date.getSeconds()\n}\n\npage.getPrettyBytes = num => {\n // MIT License\n // Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n if (typeof num !== 'number' && !isFinite(num)) return num\n\n const si = localStorage[lsKeys.siBytes] !== '0'\n const neg = num < 0 ? '-' : ''\n const scale = si ? 1000 : 1024\n if (neg) num = -num\n if (num < scale) return `${neg}${num} B`\n\n const exponent = Math.min(Math.floor((Math.log(num) * Math.LOG10E) / 3), 8) // 8 is count of KMGTPEZY\n const numStr = Number((num / Math.pow(scale, exponent)).toPrecision(3))\n const pre = (si ? 'kMGTPEZY' : 'KMGTPEZY').charAt(exponent - 1) + (si ? '' : 'i')\n return `${neg}${numStr} ${pre}B`\n}\n"]}
|
@ -13,7 +13,8 @@ routes.get('/check', (req, res, next) => {
|
|||||||
maxSize: config.uploads.maxSize,
|
maxSize: config.uploads.maxSize,
|
||||||
chunkSize: config.uploads.chunkSize,
|
chunkSize: config.uploads.chunkSize,
|
||||||
temporaryUploadAges: config.uploads.temporaryUploadAges,
|
temporaryUploadAges: config.uploads.temporaryUploadAges,
|
||||||
fileIdentifierLength: config.uploads.fileIdentifierLength
|
fileIdentifierLength: config.uploads.fileIdentifierLength,
|
||||||
|
stripTags: config.uploads.stripTags
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -151,6 +151,11 @@ fieldset[disabled] .textarea {
|
|||||||
border-color: #eff0f1
|
border-color: #eff0f1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.select select[disabled]:hover,
|
||||||
|
fieldset[disabled] .select select:hover {
|
||||||
|
border-color: #585858
|
||||||
|
}
|
||||||
|
|
||||||
.message {
|
.message {
|
||||||
background-color: #2f2f2f
|
background-color: #2f2f2f
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@ const lsKeys = {
|
|||||||
uploadsHistoryOrder: 'uploadsHistoryOrder',
|
uploadsHistoryOrder: 'uploadsHistoryOrder',
|
||||||
previewImages: 'previewImages',
|
previewImages: 'previewImages',
|
||||||
fileLength: 'fileLength',
|
fileLength: 'fileLength',
|
||||||
uploadAge: 'uploadAge'
|
uploadAge: 'uploadAge',
|
||||||
|
stripTags: 'stripTags'
|
||||||
}
|
}
|
||||||
|
|
||||||
const page = {
|
const page = {
|
||||||
@ -21,6 +22,7 @@ const page = {
|
|||||||
chunkSize: null,
|
chunkSize: null,
|
||||||
temporaryUploadAges: null,
|
temporaryUploadAges: null,
|
||||||
fileIdentifierLength: null,
|
fileIdentifierLength: null,
|
||||||
|
stripTagsConfig: null,
|
||||||
|
|
||||||
// store album id that will be used with upload requests
|
// store album id that will be used with upload requests
|
||||||
album: null,
|
album: null,
|
||||||
@ -137,6 +139,7 @@ page.checkIfPublic = () => {
|
|||||||
page.chunkSize = parseInt(response.data.chunkSize)
|
page.chunkSize = parseInt(response.data.chunkSize)
|
||||||
page.temporaryUploadAges = response.data.temporaryUploadAges
|
page.temporaryUploadAges = response.data.temporaryUploadAges
|
||||||
page.fileIdentifierLength = response.data.fileIdentifierLength
|
page.fileIdentifierLength = response.data.fileIdentifierLength
|
||||||
|
page.stripTagsConfig = response.data.stripTags
|
||||||
return page.preparePage()
|
return page.preparePage()
|
||||||
}).catch(page.onInitError)
|
}).catch(page.onInitError)
|
||||||
}
|
}
|
||||||
@ -343,6 +346,7 @@ page.prepareDropzone = () => {
|
|||||||
if (page.album !== null) xhr.setRequestHeader('albumid', page.album)
|
if (page.album !== null) xhr.setRequestHeader('albumid', page.album)
|
||||||
if (page.fileLength !== null) xhr.setRequestHeader('filelength', page.fileLength)
|
if (page.fileLength !== null) xhr.setRequestHeader('filelength', page.fileLength)
|
||||||
if (page.uploadAge !== null) xhr.setRequestHeader('age', page.uploadAge)
|
if (page.uploadAge !== null) xhr.setRequestHeader('age', page.uploadAge)
|
||||||
|
if (page.stripTags !== null) xhr.setRequestHeader('striptags', page.stripTags)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file.upload.chunked)
|
if (!file.upload.chunked)
|
||||||
@ -430,7 +434,10 @@ page.prepareDropzone = () => {
|
|||||||
}]
|
}]
|
||||||
}, {
|
}, {
|
||||||
headers: {
|
headers: {
|
||||||
token: page.token
|
token: page.token,
|
||||||
|
// Unlike the options above (e.g. albumid, filelength, etc.),
|
||||||
|
// strip tags can not yet be configured per file with this API
|
||||||
|
striptags: page.stripTags
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
// Format error for display purpose
|
// Format error for display purpose
|
||||||
@ -581,7 +588,7 @@ page.updateTemplate = (file, response) => {
|
|||||||
img.classList.remove('is-hidden')
|
img.classList.remove('is-hidden')
|
||||||
img.onerror = event => {
|
img.onerror = event => {
|
||||||
// Hide image elements that fail to load
|
// Hide image elements that fail to load
|
||||||
// Consequently include WEBP in browsers that do not have WEBP support (e.i. IE)
|
// Consequently include WEBP in browsers that do not have WEBP support (e.g. IE)
|
||||||
event.currentTarget.classList.add('is-hidden')
|
event.currentTarget.classList.add('is-hidden')
|
||||||
page.updateTemplateIcon(file.previewElement, 'icon-picture')
|
page.updateTemplateIcon(file.previewElement, 'icon-picture')
|
||||||
}
|
}
|
||||||
@ -708,7 +715,18 @@ page.prepareUploadConfig = () => {
|
|||||||
display: temporaryUploadAges,
|
display: temporaryUploadAges,
|
||||||
label: 'Upload age',
|
label: 'Upload age',
|
||||||
select: [],
|
select: [],
|
||||||
help: 'This allows your files to automatically be deleted after a certain period of time.'
|
help: 'Whether to automatically delete your uploads after a certain amount of time.'
|
||||||
|
},
|
||||||
|
stripTags: {
|
||||||
|
display: page.stripTagsConfig,
|
||||||
|
label: 'Strip tags',
|
||||||
|
select: page.stripTagsConfig ? [
|
||||||
|
{ value: page.stripTagsConfig.default ? 'default' : '1', text: 'Yes' },
|
||||||
|
{ value: page.stripTagsConfig.default ? '0' : 'default', text: 'No' }
|
||||||
|
] : null,
|
||||||
|
help: `Whether to strip tags (e.g. EXIF) from your uploads.<br>
|
||||||
|
This only applies to regular image${page.stripTagsConfig && page.stripTagsConfig.video ? ' and video' : ''} uploads (i.e. not URL uploads).`,
|
||||||
|
disabled: page.stripTagsConfig && page.stripTagsConfig.force
|
||||||
},
|
},
|
||||||
chunkSize: {
|
chunkSize: {
|
||||||
display: !isNaN(page.chunkSize),
|
display: !isNaN(page.chunkSize),
|
||||||
@ -736,8 +754,8 @@ page.prepareUploadConfig = () => {
|
|||||||
{ value: 'default', text: 'Older files on top' },
|
{ value: 'default', text: 'Older files on top' },
|
||||||
{ value: '0', text: 'Newer files on top' }
|
{ value: '0', text: 'Newer files on top' }
|
||||||
],
|
],
|
||||||
help: `Newer files on top will use <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction#Accessibility_Concerns" target="_blank" rel="noopener">a CSS technique</a>.<br>
|
help: `"Newer files on top" will use a CSS technique, which unfortunately come with <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction#Accessibility_Concerns" target="_blank" rel="noopener">some undesirable side effects</a>.<br>
|
||||||
Trying to select their texts manually from top to bottom will end up selecting the texts from bottom to top instead.`,
|
This also affects text selection, such as when trying to select text from top to bottom will result in them being selected from bottom to top instead, and vice versa.`,
|
||||||
valueHandler (value) {
|
valueHandler (value) {
|
||||||
if (value === '0') {
|
if (value === '0') {
|
||||||
const uploadFields = document.querySelectorAll('.tab-content > .uploads')
|
const uploadFields = document.querySelectorAll('.tab-content > .uploads')
|
||||||
@ -807,7 +825,11 @@ page.prepareUploadConfig = () => {
|
|||||||
if (!isNaN(parsed))
|
if (!isNaN(parsed))
|
||||||
value = parsed
|
value = parsed
|
||||||
} else {
|
} else {
|
||||||
value = localStorage[lsKeys[key]]
|
const stored = localStorage[lsKeys[key]]
|
||||||
|
if (Array.isArray(conf.select))
|
||||||
|
value = conf.select.find(sel => sel.value === stored) ? stored : undefined
|
||||||
|
else
|
||||||
|
value = stored
|
||||||
}
|
}
|
||||||
|
|
||||||
// If valueHandler function exists, defer to the function,
|
// If valueHandler function exists, defer to the function,
|
||||||
@ -826,7 +848,8 @@ page.prepareUploadConfig = () => {
|
|||||||
const opts = []
|
const opts = []
|
||||||
for (let j = 0; j < conf.select.length; j++) {
|
for (let j = 0; j < conf.select.length; j++) {
|
||||||
const opt = conf.select[j]
|
const opt = conf.select[j]
|
||||||
const selected = value && (opt.value === String(value))
|
const selected = (value && (opt.value === String(value))) ||
|
||||||
|
(value === undefined && opt.value === 'default')
|
||||||
opts.push(`
|
opts.push(`
|
||||||
<option value="${opt.value}"${selected ? ' selected' : ''}>
|
<option value="${opt.value}"${selected ? ' selected' : ''}>
|
||||||
${opt.text}${opt.value === 'default' ? ' (default)' : ''}
|
${opt.text}${opt.value === 'default' ? ' (default)' : ''}
|
||||||
@ -857,8 +880,11 @@ page.prepareUploadConfig = () => {
|
|||||||
|
|
||||||
let help
|
let help
|
||||||
if (conf.disabled) {
|
if (conf.disabled) {
|
||||||
control.disabled = conf.disabled
|
if (Array.isArray(conf.select))
|
||||||
help = 'This option is currently disabled.'
|
control.querySelector('select').disabled = conf.disabled
|
||||||
|
else
|
||||||
|
control.disabled = conf.disabled
|
||||||
|
help = 'This option is currently not configurable.'
|
||||||
} else if (typeof conf.help === 'string') {
|
} else if (typeof conf.help === 'string') {
|
||||||
help = conf.help
|
help = conf.help
|
||||||
} else if (conf.help === true && conf.number !== undefined) {
|
} else if (conf.help === true && conf.number !== undefined) {
|
||||||
|
@ -10,6 +10,7 @@ page.prepareShareX = () => {
|
|||||||
} : {}
|
} : {}
|
||||||
values.filelength = page.fileLength || ''
|
values.filelength = page.fileLength || ''
|
||||||
values.age = page.uploadAge || ''
|
values.age = page.uploadAge || ''
|
||||||
|
values.striptags = page.stripTags || ''
|
||||||
|
|
||||||
const headers = []
|
const headers = []
|
||||||
const keys = Object.keys(values)
|
const keys = Object.keys(values)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"1": "1575024012",
|
"1": "1575034913",
|
||||||
"2": "1568894058",
|
"2": "1568894058",
|
||||||
"3": "1568894058",
|
"3": "1568894058",
|
||||||
"4": "1568894058",
|
"4": "1568894058",
|
||||||
|
Loading…
Reference in New Issue
Block a user