aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--build/server.js43
-rw-r--r--src/server/HttpServer.hx14
-rw-r--r--src/server/Main.hx4
-rw-r--r--test/tests/TestServer.hx46
-rw-r--r--tests.hxml17
6 files changed, 104 insertions, 27 deletions
diff --git a/.gitignore b/.gitignore
index 40a4754..fe79413 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,8 +1,9 @@
/node_modules
+/build/tests.js
/res/temp
-/user/config.json
+/user/crashes/
+/user/logs/
/user/state.json
+/user/config.json
/user/users.json
/user/res/
-/user/logs/
-/user/crashes/
diff --git a/build/server.js b/build/server.js
index 773c774..e2ada6a 100644
--- a/build/server.js
+++ b/build/server.js
@@ -3613,7 +3613,7 @@ server_HttpServer.init = function(dir,customDir,allowLocalRequests) {
server_HttpServer.allowLocalRequests = allowLocalRequests;
};
server_HttpServer.serveFiles = function(req,res) {
- var url = decodeURI(req.url);
+ var url = server_HttpServer.safeDecodeURI(req.url);
if(url == "/") {
url = "/index.html";
}
@@ -3747,7 +3747,7 @@ server_HttpServer.proxyUrl = function(req,res) {
server_HttpServer.proxyRequest = function(url,req,res,fn) {
var url1;
try {
- url1 = new js_node_url_URL(decodeURI(url));
+ url1 = new js_node_url_URL(server_HttpServer.safeDecodeURI(url));
} catch( _g ) {
return null;
}
@@ -3782,6 +3782,14 @@ server_HttpServer.getMimeType = function(ext) {
}
return contentType;
};
+server_HttpServer.safeDecodeURI = function(data) {
+ try {
+ data = decodeURI(data);
+ } catch( _g ) {
+ }
+ data = data.replace(server_HttpServer.ctrlCharacters.r,"");
+ return data;
+};
var server_Logger = function(folder,maxCount,verbose) {
this.matchFileFormat = new EReg("[0-9_-]+\\.json$","");
this.logs = [];
@@ -3931,7 +3939,7 @@ server_Main.prototype = {
});
this.wss = new js_npm_ws_Server({ server : server});
this.wss.on("connection",$bind(this,this.onConnect));
- server.listen(this.port);
+ server.listen(this.port,$bind(this,this.onServerInited));
new haxe_Timer(25000).run = function() {
var _g = 0;
var _g1 = _gthis.clients;
@@ -3947,6 +3955,8 @@ server_Main.prototype = {
}
};
}
+ ,onServerInited: function() {
+ }
,exit: function() {
this.saveState();
this.logger.saveLog();
@@ -3998,7 +4008,7 @@ server_Main.prototype = {
var field = _g1[_g];
++_g;
if(Reflect.field(config,field) == null) {
- haxe_Log.trace("Warning: config field \"" + field + "\" is unknown",{ fileName : "src/server/Main.hx", lineNumber : 180, className : "server.Main", methodName : "getUserConfig"});
+ haxe_Log.trace("Warning: config field \"" + field + "\" is unknown",{ fileName : "src/server/Main.hx", lineNumber : 182, className : "server.Main", methodName : "getUserConfig"});
}
config[field] = Reflect.field(customConfig,field);
}
@@ -4009,14 +4019,14 @@ server_Main.prototype = {
var emote = _g1[_g];
++_g;
if(emoteCopies_h[emote.name]) {
- haxe_Log.trace("Warning: emote name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 186, className : "server.Main", methodName : "getUserConfig"});
+ haxe_Log.trace("Warning: emote name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 188, className : "server.Main", methodName : "getUserConfig"});
}
emoteCopies_h[emote.name] = true;
if(!this.verbose) {
continue;
}
if(emoteCopies_h[emote.image]) {
- haxe_Log.trace("Warning: emote url of name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 190, className : "server.Main", methodName : "getUserConfig"});
+ haxe_Log.trace("Warning: emote url of name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 192, className : "server.Main", methodName : "getUserConfig"});
}
emoteCopies_h[emote.image] = true;
}
@@ -4058,7 +4068,7 @@ server_Main.prototype = {
js_node_Fs.writeFileSync("" + folder + "/users.json",JSON.stringify({ admins : users1, bans : _g, salt : users.salt},null,"\t"));
}
,saveState: function() {
- haxe_Log.trace("Saving state...",{ fileName : "src/server/Main.hx", lineNumber : 229, className : "server.Main", methodName : "saveState"});
+ haxe_Log.trace("Saving state...",{ fileName : "src/server/Main.hx", lineNumber : 231, className : "server.Main", methodName : "saveState"});
var json = JSON.stringify({ videoList : this.videoList, isPlaylistOpen : this.isPlaylistOpen, itemPos : this.itemPos, messages : this.messages, timer : { time : this.videoTimer.getTime(), paused : this.videoTimer.isPaused()}},null,"\t");
js_node_Fs.writeFileSync(this.statePath,json);
this.writeUsers(this.userList);
@@ -4067,7 +4077,7 @@ server_Main.prototype = {
if(!sys_FileSystem.exists(this.statePath)) {
return;
}
- haxe_Log.trace("Loading state...",{ fileName : "src/server/Main.hx", lineNumber : 247, className : "server.Main", methodName : "loadState"});
+ haxe_Log.trace("Loading state...",{ fileName : "src/server/Main.hx", lineNumber : 249, className : "server.Main", methodName : "loadState"});
var data = JSON.parse(js_node_Fs.readFileSync(this.statePath,{ encoding : "utf8"}));
this.videoList.length = 0;
this.messages.length = 0;
@@ -4084,7 +4094,7 @@ server_Main.prototype = {
this.videoTimer.pause();
}
,logError: function(type,data) {
- haxe_Log.trace(type,{ fileName : "src/server/Main.hx", lineNumber : 265, className : "server.Main", methodName : "logError", customParams : [data]});
+ haxe_Log.trace(type,{ fileName : "src/server/Main.hx", lineNumber : 267, className : "server.Main", methodName : "logError", customParams : [data]});
var crashesFolder = "" + this.rootDir + "/user/crashes";
server_Utils.ensureDir(crashesFolder);
js_node_Fs.writeFileSync("" + crashesFolder + "/" + (DateTools.format(new Date(),"%Y-%m-%d_%H_%M_%S") + "-" + type) + ".json",JSON.stringify(data,null,"\t"));
@@ -4101,7 +4111,7 @@ server_Main.prototype = {
if(_gthis.clients.length == 0) {
return;
}
- haxe_Log.trace("Ping " + url,{ fileName : "src/server/Main.hx", lineNumber : 282, className : "server.Main", methodName : "initIntergationHandlers"});
+ haxe_Log.trace("Ping " + url,{ fileName : "src/server/Main.hx", lineNumber : 284, className : "server.Main", methodName : "initIntergationHandlers"});
js_node_Http.get(url,null,function(r) {
});
};
@@ -4122,13 +4132,13 @@ server_Main.prototype = {
password += this.config.salt;
var hash = haxe_crypto_Sha256.encode(password);
this.userList.admins.push({ name : name, hash : hash});
- haxe_Log.trace("Admin " + name + " added.",{ fileName : "src/server/Main.hx", lineNumber : 306, className : "server.Main", methodName : "addAdmin"});
+ haxe_Log.trace("Admin " + name + " added.",{ fileName : "src/server/Main.hx", lineNumber : 308, className : "server.Main", methodName : "addAdmin"});
}
,removeAdmin: function(name) {
HxOverrides.remove(this.userList.admins,Lambda.find(this.userList.admins,function(item) {
return item.name == name;
}));
- haxe_Log.trace("Admin " + name + " removed.",{ fileName : "src/server/Main.hx", lineNumber : 313, className : "server.Main", methodName : "removeAdmin"});
+ haxe_Log.trace("Admin " + name + " removed.",{ fileName : "src/server/Main.hx", lineNumber : 315, className : "server.Main", methodName : "removeAdmin"});
}
,replayLog: function(events) {
var _gthis = this;
@@ -4172,7 +4182,7 @@ server_Main.prototype = {
var ip = this.clientIp(req);
var id = this.freeIds.length > 0 ? this.freeIds.shift() : this.clients.length;
var name = "Guest " + (id + 1);
- haxe_Log.trace("" + name + " connected (" + ip + ")",{ fileName : "src/server/Main.hx", lineNumber : 351, className : "server.Main", methodName : "onConnect"});
+ haxe_Log.trace("" + name + " connected (" + ip + ")",{ fileName : "src/server/Main.hx", lineNumber : 353, className : "server.Main", methodName : "onConnect"});
var client = new Client(ws,req,id,name,0);
client.setGroupFlag(ClientGroup.Admin,this.config.localAdmins && req.socket.localAddress == ip);
this.clients.push(client);
@@ -4184,7 +4194,7 @@ server_Main.prototype = {
var obj = _gthis.wsEventParser.fromJson(data);
if(_gthis.wsEventParser.errors.length > 0 || _gthis.noTypeObj(obj)) {
var errors = "" + ("Wrong request for type \"" + obj.type + "\":") + "\n" + json2object_ErrorUtils.convertErrorArray(_gthis.wsEventParser.errors);
- haxe_Log.trace(errors,{ fileName : "src/server/Main.hx", lineNumber : 367, className : "server.Main", methodName : "onConnect"});
+ haxe_Log.trace(errors,{ fileName : "src/server/Main.hx", lineNumber : 369, className : "server.Main", methodName : "onConnect"});
_gthis.serverMessage(client,errors);
return;
}
@@ -4320,7 +4330,7 @@ server_Main.prototype = {
if(!internal) {
return;
}
- haxe_Log.trace("Client " + client.name + " disconnected",{ fileName : "src/server/Main.hx", lineNumber : 426, className : "server.Main", methodName : "onMessage"});
+ haxe_Log.trace("Client " + client.name + " disconnected",{ fileName : "src/server/Main.hx", lineNumber : 428, className : "server.Main", methodName : "onMessage"});
server_Utils.sortedPush(this.freeIds,client.id);
HxOverrides.remove(this.clients,client);
this.sendClientList();
@@ -4724,7 +4734,7 @@ server_Main.prototype = {
client.setGroupFlag(ClientGroup.Banned,!isOutdated);
if(isOutdated) {
HxOverrides.remove(this.userList.bans,ban);
- haxe_Log.trace("" + client.name + " ban removed",{ fileName : "src/server/Main.hx", lineNumber : 879, className : "server.Main", methodName : "checkBan"});
+ haxe_Log.trace("" + client.name + " ban removed",{ fileName : "src/server/Main.hx", lineNumber : 881, className : "server.Main", methodName : "checkBan"});
this.sendClientList();
}
break;
@@ -5061,5 +5071,6 @@ server_HttpServer.allowedLocalFiles = new haxe_ds_StringMap();
server_HttpServer.allowLocalRequests = false;
server_HttpServer.matchLang = new EReg("^[A-z]+","");
server_HttpServer.matchVarString = new EReg("\\${([A-z_]+)}","g");
+server_HttpServer.ctrlCharacters = new EReg("[\\u0000-\\u001F\\u007F-\\u009F\\u2000-\\u200D\\uFEFF]","g");
server_Main.main();
})(typeof window != "undefined" ? window : typeof global != "undefined" ? global : typeof self != "undefined" ? self : this);
diff --git a/src/server/HttpServer.hx b/src/server/HttpServer.hx
index c4853ee..7f257a4 100644
--- a/src/server/HttpServer.hx
+++ b/src/server/HttpServer.hx
@@ -50,7 +50,7 @@ class HttpServer {
}
public static function serveFiles(req:IncomingMessage, res:ServerResponse):Void {
- var url = decodeURI(req.url);
+ var url = safeDecodeURI(req.url);
if (url == "/") url = "/index.html";
var filePath = dir + url;
final ext = Path.extension(filePath).toLowerCase();
@@ -183,7 +183,7 @@ class HttpServer {
fn:(req:IncomingMessage) -> Bool
):Null<ClientRequest> {
final url = try {
- new URL(decodeURI(url));
+ new URL(safeDecodeURI(url));
} catch (e) return null;
if (url.host == req.headers["host"]) return null;
final options = {
@@ -216,6 +216,16 @@ class HttpServer {
return contentType;
}
+ static final ctrlCharacters = ~/[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/g;
+
+ static function safeDecodeURI(data:String):String {
+ try {
+ data = decodeURI(data);
+ } catch (err) {}
+ data = ctrlCharacters.replace(data, "");
+ return data;
+ }
+
static inline function decodeURI(data:String):String {
return js.Syntax.code("decodeURI({0})", data);
}
diff --git a/src/server/Main.hx b/src/server/Main.hx
index b038f01..49ac025 100644
--- a/src/server/Main.hx
+++ b/src/server/Main.hx
@@ -123,7 +123,7 @@ class Main {
});
wss = new WSServer({server: server});
wss.on("connection", onConnect);
- server.listen(port);
+ server.listen(port, onServerInited);
new Timer(25000).run = () -> {
for (client in clients) {
@@ -137,6 +137,8 @@ class Main {
};
}
+ dynamic function onServerInited():Void {};
+
public function exit():Void {
saveState();
logger.saveLog();
diff --git a/test/tests/TestServer.hx b/test/tests/TestServer.hx
new file mode 100644
index 0000000..4fcbb2e
--- /dev/null
+++ b/test/tests/TestServer.hx
@@ -0,0 +1,46 @@
+package test.tests;
+
+import js.node.Http;
+import server.Main;
+import utest.Assert;
+import utest.Async;
+import utest.Test;
+
+@:access(server)
+class TestServer extends Test {
+ @:timeout(500)
+ function testBadRequests(async:Async) {
+ final server = new Main();
+ server.onServerInited = () -> {
+ final url = 'http://${server.localIp}:${server.port}';
+ request('$url/你好,世界!@$^&*)_+-=', data -> {
+ Assert.equals("File 你好,世界!@$^&*)_+-= not found.", data);
+ });
+ request('$url/Привет%00мир!', data -> {
+ Assert.equals("File Приветмир! not found.", data);
+ });
+ request('$url/Ы%ы%00ы!', data -> {
+ Assert.equals("File %D0%AB%%D1%8B%00%D1%8B! not found.", data);
+ });
+ request('$url/video/skins/default.php?dir_inc=/etc/passwd%00', data -> {
+ Assert.equals("File video/skins/default.php?dir_inc=/etc/passwd not found.", data);
+ });
+ request('$url/%20', data -> {
+ Assert.equals("File not found.", data);
+ });
+ request('$url/build/../../server.js', data -> {
+ Assert.equals("File server.js not found.", data);
+ async.done();
+ });
+ }
+ }
+
+ function request(url:String, onComplete:(data:String) -> Void):Void {
+ Http.get(url, r -> {
+ r.setEncoding("utf8");
+ final data = new StringBuf();
+ r.on("data", chunk -> data.add(chunk));
+ r.on("end", _ -> onComplete(data.toString()));
+ }).on("error", e -> trace(e));
+ }
+}
diff --git a/tests.hxml b/tests.hxml
index c95f9d8..97efb41 100644
--- a/tests.hxml
+++ b/tests.hxml
@@ -1,6 +1,13 @@
--cp src
--cp test
+--library hxnodejs
+--library hxnodejs-ws
+--library json2object
+# Client libs for completion
+--library youtubeIFramePlayer:git:https://github.com/okawa-h/youtubeIFramePlayer-externs.git
+--library hls.js-extern:git:https://github.com/grosmar/hls.js-haxe-extern.git
+--library utest
+--class-path src
+--class-path test
--main Main
--lib utest
---interp
-#-D test=9133
+# -D UTEST_PATTERN=testMain
+--js build/tests.js
+--cmd node build/tests.js
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage