This repository has no description
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 }