9a2da60b7d
Note: websocket s2s is not working yet, still WIP. New Features * Chat Federation: * You can now connect to a remote chat with your local account. * This remote connection is done using a custom implementation of [XEP-0468: WebSocket S2S](https://xmpp.org/extensions/xep-0468.html), using some specific discovering method (so that it will work without any DNS configuration). Minor changes and fixes * Possibility to debug Prosody in development environments. * Using process.spawn instead of process.exec to launch Prosody (safer, and more optimal). * Prosody AppImage: fix path mapping: we only map necessary /etc/ subdir, so that the AppImage can access to /etc/resolv.conf, /etc/hosts, ... * Prosody AppImage: hidden debug mode to disable lua-unbound, that seems broken in some docker dev environments.
123 lines
2.7 KiB
TypeScript
123 lines
2.7 KiB
TypeScript
import type { LiveChatJSONLDInfos, LiveChatJSONLDAttribute } from './types'
|
|
import { URL } from 'url'
|
|
|
|
function sanitizePeertubeLiveChatInfos (chatInfos: any): LiveChatJSONLDAttribute {
|
|
if (chatInfos === false) { return false }
|
|
if (typeof chatInfos !== 'object') { return false }
|
|
|
|
if (chatInfos.type !== 'xmpp') { return false }
|
|
if ((typeof chatInfos.jid) !== 'string') { return false }
|
|
if (!Array.isArray(chatInfos.links)) { return false }
|
|
|
|
const r: LiveChatJSONLDInfos = {
|
|
type: chatInfos.type,
|
|
jid: chatInfos.jid,
|
|
links: []
|
|
}
|
|
|
|
for (const link of chatInfos.links) {
|
|
if ((typeof link) !== 'object') { continue }
|
|
if (['xmpp-bosh-anonymous', 'xmpp-websocket-anonymous'].includes(link.type)) {
|
|
if ((typeof link.jid) !== 'string') { continue }
|
|
if ((typeof link.url) !== 'string') { continue }
|
|
|
|
if (
|
|
!_validUrl(link.url, {
|
|
noSearchParams: true,
|
|
protocol: link.type === 'xmpp-websocket-anonymous' ? 'ws.' : 'http.'
|
|
})
|
|
) {
|
|
continue
|
|
}
|
|
|
|
r.links.push({
|
|
type: link.type,
|
|
jid: link.jid,
|
|
url: link.url
|
|
})
|
|
}
|
|
if (link.type === 'xmpp-s2s') {
|
|
if (!/^\d+$/.test(link.port)) {
|
|
continue
|
|
}
|
|
const host = _validateHost(link.host)
|
|
if (!host) {
|
|
continue
|
|
}
|
|
r.links.push({
|
|
type: link.type,
|
|
host,
|
|
port: link.port
|
|
})
|
|
}
|
|
if (link.type === 'xmpp-peertube-livechat-ws-s2s') {
|
|
if ((typeof link.url) !== 'string') { continue }
|
|
|
|
if (
|
|
!_validUrl(link.url, {
|
|
noSearchParams: true,
|
|
protocol: 'ws.'
|
|
})
|
|
) {
|
|
continue
|
|
}
|
|
|
|
r.links.push({
|
|
type: link.type,
|
|
url: link.url
|
|
})
|
|
}
|
|
}
|
|
return r
|
|
}
|
|
|
|
interface URLConstraints {
|
|
protocol: 'http.' | 'ws.'
|
|
noSearchParams: boolean
|
|
}
|
|
|
|
function _validUrl (s: string, constraints: URLConstraints): boolean {
|
|
if ((typeof s) !== 'string') { return false }
|
|
if (s === '') { return false }
|
|
let url: URL
|
|
try {
|
|
url = new URL(s)
|
|
} catch (_err) {
|
|
return false
|
|
}
|
|
|
|
if (constraints.protocol) {
|
|
if (constraints.protocol === 'http.') {
|
|
if (url.protocol !== 'https:' && url.protocol !== 'http:') {
|
|
return false
|
|
}
|
|
} else if (constraints.protocol === 'ws.') {
|
|
if (url.protocol !== 'wss:' && url.protocol !== 'ws:') {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
if (constraints.noSearchParams) {
|
|
if (url.search !== '') {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
function _validateHost (s: string): false | string {
|
|
try {
|
|
if (s.includes('/')) { return false }
|
|
const url = new URL('http://' + s)
|
|
return url.hostname
|
|
} catch (_err) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
export {
|
|
sanitizePeertubeLiveChatInfos
|
|
}
|