From 40dd66297612b2a8429c8fcad2b07170a3ba582b Mon Sep 17 00:00:00 2001 From: Bobby Wibowo Date: Sat, 20 Jun 2020 04:01:16 +0700 Subject: [PATCH] Removed delete URL from upload response I wasn't aware ShareX wouldn't do a basic GET request to the delete URL, but would instead open your browser to it. Unfortunately, due to the structure of lolisafe auth setting token through HTTP header, which had always been done by JS as it has to get the value from local storage, just visiting the API from browser will merely respond with "No token provided". We'd need cookie-based auth, which I do not want to add. The old me that added deletion API long ago might have been aware of this fact, but the me of a few hours ago already forgot.. I'll give this further thoughts at a later date, as ShareX isn't really a priority to me. Bumped v1 version string and rebuilt client assets. --- controllers/uploadController.js | 5 +++++ dist/js/misc/utils.js | 2 +- dist/js/misc/utils.js.map | 2 +- src/js/misc/utils.js | 2 ++ src/versions.json | 2 +- 5 files changed, 10 insertions(+), 3 deletions(-) diff --git a/controllers/uploadController.js b/controllers/uploadController.js index 0b08ae3..be173b9 100644 --- a/controllers/uploadController.js +++ b/controllers/uploadController.js @@ -753,8 +753,13 @@ self.sendUploadResponse = async (req, res, user, result) => { // If uploaded by user, add delete URL (intended for ShareX and its derivatives) // Homepage uploader will not use this (use dashboard instead) + // REVISION: I wasn't aware ShareX wouldn't do a basic GET request to this API, + // which I hoped would then use the token header in the downloadable ShareX config file. + // At its current state, this isn't really usable. + /* if (user) map.deleteUrl = `${config.homeDomain}/api/upload/delete/${file.name}` + */ return map }) diff --git a/dist/js/misc/utils.js b/dist/js/misc/utils.js index fc2930b..8e8f987 100644 --- a/dist/js/misc/utils.js +++ b/dist/js/misc/utils.js @@ -1,2 +1,2 @@ -lsKeys.siBytes="siBytes",page.prepareShareX=function(){var e=document.querySelector("#ShareX");if(e){var t={};page.token&&(t.token=page.token||"",t.albumid=page.album||""),t.filelength=page.fileLength||"",t.age=page.uploadAge||"",t.striptags=page.stripTags||"";var a=(window.location.hostname+window.location.pathname).replace(/\/(dashboard)?$/,""),r=a.replace(/\//g,"_"),o={Name:r,DestinationType:"ImageUploader, FileUploader",RequestMethod:"POST",RequestURL:window.location.protocol+"//"+a+"/api/upload",Headers:t,Body:"MultipartFromData",FileFormName:"files[]",URL:"$json:files[0].url$",ThumbnailURL:"$json:files[0].url$"};page.token&&(o.DeletionURL="$json:files[0].deleteUrl$");var n=JSON.stringify(o,null,2),i=new Blob([n],{type:"application/octet-binary"});e.setAttribute("href",URL.createObjectURL(i)),e.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?"-":"",r=t?1e3:1024;if(a&&(e=-e),e]/.exec(a);if(!r)return a;var o="",n=0,i=0;for(n=r.index;n]/.exec(a);if(!r)return a;var o="",n=0,i=0;for(n=r.index;n {\n const sharexElement = document.querySelector('#ShareX')\n if (!sharexElement) return\n\n const headers = {}\n\n if (page.token) {\n headers.token = page.token || ''\n headers.albumid = page.album || ''\n }\n\n headers.filelength = page.fileLength || ''\n headers.age = page.uploadAge || ''\n headers.striptags = page.stripTags || ''\n\n const origin = (window.location.hostname + window.location.pathname).replace(/\\/(dashboard)?$/, '')\n const originClean = origin.replace(/\\//g, '_')\n\n const sharexConfObj = {\n Name: originClean,\n DestinationType: 'ImageUploader, FileUploader',\n RequestMethod: 'POST',\n RequestURL: `${window.location.protocol}//${origin}/api/upload`,\n Headers: headers,\n Body: 'MultipartFromData',\n FileFormName: 'files[]',\n URL: '$json:files[0].url$',\n ThumbnailURL: '$json:files[0].url$'\n }\n\n if (page.token)\n sharexConfObj.DeletionURL = '$json:files[0].deleteUrl$'\n\n const sharexConfStr = JSON.stringify(sharexConfObj, null, 2)\n const sharexBlob = new Blob([sharexConfStr], { 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.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\npage.escape = string => {\n // MIT License\n // Copyright(c) 2012-2013 TJ Holowaychuk\n // Copyright(c) 2015 Andreas Lubbe\n // Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n\n if (!string)\n return string\n\n const str = String(string)\n const match = /[\"'&<>]/.exec(str)\n\n if (!match)\n return str\n\n let escape\n let html = ''\n let index = 0\n let lastIndex = 0\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"'\n break\n case 38: // &\n escape = '&'\n break\n case 39: // '\n escape = '''\n break\n case 60: // <\n escape = '<'\n break\n case 62: // >\n escape = '>'\n break\n default:\n continue\n }\n\n if (lastIndex !== index)\n html += str.substring(lastIndex, index)\n\n lastIndex = index + 1\n html += escape\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html\n}\n"]} \ No newline at end of file +{"version":3,"sources":["utils.js"],"names":["lsKeys","siBytes","page","prepareShareX","const","sharexElement","document","querySelector","headers","token","albumid","album","filelength","fileLength","age","uploadAge","striptags","stripTags","origin","window","location","hostname","pathname","replace","originClean","sharexConfObj","Name","DestinationType","RequestMethod","RequestURL","Headers","Body","FileFormName","URL","ThumbnailURL","sharexConfStr","JSON","stringify","sharexBlob","Blob","type","setAttribute","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","escape","string","str","String","match","exec","let","html","index","lastIndex","length","charCodeAt","substring"],"mappings":"AAGAA,OAAOC,QAAU,UAEjBC,KAAKC,cAAa,WAChBC,IAAMC,EAAgBC,SAASC,cAAc,WAC7C,GAAKF,EAAL,CAEAD,IAAMI,EAAU,GAEZN,KAAKO,QACPD,EAAQC,MAAQP,KAAKO,OAAS,GAC9BD,EAAQE,QAAUR,KAAKS,OAAS,IAGlCH,EAAQI,WAAaV,KAAKW,YAAc,GACxCL,EAAQM,IAAMZ,KAAKa,WAAa,GAChCP,EAAQQ,UAAYd,KAAKe,WAAa,GAEtCb,IAAMc,GAAUC,OAAOC,SAASC,SAAWF,OAAOC,SAASE,UAAUC,QAAQ,kBAAmB,IAC1FC,EAAcN,EAAOK,QAAQ,MAAO,KAEpCE,EAAgB,CACpBC,KAAMF,EACNG,gBAAiB,8BACjBC,cAAe,OACfC,WAAeV,OAAOC,SAAS,SAAQ,KAAKF,EAAM,cAClDY,QAAStB,EACTuB,KAAM,oBACNC,aAAc,UACdC,IAAK,sBACLC,aAAc,uBAQVC,EAAgBC,KAAKC,UAAUZ,EAAe,KAAM,GACpDa,EAAa,IAAIC,KAAK,CAACJ,GAAgB,CAAEK,KAAM,6BAErDnC,EAAcoC,aAAa,OAAQR,IAAIS,gBAAgBJ,IACvDjC,EAAcoC,aAAa,WAAejB,EAAW,WAGvDtB,KAAKyC,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,cAGThD,KAAKiD,eAAc,SAAGC,GAGpB,GAAmB,iBAARA,IAAqBC,SAASD,GAAM,OAAOA,EAEtDhD,IAAMkD,EAAsC,MAAjCC,aAAavD,OAAOC,SACzBuD,EAAMJ,EAAM,EAAI,IAAM,GACtBK,EAAQH,EAAK,IAAO,KAE1B,GADIE,IAAKJ,GAAOA,GACZA,EAAMK,EAAO,MAAO,GAAGD,EAAMJ,EAAG,KAEpChD,IAAMsD,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,KAG/BpD,KAAKkE,OAAM,SAAGC,GAMZ,IAAKA,EACH,OAAOA,EAETjE,IAMIgE,EANEE,EAAMC,OAAOF,GACbG,EAAQ,UAAUC,KAAKH,GAE7B,IAAKE,EACH,OAAOF,EAGTI,IAAIC,EAAO,GACPC,EAAQ,EACRC,EAAY,EAEhB,IAAKD,EAAQJ,EAAMI,MAAOA,EAAQN,EAAIQ,OAAQF,IAAS,CACrD,OAAQN,EAAIS,WAAWH,IACrB,KAAK,GACHR,EAAS,SACT,MACF,KAAK,GACHA,EAAS,QACT,MACF,KAAK,GACHA,EAAS,QACT,MACF,KAAK,GACHA,EAAS,OACT,MACF,KAAK,GACHA,EAAS,OACT,MACF,QACE,SAGAS,IAAcD,IAChBD,GAAQL,EAAIU,UAAUH,EAAWD,IAEnCC,EAAYD,EAAQ,EACpBD,GAAQP,EAGV,OAAOS,IAAcD,EACjBD,EAAOL,EAAIU,UAAUH,EAAWD,GAChCD","file":"utils.js","sourcesContent":["/* global lsKeys, page */\n\n// keys for localStorage\nlsKeys.siBytes = 'siBytes'\n\npage.prepareShareX = () => {\n const sharexElement = document.querySelector('#ShareX')\n if (!sharexElement) return\n\n const headers = {}\n\n if (page.token) {\n headers.token = page.token || ''\n headers.albumid = page.album || ''\n }\n\n headers.filelength = page.fileLength || ''\n headers.age = page.uploadAge || ''\n headers.striptags = page.stripTags || ''\n\n const origin = (window.location.hostname + window.location.pathname).replace(/\\/(dashboard)?$/, '')\n const originClean = origin.replace(/\\//g, '_')\n\n const sharexConfObj = {\n Name: originClean,\n DestinationType: 'ImageUploader, FileUploader',\n RequestMethod: 'POST',\n RequestURL: `${window.location.protocol}//${origin}/api/upload`,\n Headers: headers,\n Body: 'MultipartFromData',\n FileFormName: 'files[]',\n URL: '$json:files[0].url$',\n ThumbnailURL: '$json:files[0].url$'\n }\n\n /*\n if (page.token)\n sharexConfObj.DeletionURL = '$json:files[0].deleteUrl$'\n */\n\n const sharexConfStr = JSON.stringify(sharexConfObj, null, 2)\n const sharexBlob = new Blob([sharexConfStr], { 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.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\npage.escape = string => {\n // MIT License\n // Copyright(c) 2012-2013 TJ Holowaychuk\n // Copyright(c) 2015 Andreas Lubbe\n // Copyright(c) 2015 Tiancheng \"Timothy\" Gu\n\n if (!string)\n return string\n\n const str = String(string)\n const match = /[\"'&<>]/.exec(str)\n\n if (!match)\n return str\n\n let escape\n let html = ''\n let index = 0\n let lastIndex = 0\n\n for (index = match.index; index < str.length; index++) {\n switch (str.charCodeAt(index)) {\n case 34: // \"\n escape = '"'\n break\n case 38: // &\n escape = '&'\n break\n case 39: // '\n escape = '''\n break\n case 60: // <\n escape = '<'\n break\n case 62: // >\n escape = '>'\n break\n default:\n continue\n }\n\n if (lastIndex !== index)\n html += str.substring(lastIndex, index)\n\n lastIndex = index + 1\n html += escape\n }\n\n return lastIndex !== index\n ? html + str.substring(lastIndex, index)\n : html\n}\n"]} \ No newline at end of file diff --git a/src/js/misc/utils.js b/src/js/misc/utils.js index 4a218ed..8e3a6ea 100644 --- a/src/js/misc/utils.js +++ b/src/js/misc/utils.js @@ -33,8 +33,10 @@ page.prepareShareX = () => { ThumbnailURL: '$json:files[0].url$' } + /* if (page.token) sharexConfObj.DeletionURL = '$json:files[0].deleteUrl$' + */ const sharexConfStr = JSON.stringify(sharexConfObj, null, 2) const sharexBlob = new Blob([sharexConfStr], { type: 'application/octet-binary' }) diff --git a/src/versions.json b/src/versions.json index 14fd32d..c0ed8d5 100644 --- a/src/versions.json +++ b/src/versions.json @@ -1,5 +1,5 @@ { - "1": "1592598701", + "1": "1592600474", "2": "1589010026", "3": "1581416390", "4": "1581416390",