From d757b95b44f7db43b0726f2eca766a3f869094c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Rynning-T=C3=B8nnesen?= Date: Tue, 6 Mar 2018 13:02:53 +0100 Subject: [PATCH] Added more info on faulty input - Sent in the results on REST - Sent in the update_required msg on socket.io connection --- server/README.md | 386 +---------------------------- server/handlers/chat.js | 32 ++- server/handlers/frontpage.js | 8 +- server/handlers/io.js | 66 ++++- server/handlers/list.js | 98 ++++++-- server/handlers/list_change.js | 293 +++++++++++++++------- server/handlers/list_settings.js | 107 +++++--- server/handlers/search.js | 12 +- server/handlers/suggestions.js | 40 ++- server/public/assets/js/channel.js | 6 +- server/routing/client/api.js | 297 ++++++++++++++++------ 11 files changed, 728 insertions(+), 617 deletions(-) diff --git a/server/README.md b/server/README.md index 18fc5535..00e76cc2 100644 --- a/server/README.md +++ b/server/README.md @@ -2,391 +2,11 @@ Under ``` /server/apps/ ```, there are two files, ``` admin.js ``` and ``` client.js ```.``` admin.js ``` are for the adminpanel, and ``` client.js ``` are for zoff itself. + ## REST -All PUT, DELETE and POST endpoints have a 1-second waitlimit for each command per client. You'll get a response with Retry-After header for how long you have to wait. Shuffling in a player has a 5-second waitlimit, but per channel instead of per client. - -If you want to skip the wait-times, create a token at https://zoff.me/api/apply. Tokens are added to all the POST, PUT, DELETE, requests as ``` token: TOKEN ```. - -All requests return things on this form (results field is added if successful.) - -``` -{ - status: STATUSCODE, - error: MESSAGE, - success: IF_SUCCESSFULL, - results: [RESULTS] -} -``` - -Add song - -``` -POST /api/list/:channel_name/:video_id - { - "title": TITLE, - "duration": END_TIME - START_TIME, - "end_time": END_TIME, - "start_time": START_TIME, - "adminpass": PASSWORD, (leave this blank if there is no password/you don't know the password) - "userpass": USER_PASSWORD - } - -Returns 400 for bad request -Returns 403 for bad authentication (but will return a song object, with the type == "suggested", and the song will show up in the suggested tab for channel-admins) -Returns 409 if the song exists -Returns 429 if you're doing too much of this request, with a Retry-After int value in the header. -Returns 200 and the added song object if successful -``` - -Delete song -``` -DELETE /api/list/:channel_name/:video_id - { - "adminpass": PASSWORD, - "userpass": USER_PASSWORD - } - -Returns 400 for bad request -Returns 403 for bad authentication -Returns 404 if the song doesnt exist or is the currently playing song -Returns 429 if you're doing too much of this request, with a Retry-After int value in the header. -Returns 200 if successful -``` - -Vote on song -``` -PUT /api/list/:channel_name/:video_id - { - "adminpass": PASSWORD, - "userpass": USER_PASSWORD - } - -Returns 400 for bad request -Returns 403 for bad authentication -Returns 404 if the song doesnt exist -Returns 409 if you've already voted on that song -Returns 429 if you're doing too much of this request, with a Retry-After int value in the header. -Returns 200 and the added song object if successful -``` - -Change channel configurations -``` -PUT /api/conf/:channel_name - { - "userpass": USER_PASSWORD, - "adminpass": PASSWORD, - "vote": BOOLEAN, - "addsongs": BOOLEAN, - "longsongs": BOOLEAN, - "frontpage": BOOLEAN (if you want to set userpassword, this MUST be false for it to work), - "allvideos": BOOLEAN, - "removeplay": BOOLEAN, - "skip": BOOLEAN, - "shuffle": BOOLEAN, - "userpass_changed": BOOLEAN (this must be true if you want to keep the userpassword you're sending) - } - -Returns 400 for bad request -Returns 403 for bad authentication -Returns 404 if the list doesn't exist -Returns 429 if you're doing too much of this request, with a Retry-After int value in the header. -Returns 200 and the newly added configuration if successful -``` - -Get channelsettings -``` -GET /api/conf/:channel_name/ - -Returns 403 for bad authentication (if you get this, try POST with userpassword attached) -Returns 404 if the channel doesn't exist -Returns 200 and the settings-object -``` - -Get channelsettings (protected) -``` -POST /api/conf/:channel_name/ - { - "userpass": USERPASS - } - -Returns 400 for bad request -Returns 403 for bad authentication -Returns 404 if the channel doesn't exist -Returns 200 and the settings-object -``` - -Get song in channel -``` -GET /api/list/:channel_name/ - -Returns 403 for bad authentication (if you get this, the channel is protected, try getting the full channel with POST, and search through the object) -Returns 404 if the song doesn't exist -Returns 200 and the song -``` - -Get song in channel (protected) -``` -// Important fetch_song is present, or else the request will try to add a song to the channel -POST /api/list/:channel_name/ - { - "fetch_song": ANYTHING_HERE, - "userpass": USERPASS - } - -Returns 400 for bad request -Returns 403 for bad authentication -Returns 404 if the song doesn't exist -Returns 200 and the song -``` - -Get channelsettings -``` -GET /api/conf/:channel_name/ - -Returns 403 for bad authentication (if you get this, try POST with userpassword attached) -Returns 404 if the channel doesn't exist -Returns 200 and the objects in the channel -``` - -Get channelsettings (protected) -``` -POST /api/conf/:channel_name/ - { - "userpass": USERPASS - } - -Returns 400 for bad request -Returns 403 for bad authentication -Returns 404 if the channel doesn't exist -Returns 200 and the objects in the channel -``` - -Get now playing song -``` -GET /api/list/:channel_name/__np__ - -Returns 400 for bad request -Returns 403 for bad authentication (if you get this, try POST with userpassword attached) -Returns 404 if the channel doesn't exist -Returns 200 and the now playing object -``` - -Get now playing song (protected) -``` -POST /api/list/:channel_name/__np__ - { - "userpass": USERPASS - } - -Returns 400 for bad request -Returns 403 for bad authentication (if you get this, try POST with userpassword attached) -Returns 404 if the channel doesn't exist -Returns 200 and the now playing object -``` - -Get all lists -``` -GET /api/frontpages - -Returns 200 and the frontpage-lists -``` - -Still to come: SKIP and SHUFFLE RESTApi calls.. - +[Rest API info](REST.md) ## Events -### To server -``` -// Tells the server the song is over -'end', { - id: video_id, - channel: channel_name, - pass: channel_pass -} - -// Asks server where in the song it should be -'pos', { - channel: channel_name, - pass: channel_pass -} - -// Tells the server the client wants the list -'list', { - channel: channel_name, - pass: channel_pass, - version: system_version (can be checked in VERSION.js) -} - -// Sends info about a song the client wants to add -'add', { - id: VIDEO_ID, - title: VIDEO_TITLE, - adminpass: AES-CBC-Pkcs7 with Base64 IV(PASSWORD), - duration: VIDEO_DURATION, - list: channel_name, - playlist: true_if_importing_playlist, - num: current_number_of_sending_songs, - total: total_number_of_sending_songs, - pass: channel_pass -} - -// Tells the server to disconnect the user from the current channel, is used for remote controlling on the host side -'change_channel', { - channel: channel_name -} - -// Sends chat text to all chat -'all,chat', { - channel: channel_name, - data: input -} - -// Sends chat text to channelchat -'chat',{ - channel: channel_name, - data: input, - pass: channel_pass -} - -// Sends info about song the user wants to vote on. If VOTE_TYPE is del, its deleting the song, if its pos, its just voting -'vote', { - channel: CHANNEL_NAME, - id: VIDEO_ID, - type: VOTE_TYPE, - adminpass: AES-CBC-Pkcs7 with Base64 IV(PASSWORD) -} - -// Sends shuffle to the server (Only works every 5 seconds per list) -'shuffle', { - adminpass: AES-CBC-Pkcs7 with Base64 IV(PASSWORD), - channel: CHANNELNAME, - pass: USER_PASSWORD -} - -// Sends skip message to server -'skip', { - pass: AES-CBC-Pkcs7 with Base64 IV(PASSWORD), - id:video_id, - channel: chan, - userpass: channel_pass -} - -// Sends password for instant log in to server -'password', { - password: PASSWORD, - channel: CHANNEL_NAME, - oldpass: old_pass_if_changing_password -} - -// Sends message to the host channel for play -'id', { - id: CHANNEL_ID, - type: "play", - value: "mock" -} - -// Sends message to the host channel for pause -'id', { - id: CHANNEL_ID, - type: "pause", - value: "mock" -} - -// Sends message to the host channel for skip -'id', { - id: CHANNEL_ID, - type: "skip", - value: "mock" -} - -// Sends message to the host channel to change volume -'id', { - id: CHANNEL_ID, - type: "volume", - value: VALUE -} - -// Sends message to the host channel to change channel -'id', { - id: CHANNEL_ID, - type: "channel", - value: NEW_CHANNEL_NAME -} - -// Sends a video that triggered an error -'error_video', { - channel: CHANNE_NAME, - id: VIDEO_ID, - title: VIDEO_TITLE -} -``` - -### From server -``` -// Receives a string from server for what type of toast to be triggered -'toast', STRING - -// Receives a boolean if the password was correct -'pw', BOOLEAN - -// Receives configuration array from server -'conf', [ARRAY] - -// Receives chat message from allchat -'chat.all', { - from: name, - msg: message, - channel: channel, - icon: icon_src -} - -// Receives chat-history for all and for current channel -'chat_history', { - all: BOOLEAN (if true, it is for all-chat), - data: CHAT_HISTORY -} - -// Receives chat message from channelchat -'chat', { - from: name, - msg: message, - icon: icon_src -} - -// Receives the ID of the current client, used for remote listening -'id', STRING - -// Receives the messages sent on CHANNEL_ID above -id, { - type: STRING, - value: VALUE -} - -// Receives updates from channel. type is one of the following: list, added, deleted, vote, song_change, changed_values (see further down for better explanation here) -'channel', { - type: TYPE, - value: value, - time: time_of_occurence -} - -// Receives message from the server that its ready to send the playlist and info -'get_list' - -// Receives array of now playing song. Is triggered on song-change -'np', { - np: NOW_PLAYING, - conf: CONFIGURATION, - time: SERVER_TIME -} - -// Receives number of viewers on the current channel -'viewers', VALUE - -// Receives a newly updated video, that was checked for errors (song_generated contains .id which is the current id of the video, and a .new_id for the new video to change the video to) -'channel', { - type: "changed_values", - value: song_generated -} -``` +[Events sent form the server/to the server info](EVENTS.md) diff --git a/server/handlers/chat.js b/server/handlers/chat.js index 1c245e75..9197921c 100644 --- a/server/handlers/chat.js +++ b/server/handlers/chat.js @@ -29,10 +29,24 @@ function chat(msg, guid, offline, socket) { !msg.hasOwnProperty('channel') || !msg.hasOwnProperty('pass') || typeof(msg.data) != "string" || typeof(msg.channel) != "string" || typeof(msg.pass) != "string") { - socket.emit('update_required'); + var result = { + data: { + expected: "string", + got: msg.hasOwnProperty("data") ? typeof(msg.data) : undefined, + }, + channel: { + expected: "string", + got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined + }, + pass: { + expected: "string", + got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined + } + }; + socket.emit('update_required', result); return; } - var coll = msg.channel; + var coll = msg.channel.toLowerCase(); db.collection(coll + "_settings").find(function(err, docs){ if(docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || (msg.hasOwnProperty('pass') && docs[0].userpass == Functions.decrypt_string(socket.zoff_id, msg.pass)))) { var data = msg.data; @@ -64,10 +78,20 @@ function all_chat(msg, guid, offline, socket) { if(typeof(msg) !== 'object' || !msg.hasOwnProperty("channel") || !msg.hasOwnProperty("data") || typeof(msg.data) != "string" || typeof(msg.channel) != "string") { - socket.emit('update_required'); + var result = { + data: { + expected: "string", + got: msg.hasOwnProperty("data") ? typeof(msg.data) : undefined, + }, + channel: { + expected: "string", + got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined + } + }; + socket.emit('update_required', result); return; } - var coll = msg.channel; + var coll = msg.channel.toLowerCase(); var data = msg.data; Functions.check_inlist(coll, guid, socket, offline); diff --git a/server/handlers/frontpage.js b/server/handlers/frontpage.js index cfaec560..5cda8083 100644 --- a/server/handlers/frontpage.js +++ b/server/handlers/frontpage.js @@ -1,6 +1,12 @@ function frontpage_lists(msg, socket) { if(msg == undefined || !msg.hasOwnProperty('version') || msg.version != VERSION || msg.version == undefined) { - socket.emit("update_required"); + var result = { + version: { + expected: VERSION, + got: msg.hasOwnProperty("version") ? msg.version : undefined, + } + }; + socket.emit('update_required', result); return; } diff --git a/server/handlers/io.js b/server/handlers/io.js index b52d26d1..3866f8b9 100644 --- a/server/handlers/io.js +++ b/server/handlers/io.js @@ -54,7 +54,7 @@ module.exports = function() { guid = msg.guid; socketid = msg.socket_id; socket.zoff_id = socketid; - coll = msg.channel; + coll = msg.channel.toLowerCase(); in_list = true; chromecast_object = true; socket.join(coll); @@ -108,7 +108,13 @@ module.exports = function() { socket.on("removename", function(msg) { if(typeof(msg) != "object" || !msg.hasOwnProperty("channel")) { - socket.emit("update_required"); + var result = { + channel: { + expected: "string", + got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined, + } + }; + socket.emit('update_required', result); return; } Chat.removename(guid, msg.channel); @@ -117,7 +123,17 @@ module.exports = function() { socket.on("offline", function(msg){ if(!msg.hasOwnProperty('status') || !msg.hasOwnProperty('channel') || typeof(msg.status) != "boolean" || typeof(msg.channel) != "string") { - socket.emit("update_required"); + var result = { + status: { + expected: "boolean", + got: msg.hasOwnProperty("status") ? typeof(msg.status) : undefined, + }, + channel: { + expected: "string", + got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined + } + }; + socket.emit('update_required', result); return; } var status = msg.status; @@ -164,7 +180,21 @@ module.exports = function() { socket.on('get_history', function(msg) { if(!msg.hasOwnProperty("channel") || !msg.hasOwnProperty("all") || typeof(msg.channel) != "string" || typeof(msg.all) != "boolean") { - socket.emit("update_required"); + var result = { + all: { + expected: "boolean", + got: msg.hasOwnProperty("all") ? typeof(msg.all) : undefined, + }, + channel: { + expected: "string", + got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined, + }, + pass: { + expected: "string", + got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined, + } + }; + socket.emit('update_required', result); return; } Chat.get_history(msg.channel, msg.all, socket); @@ -219,7 +249,7 @@ module.exports = function() { { if(coll === undefined) { try { - coll = obj.channel; + coll = obj.channel.toLowerCase(); if(coll.length == 0) return; coll = emojiStrip(coll).toLowerCase(); coll = coll.replace("_", ""); @@ -252,7 +282,7 @@ module.exports = function() { socket.on('delete_all', function(msg) { if(coll !== undefined) { try { - coll = msg.channel; + coll = msg.channel.toLowerCase(); if(coll.length == 0) return; coll = emojiStrip(coll).toLowerCase(); coll = coll.replace("_", ""); @@ -270,7 +300,7 @@ module.exports = function() { { if(coll !== undefined) { try { - coll = msg.channel; + coll = msg.channel.toLowerCase(); if(coll.length == 0) return; coll = emojiStrip(coll).toLowerCase(); coll = coll.replace("_", ""); @@ -302,7 +332,7 @@ module.exports = function() { { if(coll !== undefined) { try { - coll = msg.channel; + coll = msg.channel.toLowerCase(); if(coll.length == 0) return; coll = emojiStrip(coll).toLowerCase(); coll = coll.replace("_", ""); @@ -319,7 +349,7 @@ module.exports = function() { { if(coll === undefined && obj !== undefined && obj.channel !== undefined){ try { - coll = obj.channel; + coll = obj.channel.toLowerCase(); if(coll.length == 0) return; coll = emojiStrip(coll).toLowerCase(); coll = coll.replace("_", ""); @@ -364,7 +394,7 @@ module.exports = function() { (obj.hasOwnProperty("pass") && typeof(obj.pass) != "string")) if(coll !== undefined) { try { - coll = obj.channel; + coll = obj.channel.toLowerCase(); if(coll.length == 0) return; coll = emojiStrip(coll).toLowerCase(); coll = coll.replace("_", ""); @@ -375,8 +405,20 @@ module.exports = function() { } } - if(coll == "" || coll == undefined || coll == null) { - socket.emit("update_required"); + if(coll == "" || coll == undefined || coll == null ||  + !obj.hasOwnProperty("channel") || typeof(obj.channel) != "string" || + obj.hasOwnProperty("pass") || typeof(obj.pass) != "string") { + var result = { + channel: { + expected: "string", + got: obj.hasOwnProperty("channel") ? typeof(obj.channel) : undefined + }, + pass: { + expected: "string", + got: obj.hasOwnProperty("pass") ? typeof(obj.pass) : undefined + } + }; + socket.emit('update_required', result); return; } diff --git a/server/handlers/list.js b/server/handlers/list.js index f3f5432a..eeaf7ce6 100644 --- a/server/handlers/list.js +++ b/server/handlers/list.js @@ -20,18 +20,29 @@ function now_playing(list, fn, socket) { function list(msg, guid, coll, offline, socket) { var socketid = socket.zoff_id; - if(typeof(msg) === 'object' && msg !== undefined && msg !== null && msg.hasOwnProperty("channel") && msg.hasOwnProperty('pass')) + if(typeof(msg) === 'object' && msg !== undefined && msg !== null) { - if(!msg.hasOwnProperty('version') || msg.version != VERSION || msg.version == undefined || + if(!msg.hasOwnProperty('version') || !msg.hasOwnProperty("channel") || !msg.hasOwnProperty("pass") || + msg.version != VERSION || msg.version == undefined || typeof(msg.channel) != "string" || typeof(msg.pass) != "string") { - socket.emit("update_required"); - return; - } - - if(coll == "" || coll == undefined || coll == null) { - socket.emit("update_required"); + var result = { + channel: { + expected: "string", + got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined, + }, + version: { + expected: VERSION, + got: msg.version, + }, + pass: { + expected: "string", + got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined, + }, + }; + socket.emit('update_required', result); return; } + coll = msg.channel.toLowerCase(); var pass = Functions.decrypt_string(socketid, msg.pass); db.collection('frontpage_lists').find({"_id": coll}, function(err, frontpage_lists){ if(frontpage_lists.length == 1) @@ -70,7 +81,13 @@ function list(msg, guid, coll, offline, socket) { } }); } else { - socket.emit('update_required'); + var result = { + msg: { + expected: "object", + got: typeof(msg) + }, + }; + socket.emit('update_required', result); } } @@ -79,10 +96,10 @@ function skip(list, guid, coll, offline, socket) { if(list !== undefined && list !== null && list !== "") { - if(coll == undefined && list.hasOwnProperty('channel')) coll = list.channel; + if(coll == undefined && list.hasOwnProperty('channel')) coll = list.channel.toLowerCase(); if(coll !== undefined) { try { - coll = list.channel; + coll = list.channel.toLowerCase(); if(coll.length == 0) return; coll = emojiStrip(coll).toLowerCase(); coll = coll.replace("_", ""); @@ -92,9 +109,29 @@ function skip(list, guid, coll, offline, socket) { return; } } - if(typeof(list.pass) != "string" || typeof(list.id) != "string" || + if(!list.hasOwnProperty("pass") || !list.hasOwnProperty("userpass") || + !list.hasOwnProperty("id") || !list.hasOwnProperty("channel") || + typeof(list.pass) != "string" || typeof(list.id) != "string" || typeof(list.channel) != "string" || typeof(list.userpass) != "string") { - socket.emit("update_required"); + var result = { + channel: { + expected: "string", + got: list.hasOwnProperty("channel") ? typeof(list.channel) : undefined, + }, + pass: { + expected: "string", + got: list.hasOwnProperty("pass") ? typeof(list.pass) : undefined, + }, + userpass: { + expected: "string", + got: list.hasOwnProperty("userpass") ? typeof(list.userpass) : undefined, + }, + id: { + expected: "string", + got: list.hasOwnProperty("id") ? typeof(list.id) : undefined, + }, + }; + socket.emit('update_required', result); return; } db.collection(coll + "_settings").find(function(err, docs){ @@ -165,7 +202,13 @@ function skip(list, guid, coll, offline, socket) { } }); } else { - socket.emit('update_required'); + var result = { + msg: { + expected: "object", + got: typeof(list), + }, + }; + socket.emit("update_required", result); } } @@ -435,9 +478,24 @@ function end(obj, coll, guid, offline, socket) { if(id !== undefined && id !== null && id !== "") { - if(coll == "" || coll == undefined || coll == null || typeof(obj.id) != "string" || typeof(obj.channel) != "string" || + if(!obj.hasOwnProperty("id") || !obj.hasOwnProperty("channel") || !obj.hasOwnProperty("pass") || + typeof(obj.id) != "string" || typeof(obj.channel) != "string" || typeof(obj.pass) != "string") { - socket.emit("update_required"); + var result = { + channel: { + expected: "string", + got: obj.hasOwnProperty("channel") ? typeof(obj.channel) : undefined, + }, + pass: { + expected: "string", + got: obj.hasOwnProperty("pass") ? typeof(obj.pass) : undefined, + }, + id: { + expected: "string", + got: obj.hasOwnProperty("id") ? typeof(obj.id) : undefined, + }, + }; + socket.emit("update_required", result); return; } @@ -470,7 +528,13 @@ function end(obj, coll, guid, offline, socket) { } }); } else { - socket.emit('update_required'); + var result = { + msg: { + expected: "object", + got: typeof(obj) + }, + }; + socket.emit("update_required", result); } } diff --git a/server/handlers/list_change.js b/server/handlers/list_change.js index 3cddf64b..fe90fe10 100644 --- a/server/handlers/list_change.js +++ b/server/handlers/list_change.js @@ -3,8 +3,19 @@ function add_function(arr, coll, guid, offline, socket) { if(typeof(arr) === 'object' && arr !== undefined && arr !== null && arr !== "" && !isNaN(parseInt(arr.duration))) { - if(coll == "" || coll == undefined || coll == null || !arr.hasOwnProperty("start") || !arr.hasOwnProperty("end")) { - socket.emit("update_required"); + if(coll == "" || coll == undefined || coll == null || + !arr.hasOwnProperty("start") || !arr.hasOwnProperty("end")) { + var result = { + start: { + expected: "number or string that can be cast to int", + got: arr.hasOwnProperty("start") ? typeof(arr.start) : undefined + }, + end: { + expected: "number or string that can be cast to int", + got: arr.hasOwnProperty("end") ? typeof(arr.end) : undefined + } + }; + socket.emit('update_required', result); return; } @@ -34,7 +45,49 @@ function add_function(arr, coll, guid, offline, socket) { typeof(arr.playlist) != "boolean" || typeof(arr.num) != "number" || typeof(arr.total) != "number" || typeof(arr.pass) != "string" || typeof(arr.adminpass) != "string") { - socket.emit("update_required"); + var result = { + start: { + expected: "number or string that can be cast to int", + got: arr.hasOwnProperty("start") ? typeof(arr.start) : undefined + }, + end: { + expected: "number or string that can be cast to int", + got: arr.hasOwnProperty("end") ? typeof(arr.end) : undefined + }, + title: { + expected: "string", + got: arr.hasOwnProperty("title") ? typeof(arr.title) : undefined + }, + list: { + expected: "string", + got: arr.hasOwnProperty("list") ? typeof(arr.list) : undefined + }, + duration: { + expected: "number or string that can be cast to int", + got: arr.hasOwnProperty("duration") ? typeof(arr.duration) : undefined + }, + playlist: { + expected: "boolean", + got: arr.hasOwnProperty("playlist") ? typeof(arr.playlist) : undefined + }, + num: { + expected: "number or string that can be cast to int", + got: arr.hasOwnProperty("num") ? typeof(arr.num) : undefined + }, + total: { + expected: "number or string that can be cast to int", + got: arr.hasOwnProperty("total") ? typeof(arr.total) : undefined + }, + pass: { + expected: "string", + got: arr.hasOwnProperty("pass") ? typeof(arr.pass) : undefined + }, + adminpass: { + expected: "string", + got: arr.hasOwnProperty("adminpass") ? typeof(arr.adminpass) : undefined + } + }; + socket.emit('update_required', result); return; } @@ -176,7 +229,17 @@ function add_function(arr, coll, guid, offline, socket) { } }); } else { - socket.emit('update_required'); + var result = { + arr: { + expected: "object", + got: typeof(arr) + }, + duration: { + expected: "number or string that can be cast to int", + got: arr.hasOwnProperty("duration") ? typeof(arr.duration) : undefined, + } + }; + socket.emit('update_required', result); } } @@ -184,19 +247,39 @@ function voteUndecided(msg, coll, guid, offline, socket) { var socketid = socket.zoff_id; if(typeof(msg) === 'object' && msg !== undefined && msg !== null){ - if(coll == "" || coll == undefined || coll == null || !msg.hasOwnProperty("adminpass") || !msg.hasOwnProperty("pass") || !msg.hasOwnProperty("id")) { - socket.emit("update_required"); - return; - } - - if(typeof(msg.channel) != "string" || typeof(msg.id) != "string" || - typeof(msg.type) != "string" || typeof(msg.adminpass) != "string" || - typeof(msg.pass) != "string") { - socket.emit("update_required"); + if(!msg.hasOwnProperty("channel") || !msg.hasOwnProperty("id") || + !msg.hasOwnProperty("type") || !msg.hasOwnProperty("adminpass") || + !msg.hasOwnProperty("pass") || typeof(msg.pass) != "string" || + typeof(msg.channel) != "string" || typeof(msg.id) != "string" || + typeof(msg.type) != "string" || typeof(msg.adminpass) != "string") { + var result = { + channel: { + expected: "string", + got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined, + }, + id: { + expected: "string", + got: msg.hasOwnProperty("id") ? typeof(msg.id) : undefined, + }, + type: { + expected: "string", + got: msg.hasOwnProperty("type") ? typeof(msg.type) : undefined, + }, + adminpass: { + expected: "adminpass", + got: msg.hasOwnProperty("adminpass") ? typeof(msg.adminpass) : undefined, + }, + pass: { + expected: "string", + got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined, + }, + }; + socket.emit('update_required', result); return; } + coll = msg.channel.toLowerCase();; - db.collection(coll + "_settings").find(function(err, docs){ + db.collection(coll + "_settings").find({id: "config"}, function(err, docs){ if(docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || (msg.hasOwnProperty('pass') && docs[0].userpass == Functions.decrypt_string(socketid, msg.pass)))) { Functions.check_inlist(coll, guid, socket, offline); @@ -218,84 +301,99 @@ function voteUndecided(msg, coll, guid, offline, socket) { } }); } else { - socket.emit('update_required'); + var result = { + msg: { + expected: "object", + got: typeof(msg) + } + }; + socket.emit('update_required', result); } } function shuffle(msg, coll, guid, offline, socket) { var socketid = socket.zoff_id; - if(msg.hasOwnProperty('adminpass') && msg.adminpass !== undefined && msg.adminpass !== null) - { - if(coll == "" || coll == undefined || coll == null) { - socket.emit("update_required"); + + + if(!msg.hasOwnProperty("adminpass") || !msg.hasOwnProperty("channel") || + !msg.hasOwnProperty("pass") || typeof(msg.adminpass) != "string" || + typeof(msg.channel) != "string" || typeof(msg.pass) != "string") { + var result = { + channel: { + expected: "string", + got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined, + }, + adminpass: { + expected: "adminpass", + got: msg.hasOwnProperty("adminpass") ? typeof(msg.adminpass) : undefined, + }, + pass: { + expected: "string", + got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined, + }, + }; + socket.emit('update_required', result); return; } + coll = msg.channel.toLowerCase(); - if(typeof(msg.adminpass) != "string" || typeof(msg.channel) != "string" || - typeof(msg.pass) != "string") { - socket.emit("update_required"); + db.collection("timeout_api").find({ + type: "shuffle", + guid: coll, + }, function(err, docs) { + if(docs.length > 0) { + var date = new Date(docs[0].createdAt); + date.setSeconds(date.getSeconds() + 5); + var now = new Date(); + var retry_in = (date.getTime() - now.getTime()) / 1000; + if(retry_in > 0) { + socket.emit("toast", "wait_longer"); return; } - - db.collection("timeout_api").find({ - type: "shuffle", - guid: coll, - }, function(err, docs) { - if(docs.length > 0) { - var date = new Date(docs[0].createdAt); - date.setSeconds(date.getSeconds() + 5); - var now = new Date(); - var retry_in = (date.getTime() - now.getTime()) / 1000; - if(retry_in > 0) { - socket.emit("toast", "wait_longer"); - return; - } - } - var now_date = new Date(); - db.collection("timeout_api").update({type: "shuffle", guid: coll}, { - $set: { - "createdAt": now_date, - type: "shuffle", - guid: coll, - }, - }, {upsert: true}, function(err, docs) { - Functions.check_inlist(coll, guid, socket, offline); - var hash; - if(msg.adminpass === "") hash = msg.adminpass; - else hash = Functions.hash_pass(Functions.decrypt_string(socketid, msg.adminpass)); - db.collection(coll + "_settings").find(function(err, docs){ - if(docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || (msg.hasOwnProperty('pass') && docs[0].userpass == Functions.decrypt_string(socketid, msg.pass)))) { - if(docs !== null && docs.length !== 0 && ((docs[0].adminpass == hash || docs[0].adminpass === "") || docs[0].shuffle === false)) - { - db.collection(coll).find({now_playing:false}).forEach(function(err, docs){ - if(!docs){ - List.send_list(coll, undefined, false, true, false, true); - socket.emit("toast", "shuffled"); - - return; - }else{ - num = Math.floor(Math.random()*1000000); - db.collection(coll).update({id:docs.id}, {$set:{added:num}}); - } - }); - }else - socket.emit("toast", "wrongpass"); - } else { - socket.emit("auth_required"); - } - }); - - var complete = function(tot, curr){ - if(tot == curr) + } + var now_date = new Date(); + db.collection("timeout_api").update({type: "shuffle", guid: coll}, { + $set: { + "createdAt": now_date, + type: "shuffle", + guid: coll, + }, + }, {upsert: true}, function(err, docs) { + Functions.check_inlist(coll, guid, socket, offline); + var hash; + if(msg.adminpass === "") hash = msg.adminpass; + else hash = Functions.hash_pass(Functions.decrypt_string(socketid, msg.adminpass)); + db.collection(coll + "_settings").find(function(err, docs){ + if(docs.length > 0 && (docs[0].userpass == undefined || docs[0].userpass == "" || (msg.hasOwnProperty('pass') && docs[0].userpass == Functions.decrypt_string(socketid, msg.pass)))) { + if(docs !== null && docs.length !== 0 && ((docs[0].adminpass == hash || docs[0].adminpass === "") || docs[0].shuffle === false)) { - List.send_list(coll, undefined, false, true, false); - List.getNextSong(coll); - } - }; + db.collection(coll).find({now_playing:false}).forEach(function(err, docs){ + if(!docs){ + List.send_list(coll, undefined, false, true, false, true); + socket.emit("toast", "shuffled"); + + return; + }else{ + num = Math.floor(Math.random()*1000000); + db.collection(coll).update({id:docs.id}, {$set:{added:num}}); + } + }); + }else + socket.emit("toast", "wrongpass"); + } else { + socket.emit("auth_required"); + } }); + + var complete = function(tot, curr){ + if(tot == curr) + { + List.send_list(coll, undefined, false, true, false); + List.getNextSong(coll); + } + }; }); - }else - socket.emit("toast", "wrongpass"); + }); } function del(params, socket, socketid) { @@ -328,15 +426,30 @@ function del(params, socket, socketid) { function delete_all(msg, coll, guid, offline, socket) { var socketid = socket.zoff_id; - if(typeof(msg) == 'object' && msg.hasOwnProperty('channel') && msg.hasOwnProperty('adminpass') && msg.hasOwnProperty('pass')) { - var hash = Functions.hash_pass(Functions.decrypt_string(socketid, msg.adminpass)); - var hash_userpass = Functions.decrypt_string(socketid, msg.pass); - - if(typeof(msg.channel) != "string" || typeof(msg.adminpass) != "string" || - typeof(msg.pass) != "string") { - socket.emit("update_required"); + if(typeof(msg) == 'object' ) { + if(!msg.hasOwnProperty('channel') || !msg.hasOwnProperty('adminpass') || + !msg.hasOwnProperty('pass') || typeof(msg.channel) != "string" || + typeof(msg.adminpass) != "string" || typeof(msg.pass) != "string") { + var result = { + channel: { + expected: "string", + got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined, + }, + adminpass: { + expected: "adminpass", + got: msg.hasOwnProperty("adminpass") ? typeof(msg.adminpass) : undefined, + }, + pass: { + expected: "string", + got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined, + }, + }; + socket.emit('update_required', result); return; } + + var hash = Functions.hash_pass(Functions.decrypt_string(socketid, msg.adminpass)); + var hash_userpass = Functions.decrypt_string(socketid, msg.pass); db.collection(coll + "_settings").find(function(err, conf) { if(conf.length == 1 && conf) { conf = conf[0]; @@ -352,7 +465,13 @@ function delete_all(msg, coll, guid, offline, socket) { } }); } else { - socket.emit("update_required"); + var result = { + msg: { + expected: "object", + got: typeof(msg) + }, + }; + socket.emit('update_required', result); return; } } diff --git a/server/handlers/list_settings.js b/server/handlers/list_settings.js index 5c2a9153..854cbb9a 100644 --- a/server/handlers/list_settings.js +++ b/server/handlers/list_settings.js @@ -3,7 +3,17 @@ function password(inp, coll, guid, offline, socket) { { if(!inp.hasOwnProperty("password") || !inp.hasOwnProperty("channel") || typeof(inp.password) != "string" || typeof(inp.channel) != "string") { - socket.emit("update_required"); + var result = { + channel: { + expected: "string", + got: inp.hasOwnProperty("channel") ? typeof(iinp.channel) : undefined, + }, + password: { + expected: "password", + got: inp.hasOwnProperty("password") ? typeof(inp.password) : undefined, + }, + }; + socket.emit('update_required', result); return; } pw = inp.password; @@ -19,11 +29,6 @@ function password(inp, coll, guid, offline, socket) { return; } - if(coll == "" || coll == undefined || coll == null) { - socket.emit("update_required"); - return; - } - uncrypted = pw; pw = Functions.decrypt_string(socket.zoff_id, pw); Functions.check_inlist(coll, guid, socket, offline); @@ -51,22 +56,18 @@ function password(inp, coll, guid, offline, socket) { } }); } else { - socket.emit('update_required'); + var result = { + inp: { + expected: "string", + got: typeof(inpt) + }, + }; + socket.emit('update_required', result); } } function conf_function(params, coll, guid, offline, socket) { - if(params !== undefined && params !== null && params !== "" && - params.hasOwnProperty('voting') && - params.hasOwnProperty('addsongs') && - params.hasOwnProperty('longsongs') && - params.hasOwnProperty('frontpage') && - params.hasOwnProperty('allvideos') && - params.hasOwnProperty('removeplay') && - params.hasOwnProperty('adminpass') && - params.hasOwnProperty('skipping') && - params.hasOwnProperty('shuffling') && - params.hasOwnProperty('channel')) + if(params !== undefined && params !== null && params !== "") { if(coll !== undefined) { try { @@ -88,6 +89,59 @@ function conf_function(params, coll, guid, offline, socket) { Functions.check_inlist(coll, guid, socket, offline); + + if(!params.hasOwnProperty('voting') || !params.hasOwnProperty('addsongs') || + !params.hasOwnProperty('longsongs') || !params.hasOwnProperty('frontpage') || + !params.hasOwnProperty('allvideos') || !params.hasOwnProperty('removeplay') || + !params.hasOwnProperty('adminpass') || !params.hasOwnProperty('skipping') || + !params.hasOwnProperty('shuffling') || !params.hasOwnProperty('channel') || + typeof(params.userpass) != "string" || typeof(params.adminpass) != "string" || + typeof(params.voting) != "boolean" || typeof(params.addsongs) != "boolean" || + typeof(params.longsongs) != "boolean" || typeof(params.frontpage) != "boolean" || + typeof(params.allvideos) != "boolean" || typeof(params.removeplay) != "boolean" || + typeof(params.skipping) != "boolean" || typeof(params.shuffling) != "boolean" || + typeof(params.userpass_changed) != "boolean") { + var result = { + adminpass: { + expected: "string", + got: params.hasOwnProperty("adminpass") ? typeof(params.adminpass) : undefined, + }, + userpass: { + expected: "string", + got: params.hasOwnProperty("userpass") ? typeof(params.userpass) : undefined, + }, + vote: { + expected: "boolean", + got: params.hasOwnProperty("vote") ? typeof(params.vote) : undefined, + }, + addsongs: { + expected: "boolean", + got: params.hasOwnProperty("addsongs") ? typeof(params.addsongs) : undefined, + }, + longsongs: { + expected: "boolean", + got: params.hasOwnProperty("longsongs") ? typeof(params.longsongs) : undefined, + }, + frontpage: { + expected: "boolean", + got: params.hasOwnProperty("frontpage") ? typeof(params.frontpage) : undefined, + }, + skipping: { + expected: "boolean", + got: params.hasOwnProperty("skipping") ? typeof(params.skipping) : undefined, + }, + shuffling: { + expected: "boolean", + got: params.hasOwnProperty("shuffling") ? typeof(params.shuffling) : undefined, + }, + userpass_changed: { + expected: "boolean", + got: params.hasOwnProperty("userpass_changed") ? typeof(params.userpass_changed) : undefined, + } + }; + socket.emit("update_required", result); + return; + } var voting = params.voting; var addsongs = params.addsongs; var longsongs = params.longsongs; @@ -98,15 +152,6 @@ function conf_function(params, coll, guid, offline, socket) { var skipping = params.skipping; var shuffling = params.shuffling; var userpass = Functions.decrypt_string(socket.zoff_id, params.userpass); - if(typeof(userpass) != "string" || typeof(adminpass) != "string" || - typeof(voting) != "boolean" || typeof(addsongs) != "boolean" || - typeof(longsongs) != "boolean" || typeof(frontpage) != "boolean" || - typeof(allvideos) != "boolean" || typeof(removeplay) != "boolean" || - typeof(skipping) != "boolean" || typeof(shuffling) != "boolean" || - typeof(params.userpass_changed) != "boolean") { - socket.emit("toast", "wrongpass"); - return; - } if((!params.userpass_changed && frontpage) || (params.userpass_changed && userpass == "")) { userpass = ""; @@ -162,7 +207,13 @@ function conf_function(params, coll, guid, offline, socket) { } }); } else { - socket.emit('update_required'); + var result = { + params: { + expected: "object", + got: typeof(params), + } + } + socket.emit('update_required', result); } } diff --git a/server/handlers/search.js b/server/handlers/search.js index dc30feb5..4e3058df 100644 --- a/server/handlers/search.js +++ b/server/handlers/search.js @@ -69,7 +69,17 @@ function get_correct_info(song_generated, channel, broadcast, callback) { function check_error_video(msg, channel) { if(!msg.hasOwnProperty("id") || !msg.hasOwnProperty("title") || typeof(msg.id) != "string" || typeof(msg.title) != "string") { - socket.emit("update_required"); + var result = { + id: { + expected: "string", + got: msg.hasOwnProperty("id") ? typeof(msg.id) : undefined, + }, + title: { + expected: "string", + got: msg.hasOwnProperty("title") ? typeof(msg.title) : undefined, + }, + }; + socket.emit("update_required", result); return; } diff --git a/server/handlers/suggestions.js b/server/handlers/suggestions.js index be54cc2d..60318e06 100644 --- a/server/handlers/suggestions.js +++ b/server/handlers/suggestions.js @@ -2,7 +2,25 @@ function thumbnail(msg, coll, guid, offline, socket) { if(msg.thumbnail && msg.channel && msg.adminpass && msg.thumbnail.indexOf("i.imgur.com") > -1){ if(typeof(msg.channel) != "string" || typeof(msg.thumbnail) != "string" || typeof(msg.adminpass) != "string" || typeof(msg.pass) != "string") { - socket.emit("update_required"); + var result = { + channel: { + expected: "string", + got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined, + }, + pass: { + expected: "string", + got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined, + }, + thumbnail: { + expected: "string", + got: msg.hasOwnProperty("thumbnail") ? typeof(msg.thumbnail) : undefined, + }, + adminpass: { + expected: "string", + got: msg.hasOwnProperty("adminpass") ? typeof(msg.adminpass) : undefined, + }, + }; + socket.emit("update_required", result); return; } msg.thumbnail = msg.thumbnail.replace(/^https?\:\/\//i, ""); @@ -30,7 +48,25 @@ function description(msg, coll, guid, offline, socket) { if(msg.description && msg.channel && msg.adminpass && msg.description.length < 100){ if(typeof(msg.channel) != "string" || typeof(msg.description) != "string" || typeof(msg.adminpass) != "string" || typeof(msg.pass) != "string") { - socket.emit("update_required"); + var result = { + channel: { + expected: "string", + got: msg.hasOwnProperty("channel") ? typeof(msg.channel) : undefined, + }, + pass: { + expected: "string", + got: msg.hasOwnProperty("pass") ? typeof(msg.pass) : undefined, + }, + description: { + expected: "string", + got: msg.hasOwnProperty("description") ? typeof(msg.description) : undefined, + }, + adminpass: { + expected: "string", + got: msg.hasOwnProperty("adminpass") ? typeof(msg.adminpass) : undefined, + }, + }; + socket.emit("update_required", result); return; } var channel = msg.channel.toLowerCase(); diff --git a/server/public/assets/js/channel.js b/server/public/assets/js/channel.js index cb0ddec4..5cb52cd3 100644 --- a/server/public/assets/js/channel.js +++ b/server/public/assets/js/channel.js @@ -93,7 +93,11 @@ var Channel = { if(socket === undefined || Helper.mobilecheck()){ no_socket = false; socket = io.connect(''+add+':8080', connection_options); - socket.on('update_required', function() { + socket.on('update_required', function(msg) { + if(window.location.hostname == "localhost") { + console.log(msg); + return; + } window.location.reload(true); }); } diff --git a/server/routing/client/api.js b/server/routing/client/api.js index 6aac41f3..acd72c3a 100644 --- a/server/routing/client/api.js +++ b/server/routing/client/api.js @@ -119,7 +119,19 @@ router.route('/api/list/:channel_name/:video_id').delete(function(req, res) { res.header({"Content-Type": "application/json"}); if(!req.body.hasOwnProperty('adminpass') || !req.body.hasOwnProperty('userpass') || !req.params.hasOwnProperty('channel_name') || !req.params.hasOwnProperty('video_id')) { - res.status(400).send(JSON.stringify(error.formatting)); + var result = { + adminpass: { + expected: "string", + got: req.body.hasOwnProperty("adminpass") ? typeof(req.body.adminpass) : undefined, + }, + userpass: { + expected: "string", + got: req.body.hasOwnProperty("userpass") ? typeof(req.body.userpass) : undefined + } + }; + var to_send = error.formatting; + to_send.results.push(result); + res.status(400).send(JSON.stringify(to_send)); return; } var token = ""; @@ -138,7 +150,19 @@ router.route('/api/list/:channel_name/:video_id').delete(function(req, res) { throw "Wrong format"; } } catch(e) { - res.status(400).send(JSON.stringify(error.formatting)); + var result = { + adminpass: { + expected: "string", + got: req.body.hasOwnProperty("adminpass") ? typeof(req.body.adminpass) : undefined, + }, + userpass: { + expected: "string", + got: req.body.hasOwnProperty("userpass") ? typeof(req.body.userpass) : undefined + } + }; + var to_send = error.formatting; + to_send.results.push(result); + res.status(400).send(JSON.stringify(to_send)); return; } @@ -202,20 +226,20 @@ router.route('/api/conf/:channel_name').put(function(req, res) { res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.header({"Content-Type": "application/json"}); - if(!req.body.hasOwnProperty('adminpass') || !req.body.hasOwnProperty('userpass') || - !req.params.hasOwnProperty('channel_name') || !req.body.hasOwnProperty('vote') || - !req.body.hasOwnProperty('addsongs') || !req.body.hasOwnProperty('longsongs') || - !req.body.hasOwnProperty('frontpage') || !req.body.hasOwnProperty('allvideos') || - !req.body.hasOwnProperty('skip') || !req.body.hasOwnProperty('shuffle') || - !req.body.hasOwnProperty('userpass_changed')) { - res.status(400).send(JSON.stringify(error.formatting)); - return; - } - var token = ""; - if(req.body.hasOwnProperty("token")) { - token = req.body.token; - } try { + if(!req.body.hasOwnProperty('adminpass') || !req.body.hasOwnProperty('userpass') || + !req.params.hasOwnProperty('channel_name') || !req.body.hasOwnProperty('vote') || + !req.body.hasOwnProperty('addsongs') || !req.body.hasOwnProperty('longsongs') || + !req.body.hasOwnProperty('frontpage') || !req.body.hasOwnProperty('allvideos') || + !req.body.hasOwnProperty('skip') || !req.body.hasOwnProperty('shuffle') || + !req.body.hasOwnProperty('userpass_changed')) { + throw "Wrong format"; + } + var token = ""; + if(req.body.hasOwnProperty("token")) { + token = req.body.token; + } + var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; var guid = Functions.hash_pass(req.get('User-Agent') + ip + req.headers["accept-language"]); var adminpass = req.body.adminpass == "" ? "" : Functions.hash_pass(crypto.createHash('sha256').update(req.body.adminpass, 'utf8').digest("hex")); @@ -240,7 +264,47 @@ router.route('/api/conf/:channel_name').put(function(req, res) { throw "Wrong format"; } } catch(e) { - res.status(400).send(JSON.stringify(error.formatting)); + var result = { + adminpass: { + expected: "string", + got: req.body.hasOwnProperty("adminpass") ? typeof(req.body.adminpass) : undefined, + }, + userpass: { + expected: "string", + got: req.body.hasOwnProperty("userpass") ? typeof(req.body.userpass) : undefined, + }, + vote: { + expected: "boolean", + got: req.body.hasOwnProperty("vote") ? typeof(req.body.vote) : undefined, + }, + addsongs: { + expected: "boolean", + got: req.body.hasOwnProperty("addsongs") ? typeof(req.body.addsongs) : undefined, + }, + longsongs: { + expected: "boolean", + got: req.body.hasOwnProperty("longsongs") ? typeof(req.body.longsongs) : undefined, + }, + frontpage: { + expected: "boolean", + got: req.body.hasOwnProperty("frontpage") ? typeof(req.body.frontpage) : undefined, + }, + skip: { + expected: "boolean", + got: req.body.hasOwnProperty("skip") ? typeof(req.body.skip) : undefined, + }, + shuffle: { + expected: "boolean", + got: req.body.hasOwnProperty("shuffle") ? typeof(req.body.shuffle) : undefined, + }, + userpass_changed: { + expected: "boolean", + got: req.body.hasOwnProperty("userpass_changed") ? typeof(req.body.userpass_changed) : undefined, + } + }; + var to_send = error.formatting; + to_send.results.push(result); + res.status(400).send(JSON.stringify(result)); return; } @@ -322,16 +386,15 @@ router.route('/api/list/:channel_name/:video_id').put(function(req,res) { res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.header({"Content-Type": "application/json"}); - if(!req.body.hasOwnProperty('adminpass') || !req.body.hasOwnProperty('userpass') || - !req.params.hasOwnProperty('channel_name') || !req.params.hasOwnProperty('video_id')) { - res.status(400).send(JSON.stringify(error.formatting)); - return; - } - var token = ""; - if(req.body.hasOwnProperty("token")) { - token = req.body.token; - } try { + if(!req.body.hasOwnProperty('adminpass') || !req.body.hasOwnProperty('userpass') || + !req.params.hasOwnProperty('channel_name') || !req.params.hasOwnProperty('video_id')) { + throw "Wrong format"; + } + var token = ""; + if(req.body.hasOwnProperty("token")) { + token = req.body.token; + } var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; var guid = Functions.hash_pass(req.get('User-Agent') + ip + req.headers["accept-language"]); var adminpass = req.body.adminpass == "" ? "" : Functions.hash_pass(crypto.createHash('sha256').update(req.body.adminpass, 'utf8').digest("hex")); @@ -343,7 +406,19 @@ router.route('/api/list/:channel_name/:video_id').put(function(req,res) { throw "Wrong format"; } } catch(e) { - res.status(400).send(JSON.stringify(error.formatting)); + var result = { + adminpass: { + expected: "string", + got: req.body.hasOwnProperty("adminpass") ? typeof(req.body.adminpass) : undefined, + }, + userpass: { + expected: "string", + got: req.body.hasOwnProperty("userpass") ? typeof(req.body.userpass) : undefined + } + }; + var to_send = error.formatting; + to_send.results.push(result); + res.status(400).send(JSON.stringify(to_send)); return; } @@ -402,23 +477,33 @@ router.route('/api/list/:channel_name/__np__').post(function(req, res) { res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.header({"Content-Type": "application/json"}); + try { + if(!req.body.hasOwnProperty('userpass')) { + throw "Wrong format"; + } - if(!req.body.hasOwnProperty('userpass')) { - res.status(400).send(JSON.stringify(error.formatting)); - return; - } - - var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; - var guid = Functions.hash_pass(req.get('User-Agent') + ip + req.headers["accept-language"]); - var channel_name = req.params.channel_name; - req.body.userpass = req.body.userpass == "" ? "" : crypto.createHash('sha256').update(req.body.userpass, 'utf8').digest("hex"); - var userpass = req.body.userpass; - var token = ""; - if(req.body.hasOwnProperty("token")) { - token = req.body.token; - } - if(typeof(userpass) != "string") { - res.status(400).send(JSON.stringify(error.formatting)); + var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; + var guid = Functions.hash_pass(req.get('User-Agent') + ip + req.headers["accept-language"]); + var channel_name = req.params.channel_name; + req.body.userpass = req.body.userpass == "" ? "" : crypto.createHash('sha256').update(req.body.userpass, 'utf8').digest("hex"); + var userpass = req.body.userpass; + var token = ""; + if(req.body.hasOwnProperty("token")) { + token = req.body.token; + } + if(typeof(userpass) != "string") { + throw "Wrong format"; + } + } catch(e) { + var result = { + userpass: { + expected: "string", + got: req.body.hasOwnProperty("userpass") ? typeof(req.body.userpass) : undefined + } + }; + var to_send = error.formatting; + to_send.results.push(result); + res.status(400).send(JSON.stringify(to_send)); return; } token_db.collection("api_token").find({token: token}, function(err, token_docs) { @@ -474,14 +559,14 @@ router.route('/api/list/:channel_name/:video_id').post(function(req,res) { if(req.body.hasOwnProperty("token")) { token = req.body.token; } - if(!fetch_only && (!req.body.hasOwnProperty('adminpass') || !req.body.hasOwnProperty('userpass') || - !req.params.hasOwnProperty('channel_name') || !req.params.hasOwnProperty('video_id') || - !req.body.hasOwnProperty('duration') || !req.body.hasOwnProperty('start_time') || - !req.body.hasOwnProperty('end_time') || !req.body.hasOwnProperty('title'))) { - res.status(400).send(JSON.stringify(error.formatting)); - return; - } try { + if(!fetch_only && (!req.body.hasOwnProperty('adminpass') || !req.body.hasOwnProperty('userpass') || + !req.params.hasOwnProperty('channel_name') || !req.params.hasOwnProperty('video_id') || + !req.body.hasOwnProperty('duration') || !req.body.hasOwnProperty('start_time') || + !req.body.hasOwnProperty('end_time') || !req.body.hasOwnProperty('title'))) { + throw "Wrong format"; + } + var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; var guid = Functions.hash_pass(req.get('User-Agent') + ip + req.headers["accept-language"]); req.body.userpass = req.body.userpass == "" ? "" : crypto.createHash('sha256').update(req.body.userpass, 'utf8').digest("hex"); @@ -496,12 +581,40 @@ router.route('/api/list/:channel_name/:video_id').post(function(req,res) { if(duration != end_time - start_time) duration = end_time - start_time; var title = req.body.title; if(typeof(userpass) != "string" || typeof(adminpass) != "string" || - typeof(title) != "string") { + typeof(title) != "string" || isNaN(duration) || isNaN(start_time) || isNaN(end_time)) { throw "Wrong format"; } } } catch(e) { - res.status(400).send(JSON.stringify(error.formatting)); + var result = { + adminpass: { + expected: "string", + got: req.body.hasOwnProperty("adminpass") ? typeof(req.body.adminpass) : undefined, + }, + userpass: { + expected: "string", + got: req.body.hasOwnProperty("userpass") ? typeof(req.body.userpass) : undefined + }, + title: { + expected: "string", + got: req.body.hasOwnProperty("title") ? typeof(req.body.title) : undefined + }, + start_time: { + expected: "number or string that can be cast to int", + got: !req.body.hasOwnProperty("start_time") ? undefined : isNaN(req.body.start_time) ? "uncastable string" : typeof(req.body.start_time) + }, + end_time: { + expected: "number or string that can be cast to int", + got: !req.body.hasOwnProperty("end_time") ? undefined : isNaN(req.body.end_time) ? "uncastable string" : typeof(req.body.end_time) + }, + duration: { + expected: "number or string that can be cast to int", + got: !req.body.hasOwnProperty("duration") ? undefined : isNaN(req.body.duration) ? "uncastable string" : typeof(req.body.duration) + } + }; + var to_send = error.formatting; + to_send.results.push(result); + res.status(400).send(JSON.stringify(to_send)); return; } @@ -693,22 +806,33 @@ router.route('/api/conf/:channel_name').post(function(req, res) { res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.header({"Content-Type": "application/json"}); - if(!req.body.hasOwnProperty('userpass')) { - res.status(400).send(JSON.stringify(error.formatting)); - return; - } - var token = ""; - if(req.body.hasOwnProperty("token")) { - token = req.body.token; - } - var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; - var guid = Functions.hash_pass(req.get('User-Agent') + ip + req.headers["accept-language"]); - var channel_name = req.params.channel_name; - req.body.userpass = req.body.userpass == "" ? "" : crypto.createHash('sha256').update(req.body.userpass, 'utf8').digest("hex"); - var userpass = req.body.userpass; + try { + if(!req.body.hasOwnProperty('userpass')) { + throw "Wrong format" + } + var token = ""; + if(req.body.hasOwnProperty("token")) { + token = req.body.token; + } + var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; + var guid = Functions.hash_pass(req.get('User-Agent') + ip + req.headers["accept-language"]); + var channel_name = req.params.channel_name; + req.body.userpass = req.body.userpass == "" ? "" : crypto.createHash('sha256').update(req.body.userpass, 'utf8').digest("hex"); + var userpass = req.body.userpass; - if(typeof(userpass) != "string") { - res.status(400).send(JSON.stringify(error.formatting)); + if(typeof(userpass) != "string") { + throw "Wrong format"; + } + } catch(e) { + var result = { + userpass: { + expected: "string", + got: req.body.hasOwnProperty("userpass") ? typeof(req.body.userpass) : undefined + } + }; + var to_send = error.formatting; + to_send.results.push(result); + res.status(400).send(JSON.stringify(to_send)); return; } @@ -793,23 +917,34 @@ router.route('/api/list/:channel_name').post(function(req, res) { res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); res.header({"Content-Type": "application/json"}); - if(!req.body.hasOwnProperty('userpass')) { - res.status(400).send(JSON.stringify(error.formatting)); - return; - } + try { + if(!req.body.hasOwnProperty('userpass')) { + throw "Wrong format"; + } - var token = ""; - if(req.body.hasOwnProperty("token")) { - token = req.body.token; - } - var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; - var guid = Functions.hash_pass(req.get('User-Agent') + ip + req.headers["accept-language"]); - var channel_name = req.params.channel_name; - req.body.userpass = req.body.userpass == "" ? "" : crypto.createHash('sha256').update(req.body.userpass, 'utf8').digest("hex"); - var userpass = req.body.userpass; + var token = ""; + if(req.body.hasOwnProperty("token")) { + token = req.body.token; + } + var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; + var guid = Functions.hash_pass(req.get('User-Agent') + ip + req.headers["accept-language"]); + var channel_name = req.params.channel_name; + req.body.userpass = req.body.userpass == "" ? "" : crypto.createHash('sha256').update(req.body.userpass, 'utf8').digest("hex"); + var userpass = req.body.userpass; - if(typeof(userpass) != "string") { - res.status(400).send(JSON.stringify(error.formatting)); + if(typeof(userpass) != "string") { + throw "Wrong format"; + } + } catch(e) { + var result = { + userpass: { + expected: "string", + got: req.body.hasOwnProperty("userpass") ? typeof(req.body.userpass) : undefined + } + }; + var to_send = error.formatting; + to_send.results.push(result); + res.status(400).send(JSON.stringify(to_send)); return; }