Skip to content

Commit

Permalink
Merge pull request #2222 from gmt2001/patch-70
Browse files Browse the repository at this point in the history
Patch 70
  • Loading branch information
BrandenB committed Apr 24, 2020
2 parents 992c875 + 2ee61e7 commit 20a15c3
Show file tree
Hide file tree
Showing 12 changed files with 292 additions and 22 deletions.
46 changes: 34 additions & 12 deletions javascript-source/commands/customCommands.js
Expand Up @@ -771,20 +771,42 @@
* @param {sub} subcommand
* @returns 0 = good, 1 = command perm bad, 2 = subcommand perm bad
*/
function permCom(username, command, subcommand) {
function permCom(username, command, subcommand, tags) {
var commandGroup, allowed;
if (subcommand === '') {
if ($.getCommandGroup(command) >= $.getUserGroupId(username)) {
return 0;
} else {
return 1;
}
commandGroup = $.getCommandGroup(command);
} else {
if ($.getSubcommandGroup(command, subcommand) >= $.getUserGroupId(username)) {
return 0;
} else {
return 2;
}
}
commandGroup = $.getSubcommandGroup(command, subcommand);
}

switch(commandGroup) {
case 0:
allowed = $.isCaster(username);
break;
case 1:
allowed = $.isAdmin(username);
break;
case 2:
allowed = $.isModv3(username, tags);
break;
case 3:
allowed = $.isSubv3(username, tags) || $.isModv3(username, tags);
break;
case 4:
allowed = $.isDonator(username) || $.isModv3(username, tags);
break;
case 5:
allowed = $.isVIP(username, tags) || $.isModv3(username, tags);
break;
case 6:
allowed = $.isReg(username) || $.isModv3(username, tags);
break;
default:
allowed = true;
break;
}

return allowed ? 0 : (subcommand === '' ? 1 : 2);
}

/*
Expand Down
4 changes: 2 additions & 2 deletions javascript-source/core/commandRegister.js
Expand Up @@ -228,7 +228,7 @@
} else if (commands[command].groupId == 4) {
group = 'Donator';
} else if (commands[command].groupId == 5) {
group = 'Hoster';
group = 'VIP';
} else if (commands[command].groupId == 6) {
group = 'Regular';
} else if (commands[command].groupId == 7) {
Expand Down Expand Up @@ -278,7 +278,7 @@
} else if (commands[command].subcommands[subcommand].groupId == 4) {
group = 'Donator';
} else if (commands[command].subcommands[subcommand].groupId == 5) {
group = 'Hoster';
group = 'VIP';
} else if (commands[command].subcommands[subcommand].groupId == 6) {
group = 'Regular';
} else if (commands[command].subcommands[subcommand].groupId == 7) {
Expand Down
15 changes: 15 additions & 0 deletions javascript-source/core/misc.js
Expand Up @@ -142,6 +142,20 @@
}
}

function equalsIgnoreCase(str1, str2) {
try {
return str1.equalsIgnoreCase(str2);
} catch (e) {
try {
return str1.toLowerCase() == str2.toLowerCase();
} catch (e) {
return false;
}
}

return false;
}

/**
* @function say
* @export $
Expand Down Expand Up @@ -748,4 +762,5 @@
$.getMessageWrites = getMessageWrites;
$.sayWithTimeout = sayWithTimeout;
$.paginateArrayDiscord = paginateArrayDiscord;
$.equalsIgnoreCase = equalsIgnoreCase;
})();
6 changes: 3 additions & 3 deletions javascript-source/core/permissions.js
Expand Up @@ -151,7 +151,7 @@
var idx = -1;

for (var i = 0; i < list.length; i++) {
if (list[i] !== undefined && list[i].equalsIgnoreCase(value)) {
if (list[i] !== undefined && $.equalsIgnoreCase(list[i], value)) {
idx = i;
break;
}
Expand Down Expand Up @@ -228,7 +228,7 @@
* @returns {boolean}
*/
function isModv3(username, tags) {
return (tags != null && tags != '{}' && tags.get('user-type').length() > 0) || isModeratorCache(username.toLowerCase());
return (tags != null && tags != '{}' && tags.get('user-type').length() > 0) || isModeratorCache(username.toLowerCase()) || isOwner(username);
}

/**
Expand All @@ -249,7 +249,7 @@
* @returns {boolean}
*/
function isSubv3(username, tags) {
return (tags != null && tags != '{}' && tags.get('subscriber').equals('1'));
return (tags != null && tags != '{}' && tags.get('subscriber').equals('1')) || isSub(username);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion javascript-source/init.js
Expand Up @@ -499,7 +499,7 @@
} else

// Check the command permission.
if ($.permCom(sender, command, subCommand) !== 0) {
if ($.permCom(sender, command, subCommand, event.getTags()) !== 0) {
$.sayWithTimeout($.whisperPrefix(sender) + $.lang.get('cmd.perm.404', (!$.subCommandExists(command, subCommand) ? $.getCommandGroupName(command) : $.getSubCommandGroupName(command, subCommand))), $.getIniDbBoolean('settings', 'permComMsgEnabled', false));
consoleDebug('Command !' + command + ' was not sent due to the user not having permission for it.');
return;
Expand Down
3 changes: 3 additions & 0 deletions source/com/gmt2001/httpwsserver/HTTPWSServer.java
Expand Up @@ -56,6 +56,8 @@ public final class HTTPWSServer {
*/
private Channel ch;

public boolean sslEnabled = false;

/**
* Gets the server instance.
*
Expand Down Expand Up @@ -112,6 +114,7 @@ private HTTPWSServer(String ipOrHostname, int port, boolean useHttps, String ssl
tmf.init(ks);

sslCtx = SslContextBuilder.forServer(kmf).trustManager(tmf).build();
sslEnabled = true;
}
} else {
sslCtx = null;
Expand Down
7 changes: 4 additions & 3 deletions source/com/gmt2001/httpwsserver/HTTPWSServerInitializer.java
Expand Up @@ -23,6 +23,7 @@
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
import io.netty.handler.ssl.OptionalSslHandler;
import io.netty.handler.ssl.SslContext;

/**
Expand Down Expand Up @@ -58,14 +59,14 @@ protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();

if (sslCtx != null) {
pipeline.addLast(sslCtx.newHandler(ch.alloc()));
pipeline.addLast(new HttpOptionalSslHandler(sslCtx));
}

pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(65536));
pipeline.addLast(new WebSocketServerCompressionHandler());
pipeline.addLast(new WebSocketServerProtocolHandler("/ws", null, true, 65536, false, true));
pipeline.addLast(new HttpServerPageHandler());
pipeline.addLast(new WebSocketFrameHandler());
pipeline.addLast("pagehandler", new HttpServerPageHandler());
pipeline.addLast("wshandler", new WebSocketFrameHandler());
}
}
44 changes: 44 additions & 0 deletions source/com/gmt2001/httpwsserver/HttpOptionalSslHandler.java
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2016-2019 phantombot.tv
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.gmt2001.httpwsserver;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.ssl.OptionalSslHandler;
import io.netty.handler.ssl.SslContext;

/**
* Detects Non-SSL HTTP connections and activates the SSL Redirect handler, when SSL is enabled
*
* @author gmt2001
*/
public class HttpOptionalSslHandler extends OptionalSslHandler {

/**
* Default Constructor
*/
HttpOptionalSslHandler(SslContext sslContext) {
super(sslContext);
}

@Override
protected ChannelHandler newNonSslHandler(ChannelHandlerContext context) {
context.pipeline().replace("pagehandler", "httpsslredirect", new HttpSslRedirectHandler());
context.pipeline().replace("wshandler", "wssslerror", new WsSslErrorHandler());
return null;
}
}
83 changes: 83 additions & 0 deletions source/com/gmt2001/httpwsserver/HttpSslRedirectHandler.java
@@ -0,0 +1,83 @@
/*
* Copyright (C) 2016-2019 phantombot.tv
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.gmt2001.httpwsserver;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.sqlite.SQLiteConfig;

/**
* Redirects HTTP requests to HTTPS, when SSL is enabled
*
* @author gmt2001
*/
public class HttpSslRedirectHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

/**
* Default Constructor
*/
HttpSslRedirectHandler() {
super();
}

/**
* Redirects non-SSL requests to SSL
*
* @param ctx The {@link ChannelHandlerContext} of the session
* @param req The {@link FullHttpRequest} containing the request
* @throws Exception Passes any thrown exceptions up the stack
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
if (!req.decoderResult().isSuccess()) {
HttpServerPageHandler.sendHttpResponse(ctx, req, HttpServerPageHandler.prepareHttpResponse(HttpResponseStatus.BAD_REQUEST, null, null));
return;
}

String host = req.headers().get(HttpHeaderNames.HOST);

if (host != null && !host.isBlank()) {
String uri = "https://" + host + req.uri();

com.gmt2001.Console.debug.println("301: " + uri);

FullHttpResponse res = HttpServerPageHandler.prepareHttpResponse(HttpResponseStatus.MOVED_PERMANENTLY, null, null);

res.headers().set(HttpHeaderNames.LOCATION, uri);

HttpServerPageHandler.sendHttpResponse(ctx, req, res);
} else {
HttpServerPageHandler.sendHttpResponse(ctx, req, HttpServerPageHandler.prepareHttpResponse(HttpResponseStatus.FORBIDDEN, "HTTPS Required".getBytes(), null));
}
}

/**
* Handles exceptions that are thrown up the stack
*
* @param ctx The {@link ChannelHandlerContext} of the session
* @param cause The exception
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
com.gmt2001.Console.debug.printOrLogStackTrace(cause);
ctx.close();
}
}
84 changes: 84 additions & 0 deletions source/com/gmt2001/httpwsserver/WsSslErrorHandler.java
@@ -0,0 +1,84 @@
/*
* Copyright (C) 2016-2019 phantombot.tv
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.gmt2001.httpwsserver;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler.HandshakeComplete;
import org.json.JSONStringer;

/**
* Processes WebSocket frames and passes successful ones to the appropriate registered final handler
*
* @author gmt2001
*/
public class WsSslErrorHandler extends SimpleChannelInboundHandler<WebSocketFrame> {

WsSslErrorHandler() {
super();
}

/**
* Handles incoming WebSocket frames and passes them to the appropriate {@link WsFrameHandler}
*
* @param ctx The {@link ChannelHandlerContext} of the session
* @param req The {@link WebSocketFrame} containing the request frame
* @throws Exception Passes any thrown exceptions up the stack
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {

}

/**
* Captures {@link HandshakeComplete} events and saves the {@link WsFrameHandler} URI to the session
*
* If a handler is not available for the requested path, then {@code 404 NOT FOUND} is sent back to the client using JSON:API format
*
* @param ctx The {@link ChannelHandlerContext} of the session
* @param evt The event object
* @throws Exception Passes any thrown exceptions up the stack
*/
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof HandshakeComplete) {
JSONStringer jsonObject = new JSONStringer();
jsonObject.object().key("errors").array().object()
.key("status").value("403")
.key("title").value("Forbidden")
.key("detail").value("WSS Required")
.endObject().endArray().endObject();

ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonObject.toString()));
ctx.close();
}
}

/**
* Handles exceptions that are thrown up the stack
*
* @param ctx The {@link ChannelHandlerContext} of the session
* @param cause The exception
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
com.gmt2001.Console.debug.printOrLogStackTrace(cause);
ctx.close();
}
}

0 comments on commit 20a15c3

Please sign in to comment.