harbour-quill 0.2.12: note markdown con sync WebDAV
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
import QtQuick 2.2
|
||||
import "PropfindParser.js" as Prop
|
||||
|
||||
// Minimal WebDAV client over XMLHttpRequest. One request at a time
|
||||
// (busy flag); 30 s watchdog turns hangs into a failed() signal.
|
||||
Item {
|
||||
id: dav
|
||||
|
||||
property bool busy: false
|
||||
|
||||
signal listReady(var entries)
|
||||
signal fileReady(string content)
|
||||
signal writeDone()
|
||||
signal deleteDone()
|
||||
signal connOk()
|
||||
signal failed(string message)
|
||||
|
||||
property var currentXhr: null
|
||||
|
||||
Timer {
|
||||
id: watchdog
|
||||
interval: 30000
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
if (dav.currentXhr) {
|
||||
dav.currentXhr.abort()
|
||||
dav.currentXhr = null
|
||||
}
|
||||
dav.busy = false
|
||||
dav.failed(qsTr("Network timeout"))
|
||||
}
|
||||
}
|
||||
|
||||
function authHeader() {
|
||||
var user = appSettings.username
|
||||
if (!user) return ""
|
||||
return "Basic " + Qt.btoa(user + ":" + appSettings.password)
|
||||
}
|
||||
|
||||
function encodeRel(rel) {
|
||||
if (!rel) return rel
|
||||
var parts = rel.split("/")
|
||||
var out = []
|
||||
for (var i = 0; i < parts.length; i++) out.push(encodeURIComponent(parts[i]))
|
||||
return out.join("/")
|
||||
}
|
||||
|
||||
function fullUrl(rel) {
|
||||
var base = String(appSettings.serverUrl).replace(/\s+$/, "")
|
||||
if (!base) return ""
|
||||
if (rel && rel !== "") {
|
||||
if (base.charAt(base.length - 1) !== "/") base += "/"
|
||||
base += encodeRel(rel)
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
||||
function request(method, url, body, onDone) {
|
||||
if (busy) {
|
||||
failed(qsTr("Request already in progress"))
|
||||
return
|
||||
}
|
||||
busy = true
|
||||
var xhr = new XMLHttpRequest()
|
||||
currentXhr = xhr
|
||||
xhr.open(method, url, true)
|
||||
var auth = authHeader()
|
||||
if (auth) xhr.setRequestHeader("Authorization", auth)
|
||||
if (method === "PROPFIND") xhr.setRequestHeader("Depth", "1")
|
||||
if (method === "PUT") xhr.setRequestHeader("Content-Type", "text/markdown; charset=utf-8")
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState !== 4) return
|
||||
watchdog.stop()
|
||||
if (currentXhr === xhr) {
|
||||
currentXhr = null
|
||||
busy = false
|
||||
onDone(xhr)
|
||||
}
|
||||
// else: aborted by the watchdog — already signalled
|
||||
}
|
||||
xhr.send(body || "")
|
||||
watchdog.restart()
|
||||
}
|
||||
|
||||
function listDir(relPath) {
|
||||
request("PROPFIND", fullUrl(relPath || ""), "", function (xhr) {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
var entries = Prop.parse(xhr.responseText, appSettings.serverUrl)
|
||||
listReady(entries)
|
||||
} else {
|
||||
failed(statusMessage(xhr.status))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function readFile(relPath) {
|
||||
request("GET", fullUrl(relPath), "", function (xhr) {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
fileReady(xhr.responseText)
|
||||
} else {
|
||||
failed(statusMessage(xhr.status))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function writeFile(relPath, content) {
|
||||
request("PUT", fullUrl(relPath), content, function (xhr) {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
writeDone()
|
||||
} else {
|
||||
failed(statusMessage(xhr.status))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function deleteFile(relPath) {
|
||||
request("DELETE", fullUrl(relPath), "", function (xhr) {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
deleteDone()
|
||||
} else {
|
||||
failed(statusMessage(xhr.status))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function testConnection() {
|
||||
request("PROPFIND", fullUrl(""), "", function (xhr) {
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
connOk()
|
||||
} else {
|
||||
failed(statusMessage(xhr.status))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function statusMessage(status) {
|
||||
if (status === 401) return qsTr("Invalid credentials (401)")
|
||||
if (status === 403) return qsTr("Access denied (403)")
|
||||
if (status === 404) return qsTr("Folder not found (404) — check the URL")
|
||||
if (status === 405) return qsTr("WebDAV not available (405) — the URL must point to a DAV folder")
|
||||
if (status === 0) return qsTr("Server unreachable")
|
||||
if (status >= 500) return qsTr("Server error (%1)").arg(status)
|
||||
return qsTr("HTTP error %1").arg(status)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user