Partial merge of develop to experimental
Does not include #2336 as the file has been moved out from underneath it: will do this separately
This commit is contained in:
parent
00405e7f22
commit
7d161de35b
77 changed files with 3526 additions and 598 deletions
|
@ -15,6 +15,8 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
import MatrixClientPeg from "./MatrixClientPeg";
|
||||
import isIp from "is-ip";
|
||||
import utils from 'matrix-js-sdk/lib/utils';
|
||||
|
||||
export const host = "matrix.to";
|
||||
export const baseUrl = `https://${host}`;
|
||||
|
@ -90,7 +92,9 @@ export function pickServerCandidates(roomId) {
|
|||
// Rationale for popular servers: It's hard to get rid of people when
|
||||
// they keep flocking in from a particular server. Sure, the server could
|
||||
// be ACL'd in the future or for some reason be evicted from the room
|
||||
// however an event like that is unlikely the larger the room gets.
|
||||
// however an event like that is unlikely the larger the room gets. If
|
||||
// the server is ACL'd at the time of generating the link however, we
|
||||
// shouldn't pick them. We also don't pick IP addresses.
|
||||
|
||||
// Note: we don't pick the server the room was created on because the
|
||||
// homeserver should already be using that server as a last ditch attempt
|
||||
|
@ -104,12 +108,29 @@ export function pickServerCandidates(roomId) {
|
|||
// The receiving user can then manually append the known-good server to
|
||||
// the list and magically have the link work.
|
||||
|
||||
const bannedHostsRegexps = [];
|
||||
let allowedHostsRegexps = [new RegExp(".*")]; // default allow everyone
|
||||
if (room.currentState) {
|
||||
const aclEvent = room.currentState.getStateEvents("m.room.server_acl", "");
|
||||
if (aclEvent && aclEvent.getContent()) {
|
||||
const getRegex = (hostname) => new RegExp("^" + utils.globToRegexp(hostname, false) + "$");
|
||||
|
||||
const denied = aclEvent.getContent().deny || [];
|
||||
denied.forEach(h => bannedHostsRegexps.push(getRegex(h)));
|
||||
|
||||
const allowed = aclEvent.getContent().allow || [];
|
||||
allowedHostsRegexps = []; // we don't want to use the default rule here
|
||||
allowed.forEach(h => allowedHostsRegexps.push(getRegex(h)));
|
||||
}
|
||||
}
|
||||
|
||||
const populationMap: {[server:string]:number} = {};
|
||||
const highestPlUser = {userId: null, powerLevel: 0, serverName: null};
|
||||
|
||||
for (const member of room.getJoinedMembers()) {
|
||||
const serverName = member.userId.split(":").splice(1).join(":");
|
||||
if (member.powerLevel > highestPlUser.powerLevel) {
|
||||
if (member.powerLevel > highestPlUser.powerLevel && !isHostnameIpAddress(serverName)
|
||||
&& !isHostInRegex(serverName, bannedHostsRegexps) && isHostInRegex(serverName, allowedHostsRegexps)) {
|
||||
highestPlUser.userId = member.userId;
|
||||
highestPlUser.powerLevel = member.powerLevel;
|
||||
highestPlUser.serverName = serverName;
|
||||
|
@ -125,8 +146,9 @@ export function pickServerCandidates(roomId) {
|
|||
const beforePopulation = candidates.length;
|
||||
const serversByPopulation = Object.keys(populationMap)
|
||||
.sort((a, b) => populationMap[b] - populationMap[a])
|
||||
.filter(a => !candidates.includes(a));
|
||||
for (let i = beforePopulation; i <= MAX_SERVER_CANDIDATES; i++) {
|
||||
.filter(a => !candidates.includes(a) && !isHostnameIpAddress(a)
|
||||
&& !isHostInRegex(a, bannedHostsRegexps) && isHostInRegex(a, allowedHostsRegexps));
|
||||
for (let i = beforePopulation; i < MAX_SERVER_CANDIDATES; i++) {
|
||||
const idx = i - beforePopulation;
|
||||
if (idx >= serversByPopulation.length) break;
|
||||
candidates.push(serversByPopulation[idx]);
|
||||
|
@ -134,3 +156,34 @@ export function pickServerCandidates(roomId) {
|
|||
|
||||
return candidates;
|
||||
}
|
||||
|
||||
function getHostnameFromMatrixDomain(domain) {
|
||||
if (!domain) return null;
|
||||
|
||||
// The hostname might have a port, so we convert it to a URL and
|
||||
// split out the real hostname.
|
||||
const parser = document.createElement('a');
|
||||
parser.href = "https://" + domain;
|
||||
return parser.hostname;
|
||||
}
|
||||
|
||||
function isHostInRegex(hostname, regexps) {
|
||||
hostname = getHostnameFromMatrixDomain(hostname);
|
||||
if (!hostname) return true; // assumed
|
||||
if (regexps.length > 0 && !regexps[0].test) throw new Error(regexps[0]);
|
||||
|
||||
return regexps.filter(h => h.test(hostname)).length > 0;
|
||||
}
|
||||
|
||||
function isHostnameIpAddress(hostname) {
|
||||
hostname = getHostnameFromMatrixDomain(hostname);
|
||||
if (!hostname) return false;
|
||||
|
||||
// is-ip doesn't want IPv6 addresses surrounded by brackets, so
|
||||
// take them off.
|
||||
if (hostname.startsWith("[") && hostname.endsWith("]")) {
|
||||
hostname = hostname.substring(1, hostname.length - 1);
|
||||
}
|
||||
|
||||
return isIp(hostname);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue