Add JSONP mode and captcha

JSONP mode is on by default. It will fetch main wiki pages in the
browser, without the server needing to make any requests. To turn it
off, add [feature_json] enabled = false to config.ini.

Captcha is off by default. It is a custom solution and is still
experimental at this stage. If you turn it on, please monitor the logs
to see how it goes! config.ini options are as follows:

[captcha]
enabled = true|false
log = true|false
ip_header = <header name set by your reverse proxy, like x-forwarded-for>
This commit is contained in:
Cadence Ember
2025-11-04 23:06:55 +13:00
parent 443f1eecbc
commit 23a201cc84
11 changed files with 431 additions and 47 deletions
+24
View File
@@ -0,0 +1,24 @@
const u = new URL(location)
const from = u.searchParams.get("from") || location.href
let answered = false
const area = document.getElementById("captcha-area")
const areaBox = area.getBoundingClientRect()
const width = Math.floor(areaBox.width)
const height = Math.floor(window.innerHeight - areaBox.bottom - areaBox.left)
const img = document.createElement("img")
img.src = `/captcha/img/${width}/${height}`
img.addEventListener("click", event => {
if (answered) return
answered = true
location = `/captcha/verify/${width}/${height}/${event.offsetX}/${event.offsetY}?` + new URLSearchParams({from})
})
area.appendChild(img)
document.addEventListener("keydown", event => {
if (event.repeat) {
if (answered) return
answered = true
location = `/captcha/verify/0/0/${event.key}/0?` + new URLSearchParams({from})
}
})
+57
View File
@@ -0,0 +1,57 @@
const loading = document.getElementById("loading")
loading.textContent = "Loading, please wait..."
const progress = document.getElementById("progress")
let wikiPage = null
function wikiPageCallback(data) {
wikiPage = data
cont()
}
let siteinfo = null
function siteinfoCallback(data) {
siteinfo = data
cont()
}
async function cont() {
if (!(wikiPage && siteinfo)) return
const xhr = new XMLHttpRequest();
const uploadFraction = 0.7
// Upload progress
xhr.upload.addEventListener("progress", event => {
if (event.lengthComputable) {
progress.value = (event.loaded / event.total) * uploadFraction
console.log(
`Uploaded ${((event.loaded / event.total) * 100).toFixed(2)}%`,
)
}
})
// Download progress
xhr.addEventListener("progress", event => {
if (event.lengthComputable) {
progress.value = (event.loaded / event.total) * (1 - uploadFraction) + uploadFraction
console.log(
`Downloaded ${((event.loaded / event.total) * 100).toFixed(2)}%`,
)
}
})
xhr.addEventListener("load", () => {
console.log(xhr)
document.body = xhr.responseXML.body
})
xhr.open("POST", "/api/render/wiki")
xhr.responseType = "document"
xhr.send(JSON.stringify({
data: wikiPage,
siteinfo,
wikiname,
path
}));
}
+1
View File
@@ -2,3 +2,4 @@ User-Agent: *
Disallow: /*/wiki/*
Disallow: /proxy
Disallow: /set-user-settings
Disallow: /captcha