2021-03-23 21:04:17 +01:00
|
|
|
|
2021-03-24 11:55:05 +01:00
|
|
|
const webmentionReceiver = require('./../webmention/receive')
|
2021-03-23 21:04:17 +01:00
|
|
|
const config = require('./../config')
|
|
|
|
const parser = require("fast-xml-parser")
|
2021-04-05 17:44:27 +02:00
|
|
|
const log = require('pino')()
|
2021-03-23 21:04:17 +01:00
|
|
|
|
|
|
|
/**
|
2021-03-24 11:55:05 +01:00
|
|
|
See https://www.hixie.ch/specs/pingback/pingback#refsXMLRPC
|
|
|
|
---
|
2021-03-23 21:04:17 +01:00
|
|
|
Sample XML:
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
<methodCall>
|
|
|
|
<methodName>pingback.ping</methodName>
|
|
|
|
<params>
|
|
|
|
<param>
|
|
|
|
<value><string>https://brainbaking.com/kristien.html</string></value>
|
|
|
|
</param>
|
|
|
|
<param>
|
|
|
|
<value><string>https://kristienthoelen.be/2021/03/22/de-stadia-van-een-burn-out-in-welk-stadium-zit-jij/</string></value>
|
|
|
|
</param>
|
|
|
|
</params>
|
|
|
|
</methodCall>
|
|
|
|
*/
|
|
|
|
const isValidDomain = (url) => {
|
|
|
|
return config.allowedWebmentionSources.some(domain => {
|
|
|
|
return url.indexOf(domain) !== -1
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-04-05 17:44:27 +02:00
|
|
|
function xmlparse(body) {
|
|
|
|
try {
|
|
|
|
return parser.parse(body)
|
|
|
|
} catch(e) {
|
|
|
|
log.error('%s %s', 'fast-xml-parser was unable to parse the following body:', body)
|
|
|
|
throw e
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-23 21:04:17 +01:00
|
|
|
function validate(body) {
|
2021-04-05 17:44:27 +02:00
|
|
|
const xml = xmlparse(body)
|
2021-03-23 21:04:17 +01:00
|
|
|
if(!xml) return false
|
|
|
|
if(!xml.methodCall || xml.methodCall.methodName !== "pingback.ping") return false
|
|
|
|
if(!xml.methodCall.params || !xml.methodCall.params.param || xml.methodCall.params.param.length !== 2) return false
|
|
|
|
if(!xml.methodCall.params.param.every(param => param?.value?.string?.startsWith('http'))) return false
|
|
|
|
if(!isValidDomain(xml.methodCall.params.param[1].value.string)) return false
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2021-03-24 11:55:05 +01:00
|
|
|
// we treat a pingback as a webmention.
|
|
|
|
// Wordpress pingback processing source: https://developer.wordpress.org/reference/classes/wp_xmlrpc_server/pingback_ping/
|
2021-03-23 21:04:17 +01:00
|
|
|
async function receive(body) {
|
2021-04-05 17:44:27 +02:00
|
|
|
const xml = xmlparse(body)
|
2021-03-24 14:03:54 +01:00
|
|
|
const webmentionBody = {
|
2021-03-24 11:55:05 +01:00
|
|
|
source: xml.methodCall.params.param[0].value.string,
|
|
|
|
target: xml.methodCall.params.param[1].value.string
|
2021-03-24 14:03:54 +01:00
|
|
|
}
|
|
|
|
|
2021-04-05 17:44:27 +02:00
|
|
|
log.info('%s %o', 'OK: looks like a valid pingback', webmentionBody)
|
2021-03-24 14:03:54 +01:00
|
|
|
await webmentionReceiver.receive(webmentionBody)
|
2021-03-23 21:04:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
receive,
|
|
|
|
validate
|
|
|
|
}
|