diff --git a/client/src/main/resources/html/docs/ConfigurationFile.md b/client/src/main/resources/html/docs/ConfigurationFile.md index c691c1cb..d1312750 100644 --- a/client/src/main/resources/html/docs/ConfigurationFile.md +++ b/client/src/main/resources/html/docs/ConfigurationFile.md @@ -57,7 +57,7 @@ the port ctbrec tries to connect to, if it is run in remote mode. - **recordSingleFile** (server only) - [`true`,`false`] - How recordings are stored in the file system. `true` means, each recording is saved in one large file. `false` means, ctbrec just downloads the stream segments. -- **splitRecordings** (app only) - [0 - 2147483647] in seconds. Split recordings after this amount of seconds. The recordings are split up into several individual recordings, +- **splitRecordings** - [0 - 2147483647] in seconds. Split recordings after this amount of seconds. The recordings are split up into several individual recordings, which have the defined length (roughly). 0 means no splitting. The server does not support splitRecordings. - **webinterface** (server only) - [`true`,`false`] Enables the webinterface for the server. You can access it with http://host:port/static/index.html Don't activate this on diff --git a/server/src/main/java/ctbrec/recorder/server/ConfigServlet.java b/server/src/main/java/ctbrec/recorder/server/ConfigServlet.java index 11e368d5..8dcd632b 100644 --- a/server/src/main/java/ctbrec/recorder/server/ConfigServlet.java +++ b/server/src/main/java/ctbrec/recorder/server/ConfigServlet.java @@ -3,6 +3,8 @@ package ctbrec.recorder.server; import static javax.servlet.http.HttpServletResponse.*; import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -36,26 +38,45 @@ public class ConfigServlet extends AbstractCtbrecServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - // try { - // boolean authenticated = checkAuthentication(req, body(req)); - // if (!authenticated) { - // resp.setStatus(SC_UNAUTHORIZED); - // String response = "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}"; - // resp.getWriter().write(response); - // return; - // } - // } catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) { - // throw new ServletException(e); - // } + try { + boolean authenticated = checkAuthentication(req, body(req)); + if (!authenticated) { + resp.setStatus(SC_UNAUTHORIZED); + String response = "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}"; + resp.getWriter().write(response); + return; + } - resp.setStatus(SC_OK); - resp.setContentType("application/json"); + JSONArray json = new JSONArray(); + addParameter("concurrentRecordings", "Concurrent Recordings", DataType.INTEGER, settings.concurrentRecordings, json); + addParameter("ffmpegFileSuffix", "File Suffix", DataType.STRING, settings.ffmpegFileSuffix, json); + addParameter("ffmpegMergedDownloadArgs", "FFmpeg Parameters", DataType.STRING, settings.ffmpegMergedDownloadArgs, json); + addParameter("httpPort", "HTTP port", DataType.INTEGER, settings.httpPort, json); + addParameter("httpsPort", "HTTPS port", DataType.INTEGER, settings.httpSecurePort, json); + addParameter("httpUserAgent", "User-Agent", DataType.STRING, settings.httpUserAgent, json); + addParameter("httpUserAgentMobile", "Mobile User-Agent", DataType.STRING, settings.httpUserAgentMobile, json); + addParameter("generatePlaylist", "Generate Playlist", DataType.BOOLEAN, settings.generatePlaylist, json); + addParameter("maximumResolution", "Maximum Resolution", DataType.INTEGER, settings.maximumResolution, json); + addParameter("minimumLengthInSeconds", "Minimum Length (secs)", DataType.INTEGER, settings.minimumLengthInSeconds, json); + addParameter("minimumSpaceLeftInBytes", "Leave Space On Device (GiB)", DataType.INTEGER, settings.minimumSpaceLeftInBytes, json); + addParameter("onlineCheckIntervalInSecs", "Online Check Interval (secs)", DataType.INTEGER, settings.onlineCheckIntervalInSecs, json); + addParameter("postProcessing", "Post-Processing", DataType.STRING, settings.postProcessing, json); + addParameter("postProcessingThreads", "Post-Processing Threads", DataType.INTEGER, settings.postProcessingThreads, json); + addParameter("recordingsDir", "Recordings Directory", DataType.STRING, settings.recordingsDir, json); + addParameter("recordSingleFile", "Record Single File", DataType.BOOLEAN, settings.recordSingleFile, json); + addParameter("splitRecordings", "Split Recordings (secs)", DataType.INTEGER, settings.splitRecordings, json); + addParameter("transportLayerSecurity", "Transport Layer Security (TLS)", DataType.BOOLEAN, settings.transportLayerSecurity, json); + addParameter("webinterface", "Web-Interface", DataType.BOOLEAN, settings.webinterface, json); + addParameter("webinterfaceUsername", "Web-Interface User", DataType.STRING, settings.webinterfaceUsername, json); + addParameter("webinterfacePassword", "Web-Interface Password", DataType.STRING, settings.webinterfacePassword, json); - JSONArray json = new JSONArray(); - addParameter("httpPort", "HTTP port", DataType.INTEGER, settings.httpPort, json); - - resp.getWriter().print(json.toString(2)); - LOG.debug("GET {} {}", req.getRequestURI(), req.getRequestURL()); + resp.setStatus(SC_OK); + resp.setContentType("application/json"); + resp.getWriter().print(json.toString()); + } catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) { + resp.setStatus(SC_INTERNAL_SERVER_ERROR); + LOG.error("Error during authentication", e); + } } private void addParameter(String key, String name, DataType type, Object value, JSONArray json) { @@ -69,8 +90,24 @@ public class ConfigServlet extends AbstractCtbrecServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - resp.setStatus(SC_OK); - resp.setContentType("application/json"); - LOG.debug("POST"); + try { + boolean authenticated = checkAuthentication(req, body(req)); + if (!authenticated) { + resp.setStatus(SC_UNAUTHORIZED); + String response = "{\"status\": \"error\", \"msg\": \"HMAC does not match\"}"; + resp.getWriter().write(response); + return; + } + + String postBody = body(req); + LOG.info("POST {}", postBody); + //JSONObject json = new JSONObject(postBody); + resp.setStatus(SC_OK); + resp.setContentType("application/json"); + resp.getWriter().print("{\"status\": \"success\"}"); + } catch (InvalidKeyException | NoSuchAlgorithmException | IllegalStateException e) { + resp.setStatus(SC_INTERNAL_SERVER_ERROR); + } + } } diff --git a/server/src/main/java/ctbrec/recorder/server/RecorderServlet.java b/server/src/main/java/ctbrec/recorder/server/RecorderServlet.java index 044424fd..3efb2f46 100644 --- a/server/src/main/java/ctbrec/recorder/server/RecorderServlet.java +++ b/server/src/main/java/ctbrec/recorder/server/RecorderServlet.java @@ -211,14 +211,16 @@ public class RecorderServlet extends AbstractCtbrecServlet { } } - private void startByUrl(Request request) throws InvalidKeyException, NoSuchAlgorithmException, IllegalStateException, IOException { + private void startByUrl(Request request) throws InvalidKeyException, NoSuchAlgorithmException, IOException { String url = request.model.getUrl(); for (Site site : sites) { Model model = site.createModelFromUrl(url); if (model != null) { recorder.startRecording(model); + return; } } + throw new IllegalArgumentException("No site found to record " + url); } private static class Request { diff --git a/server/src/main/resources/html/static/config.js b/server/src/main/resources/html/static/config.js new file mode 100644 index 00000000..19e55ed8 --- /dev/null +++ b/server/src/main/resources/html/static/config.js @@ -0,0 +1,65 @@ +function loadConfig() { + try { + $.ajax({ + type : 'GET', + url : '../config', + dataType : 'json', + async : true, + timeout : 60000, + headers : { + 'CTBREC-HMAC' : CryptoJS.HmacSHA256('', hmac) + } + }).done(function(data, textStatus, jqXHR) { + if (textStatus === 'success') { + for (let i = 0; i < data.length; i++) { + let param = data[i]; + param.ko_value = ko.observable(param.value); + param.ko_value.subscribe(function(newValue) { + console.log("The person's new name is " + newValue); + }); + observableSettingsArray.push(param); + } + } else { + if (console) + console.log('request failed', data); + } + }).fail(function(jqXHR, textStatus, errorThrown) { + if (console) + console.log(jqXHR, textStatus, errorThrown); + }); + } catch (e) { + if (console) + console.log('Unexpected error', e); + } +} + +function saveConfig() { + try { + let msg = JSON.stringify(observableSettingsArray()); + console.log(msg); + $.ajax({ + type : 'POST', + url : '../config', + dataType : 'json', + async : true, + timeout : 60000, + headers : { + 'CTBREC-HMAC' : CryptoJS.HmacSHA256(msg, hmac) + }, + data : msg + }).done(function(data, textStatus, jqXHR) { + if (textStatus === 'success') { + //$.notify('Configuration saved', 'info'); + } else { + if (console) + console.log('request failed', data); + } + }).fail(function(jqXHR, textStatus, errorThrown) { + if (console) + console.log(jqXHR, textStatus, errorThrown); + }); + } catch (e) { + if (console) + console.log('Unexpected error', e); + } +} \ No newline at end of file diff --git a/server/src/main/resources/html/static/index.html b/server/src/main/resources/html/static/index.html index 0627acc8..957582de 100644 --- a/server/src/main/resources/html/static/index.html +++ b/server/src/main/resources/html/static/index.html @@ -66,9 +66,9 @@