This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / configs / services / pad / upload-any-file.patch
8.9 kB 226 lines
1diff -r a/lib/config/default.js b/lib/config/default.js 2--- a/lib/config/default.js 2026-10-11 08:22:28.833011861 +0200 3+++ b/lib/config/default.js 2026-10-11 08:22:52.996391760 +0200 4@@ -71,11 +71,14 @@ 5 tooBusyLag: 70, 6 // document 7 documentMaxLength: 100000, 8- // image upload setting, available options are imgur/s3/filesystem/azure/lutim 9+ // image upload setting, available options are imgur/s3/filesystem/azure/lutim/krebspaste 10 imageUploadType: 'filesystem', 11 lutim: { 12 url: 'https://framapic.org/' 13 }, 14+ krebspaste: { 15+ url: 'https://p.krebsco.de' 16+ }, 17 imgur: { 18 clientID: undefined 19 }, 20diff -r a/lib/config/index.js b/lib/config/index.js 21--- a/lib/config/index.js 2026-10-11 08:22:28.832388404 +0200 22+++ b/lib/config/index.js 2026-10-11 08:22:52.994753055 +0200 23@@ -170,8 +170,8 @@ 24 } 25 26 // Validate upload upload providers 27-if (['filesystem', 's3', 'minio', 'imgur', 'azure', 'lutim'].indexOf(config.imageUploadType) === -1) { 28- logger.error('"imageuploadtype" is not correctly set. Please use "filesystem", "s3", "minio", "azure", "lutim" or "imgur". Defaulting to "filesystem"') 29+if (['filesystem', 's3', 'minio', 'imgur', 'azure', 'lutim', 'krebspaste'].indexOf(config.imageUploadType) === -1) { 30+ logger.error('"imageuploadtype" is not correctly set. Please use "filesystem", "s3", "minio", "azure", "lutim", "krebspaste" or "imgur". Defaulting to "filesystem"') 31 config.imageUploadType = 'filesystem' 32 } 33 34@@ -179,23 +179,26 @@ 35 logger.error('You can only deactivate one of "saml.wantAssertionsSigned" and "saml.wantAuthnResponseSigned"') 36 } 37 38-// figure out mime types for image uploads 39-switch (config.imageUploadType) { 40- case 'imgur': 41- config.allowedUploadMimeTypes = [ 42- 'image/jpeg', 43- 'image/png', 44- 'image/gif' 45- ] 46- break 47- default: 48- config.allowedUploadMimeTypes = [ 49- 'image/jpeg', 50- 'image/png', 51- 'image/gif', 52- 'image/svg+xml', 53- 'image/webp' 54- ] 55+// figure out mime types for image uploads, unless set explicitly. 56+// ['*'] allows any file type. 57+if (!Array.isArray(config.allowedUploadMimeTypes)) { 58+ switch (config.imageUploadType) { 59+ case 'imgur': 60+ config.allowedUploadMimeTypes = [ 61+ 'image/jpeg', 62+ 'image/png', 63+ 'image/gif' 64+ ] 65+ break 66+ default: 67+ config.allowedUploadMimeTypes = [ 68+ 'image/jpeg', 69+ 'image/png', 70+ 'image/gif', 71+ 'image/svg+xml', 72+ 'image/webp' 73+ ] 74+ } 75 } 76 77 // generate correct path 78diff -r a/lib/web/imageRouter/index.js b/lib/web/imageRouter/index.js 79--- a/lib/web/imageRouter/index.js 2026-10-11 08:22:28.837198185 +0200 80+++ b/lib/web/imageRouter/index.js 2026-10-11 08:22:29.024913829 +0200 81@@ -32,6 +32,9 @@ 82 export default imageRouter 83 84 async function checkUploadType (filePath) { 85+ if (config.allowedUploadMimeTypes.includes('*')) { 86+ return true 87+ } 88 const extension = path.extname(filePath).toLowerCase() 89 const FileType = await import('file-type') 90 let typeFromMagic = await FileType.fileTypeFromFile(filePath) 91diff -r a/lib/web/imageRouter/krebspaste.js b/lib/web/imageRouter/krebspaste.js 92--- a/lib/web/imageRouter/krebspaste.js 1970-01-01 01:00:00.000000000 +0100 93+++ b/lib/web/imageRouter/krebspaste.js 2026-10-11 08:22:41.108085483 +0200 94@@ -0,0 +1,62 @@ 95+'use strict' 96+// Uploads to a krebs paste service (https://p.krebsco.de): images to its 97+// imgur-compatible /image endpoint, everything else (and images /image 98+// rejects) as a plain paste to /. 99+const fs = require('fs') 100+ 101+const config = require('../../config') 102+const logger = require('../../logger') 103+ 104+async function post (url, body) { 105+ const res = await fetch(url, { method: 'POST', body }) 106+ const text = await res.text() 107+ return { status: res.status, ok: res.ok, text } 108+} 109+ 110+// The service reports links with the scheme/host it saw; keep only the path. 111+function rebase (link, base) { 112+ return new URL(new URL(link).pathname, base).href 113+} 114+ 115+async function upload (filePath) { 116+ const base = config.krebspaste.url 117+ const body = fs.readFileSync(filePath) 118+ const FileType = await import('file-type') 119+ const type = await FileType.fileTypeFromBuffer(body) 120+ 121+ if (type && type.mime.startsWith('image/')) { 122+ const res = await post(new URL('/image', base), body) 123+ if (res.ok) { 124+ return rebase(JSON.parse(res.text).data.link, base) 125+ } 126+ if (res.status !== 400) { 127+ throw new Error(`krebspaste /image: ${res.status} ${res.text}`) 128+ } 129+ logger.debug(`krebspaste: /image rejected ${type.mime}, pasting instead`) 130+ } 131+ 132+ const res = await post(new URL('/', base), body) 133+ if (!res.ok) { 134+ throw new Error(`krebspaste /: ${res.status} ${res.text}`) 135+ } 136+ // one link per line: full hash, then the short one if unambiguous 137+ const links = res.text.trim().split('\n') 138+ return rebase(links[links.length - 1], base) 139+} 140+ 141+exports.uploadImage = function (imagePath, callback) { 142+ if (!callback || typeof callback !== 'function') { 143+ logger.error('Callback has to be a function') 144+ return 145+ } 146+ 147+ if (!imagePath || typeof imagePath !== 'string') { 148+ callback(new Error('Image path is missing or wrong'), null) 149+ return 150+ } 151+ 152+ upload(imagePath).then( 153+ (url) => callback(null, url), 154+ (err) => callback(err, null) 155+ ) 156+} 157diff -r a/public/js/lib/editor/toolbar.html b/public/js/lib/editor/toolbar.html 158--- a/public/js/lib/editor/toolbar.html 2026-10-11 08:22:28.849861030 +0200 159+++ b/public/js/lib/editor/toolbar.html 2026-10-11 08:22:29.025254870 +0200 160@@ -34,8 +34,8 @@ 161 <a id="makeImage" class="btn btn-sm text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Image"> 162 <i class="fa fa-image fa-fw"></i> 163 </a> 164- <a id="uploadImage" class="btn btn-sm btn-file ui-upload-image" title="Upload Image"> 165- <i class="fa fa-upload fa-fw"></i><input type="file" accept="image/*" name="upload" multiple title="Upload Image"> 166+ <a id="uploadImage" class="btn btn-sm btn-file ui-upload-image" title="Upload File"> 167+ <i class="fa fa-upload fa-fw"></i><input type="file" name="upload" multiple title="Upload File"> 168 </a> 169 <a id="makeTable" class="btn btn-sm text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Table"> 170 <i class="fa fa-table fa-fw"></i> 171diff -r a/public/vendor/inlineAttachment/inline-attachment.js b/public/vendor/inlineAttachment/inline-attachment.js 172--- a/public/vendor/inlineAttachment/inline-attachment.js 2026-10-11 08:22:28.904847610 +0200 173+++ b/public/vendor/inlineAttachment/inline-attachment.js 2026-10-11 08:22:29.025553536 +0200 174@@ -232,6 +232,8 @@ 175 var fileNameMatches = file.name.match(/\.(.+)$/); 176 if (fileNameMatches) { 177 extension = fileNameMatches[1]; 178+ } else if (file.type.indexOf('image/') !== 0) { 179+ extension = 'bin'; 180 } 181 } 182 183@@ -265,7 +267,7 @@ 184 xhr.onload = function() { 185 // If HTTP status is OK or Created 186 if (xhr.status === 200 || xhr.status === 201) { 187- me.onFileUploadResponse(xhr, id); 188+ me.onFileUploadResponse(xhr, id, file); 189 } else { 190 me.onFileUploadError(xhr, id); 191 } 192@@ -295,7 +297,7 @@ 193 * @param {XMLHttpRequest} xhr 194 * @return {Void} 195 */ 196- inlineAttachment.prototype.onFileUploadResponse = function(xhr, id) { 197+ inlineAttachment.prototype.onFileUploadResponse = function(xhr, id, file) { 198 if (this.settings.onFileUploadResponse.call(this, xhr) !== false) { 199 var result = JSON.parse(xhr.responseText), 200 filename = result[this.settings.jsonFieldName]; 201@@ -305,6 +307,11 @@ 202 var string = this.settings.progressText.replace(this.filenameTag, id); 203 var lines = this.editor.getValue().split('\n'); 204 var newValue = this.settings.urlText.replace(this.filenameTag, filename); 205+ // Non-image files become a plain link named after the file. 206+ if (file && file.type.indexOf('image/') !== 0) { 207+ var name = (file.name || 'file').replace(/([\\\[\]])/g, '\\$1'); 208+ newValue = '[' + name + '](' + filename + ')'; 209+ } 210 for(var i = 0; i < lines.length; i++) { 211 var ch = lines[i].indexOf(string); 212 if(ch != -1) 213@@ -368,10 +375,12 @@ 214 for (var i = 0; i < items.length; i++) { 215 var item = items[i]; 216 if (this.isFileAllowed(item)) { 217- result = true; 218 var id = ID(); 219 var file = item.getAsFile(); 220+ // Only file items count; with allowedTypes '*' string items 221+ // (plain text, html) also pass isFileAllowed. 222 if (file !== null) { 223+ result = true; 224 this.onFileInserted(file, id); 225 this.uploadFile(file, id); 226 }