From 54db86b09a34d0571f7756ed433a90ae666246a5 Mon Sep 17 00:00:00 2001 From: MrDave Date: Wed, 10 Mar 2021 22:18:34 -0700 Subject: [PATCH] Revise the webcontrol --- src/Makefile.am | 3 +- src/conf.cpp | 168 +- src/conf.hpp | 10 +- src/motion_loop.cpp | 8 +- src/motionplus.cpp | 104 +- src/motionplus.hpp | 11 +- src/netcam.cpp | 75 +- src/webu.cpp | 2223 ++++---------------------- src/webu.hpp | 102 +- src/webu_html.cpp | 1758 +++++++------------- src/webu_html.hpp | 3 +- src/webu_json.cpp | 297 ++++ src/{webu_text.hpp => webu_json.hpp} | 11 +- src/webu_post.cpp | 405 +++++ src/webu_post.hpp | 25 + src/webu_stream.cpp | 204 ++- src/webu_stream.hpp | 3 +- src/webu_text.cpp | 1235 -------------- 18 files changed, 1964 insertions(+), 4681 deletions(-) create mode 100644 src/webu_json.cpp rename src/{webu_text.hpp => webu_json.hpp} (67%) create mode 100644 src/webu_post.cpp create mode 100644 src/webu_post.hpp delete mode 100644 src/webu_text.cpp diff --git a/src/Makefile.am b/src/Makefile.am index ae5f9c96..ccd852e9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,5 +11,6 @@ bin_PROGRAMS = motionplus motionplus_SOURCES = motionplus.cpp motion_loop.cpp logger.cpp conf.cpp util.cpp alg.cpp alg_sec.cpp\ video_v4l2.cpp video_common.cpp video_loopback.cpp netcam.cpp jpegutils.cpp exif.cpp \ rotate.cpp draw.cpp event.cpp movie.cpp picture.cpp dbse.cpp track.cpp \ - webu.cpp webu_html.cpp webu_stream.cpp webu_text.cpp mmalcam.cpp $(MMAL_SRC) + webu.cpp webu_html.cpp webu_stream.cpp webu_json.cpp webu_post.cpp \ + mmalcam.cpp $(MMAL_SRC) diff --git a/src/conf.cpp b/src/conf.cpp index 09b0f43b..59070bae 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -530,34 +530,10 @@ struct ctx_parm config_parms[] = { 1, PARM_TYP_STRING, PARM_CAT_13, WEBUI_LEVEL_RESTRICTED}, { - "stream_port", + "stream_preview_scale", "############################################################\n" "# Live stream configuration parameters\n" "############################################################\n\n" - "# The port number for the live stream.", - 0, PARM_TYP_INT, PARM_CAT_14, WEBUI_LEVEL_ADVANCED }, - { - "stream_localhost", - "# Restrict stream connections to the localhost.", - 0, PARM_TYP_BOOL, PARM_CAT_14, WEBUI_LEVEL_ADVANCED }, - { - "stream_auth_method", - "# Authentication method for live stream.", - 0, PARM_TYP_INT, PARM_CAT_14, WEBUI_LEVEL_RESTRICTED}, - { - "stream_authentication", - "# The authentication string for the stream. Syntax username:password", - 1, PARM_TYP_STRING, PARM_CAT_14, WEBUI_LEVEL_RESTRICTED }, - { - "stream_tls", - "# Use ssl / tls for stream.", - 0, PARM_TYP_BOOL, PARM_CAT_14, WEBUI_LEVEL_RESTRICTED }, - { - "stream_cors_header", - "# The cross-origin resource sharing (CORS) header for the stream", - 0, PARM_TYP_STRING, PARM_CAT_14, WEBUI_LEVEL_RESTRICTED }, - { - "stream_preview_scale", "# Percentage to scale the stream image on the webcontrol.", 0, PARM_TYP_INT, PARM_CAT_14, WEBUI_LEVEL_LIMITED }, { @@ -2705,110 +2681,6 @@ static void conf_edit_webcontrol_html(struct ctx_cam *cam, std::string &parm, en MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","webcontrol_html",_("webcontrol_html")); } -static void conf_edit_stream_port(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) -{ - int parm_in; - if (pact == PARM_ACT_DFLT){ - cam->conf->stream_port = 0; - } else if (pact == PARM_ACT_SET){ - parm_in = atoi(parm.c_str()); - if ((parm_in < 0) || (parm_in > 65535)) { - MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Invalid stream_port %d"),parm_in); - } else { - cam->conf->stream_port = parm_in; - } - } else if (pact == PARM_ACT_GET){ - parm = std::to_string(cam->conf->stream_port); - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","stream_port",_("stream_port")); -} - -static void conf_edit_stream_localhost(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) -{ - if (pact == PARM_ACT_DFLT){ - cam->conf->stream_localhost = TRUE; - } else if (pact == PARM_ACT_SET){ - conf_edit_set_bool(cam->conf->stream_localhost, parm); - } else if (pact == PARM_ACT_GET){ - conf_edit_get_bool(parm, cam->conf->stream_localhost); - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","stream_localhost",_("stream_localhost")); -} - -static void conf_edit_stream_auth_method(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) -{ - int parm_in; - if (pact == PARM_ACT_DFLT){ - cam->conf->stream_auth_method = 0; - } else if (pact == PARM_ACT_SET){ - parm_in = atoi(parm.c_str()); - if ((parm_in < 0) || (parm_in > 2)) { - MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Invalid stream_auth_method %d"),parm_in); - } else { - cam->conf->stream_auth_method = parm_in; - } - } else if (pact == PARM_ACT_GET){ - parm = std::to_string(cam->conf->stream_auth_method); - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","stream_auth_method",_("stream_auth_method")); -} - -static void conf_edit_stream_authentication(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) -{ - if (pact == PARM_ACT_DFLT) { - cam->conf->stream_authentication = ""; - } else if (pact == PARM_ACT_SET){ - cam->conf->stream_authentication = parm; - } else if (pact == PARM_ACT_GET){ - parm = cam->conf->stream_authentication; - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","stream_authentication",_("stream_authentication")); -} - -static void conf_edit_stream_tls(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) -{ - if (pact == PARM_ACT_DFLT){ - cam->conf->stream_tls = FALSE; - } else if (pact == PARM_ACT_SET){ - conf_edit_set_bool(cam->conf->stream_tls, parm); - } else if (pact == PARM_ACT_GET){ - conf_edit_get_bool(parm, cam->conf->stream_tls); - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","stream_tls",_("stream_tls")); -} - -static void conf_edit_stream_cors_header(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) -{ - int retcd; - if (pact == PARM_ACT_DFLT) { - cam->conf->stream_cors_header = ""; - } else if (pact == PARM_ACT_SET){ - const char *regex_str = "(http|https)://(((.*):(.*))@)?([^/:]|[-_.a-z0-9]+)(:([0-9]+))?($|(/[^*]*))"; - regex_t regex; - if (regcomp(®ex, regex_str, REG_EXTENDED) != 0) { - MOTION_LOG(ERR, TYPE_STREAM, NO_ERRNO,_("Error compiling regex in copy_uri")); - return; - } - /* We only warn on this since regex may not perfectly edit uris */ - retcd = regexec(®ex, parm.c_str(), 0, NULL, 0); - if ((parm != "*") && (parm != "") && (retcd == REG_NOMATCH)) { - MOTION_LOG(ERR, TYPE_STREAM, NO_ERRNO,_("Possibly invalid stream_cors_header")); - } - - cam->conf->stream_cors_header = parm; - regfree(®ex); - } else if (pact == PARM_ACT_GET){ - parm = cam->conf->stream_cors_header; - } - return; - MOTION_LOG(DBG, TYPE_ALL, NO_ERRNO,"%s:%s","stream_cors_header",_("stream_cors_header")); -} - static void conf_edit_stream_preview_scale(struct ctx_cam *cam, std::string &parm, enum PARM_ACT pact) { int parm_in; @@ -3439,13 +3311,7 @@ static void conf_edit_cat13(struct ctx_cam *cam, std::string parm_nm static void conf_edit_cat14(struct ctx_cam *cam, std::string parm_nm , std::string &parm_val, enum PARM_ACT pact) { - if (parm_nm == "stream_port"){ conf_edit_stream_port(cam, parm_val, pact); - } else if (parm_nm == "stream_localhost"){ conf_edit_stream_localhost(cam, parm_val, pact); - } else if (parm_nm == "stream_auth_method"){ conf_edit_stream_auth_method(cam, parm_val, pact); - } else if (parm_nm == "stream_authentication"){ conf_edit_stream_authentication(cam, parm_val, pact); - } else if (parm_nm == "stream_tls"){ conf_edit_stream_tls(cam, parm_val, pact); - } else if (parm_nm == "stream_cors_header"){ conf_edit_stream_cors_header(cam, parm_val, pact); - } else if (parm_nm == "stream_preview_scale"){ conf_edit_stream_preview_scale(cam, parm_val, pact); + if (parm_nm == "stream_preview_scale"){ conf_edit_stream_preview_scale(cam, parm_val, pact); } else if (parm_nm == "stream_preview_newline"){ conf_edit_stream_preview_newline(cam, parm_val, pact); } else if (parm_nm == "stream_preview_method"){ conf_edit_stream_preview_method(cam, parm_val, pact); } else if (parm_nm == "stream_quality"){ conf_edit_stream_quality(cam, parm_val, pact); @@ -4122,8 +3988,6 @@ void conf_parms_log(struct ctx_cam **cam_list) if ((config_parms[i].parm_name == "netcam_url") || (config_parms[i].parm_name == "netcam_userpass") || (config_parms[i].parm_name == "netcam_high_url") || - (config_parms[i].parm_name == "stream_cors_header") || - (config_parms[i].parm_name == "stream_authentication") || (config_parms[i].parm_name == "webcontrol_authentication") || (config_parms[i].parm_name == "webcontrol_cors_header") || (config_parms[i].parm_name == "webcontrol_key") || @@ -4151,20 +4015,20 @@ void conf_parms_log(struct ctx_cam **cam_list) } /** Write the configuration(s) to file */ -void conf_parms_write(struct ctx_cam **cam_list) +void conf_parms_write(struct ctx_motapp *motapp) { std::string parm_val, parm_main; int indx, indx2, indx_cam; char timestamp[32]; FILE *conffile; - for (indx_cam = 0; cam_list[indx_cam]; indx_cam++) { + for (indx_cam = 0; motapp->cam_list[indx_cam]; indx_cam++) { /* MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO ,_("Writing config file to %s") ,cam_list[indx_cam]->conf_filename); */ - conffile = myfopen(cam_list[indx_cam]->conf_filename, "w"); + conffile = myfopen(motapp->cam_list[indx_cam]->conf_filename, "w"); if (!conffile) { continue; @@ -4173,16 +4037,16 @@ void conf_parms_write(struct ctx_cam **cam_list) time_t now = time(0); strftime(timestamp, 32, "%Y-%m-%dT%H:%M:%S", localtime(&now)); - fprintf(conffile, "# %s\n", cam_list[indx_cam]->conf_filename); + fprintf(conffile, "# %s\n", motapp->cam_list[indx_cam]->conf_filename); fprintf(conffile, "#\n# This config file was generated by MotionPlus " VERSION "\n"); fprintf(conffile, "# at %s\n", timestamp); fprintf(conffile, "\n\n"); indx = 0; while (config_parms[indx].parm_name != ""){ - conf_edit_get(cam_list[indx_cam], config_parms[indx].parm_name + conf_edit_get(motapp->cam_list[indx_cam], config_parms[indx].parm_name , parm_val, config_parms[indx].parm_cat); - conf_edit_get(cam_list[0], config_parms[indx].parm_name + conf_edit_get(motapp->cam_list[0], config_parms[indx].parm_name , parm_main, config_parms[indx].parm_cat); if ((config_parms[indx].parm_name != "camera") && @@ -4201,15 +4065,17 @@ void conf_parms_write(struct ctx_cam **cam_list) } if ((config_parms[indx].parm_name == "camera") && (indx_cam == 0)) { fprintf(conffile, "%s\n", config_parms[indx].parm_help.c_str()); - if (cam_list[0]->from_conf_dir == FALSE) { + if (motapp->cam_list[0]->from_conf_dir == FALSE) { indx2 = 1; - while (cam_list[indx2] != NULL) { + while (motapp->cam_list[indx2] != NULL) { if (parm_val.compare(0, 1, " ") == 0) { fprintf(conffile, "%s \"%s\"\n\n" - , config_parms[indx].parm_name.c_str(), cam_list[indx2]->conf_filename); + , config_parms[indx].parm_name.c_str() + , motapp->cam_list[indx2]->conf_filename); } else { fprintf(conffile, "%s %s\n\n" - , config_parms[indx].parm_name.c_str(), cam_list[indx2]->conf_filename); + , config_parms[indx].parm_name.c_str() + , motapp->cam_list[indx2]->conf_filename); } indx2++; } @@ -4218,7 +4084,7 @@ void conf_parms_write(struct ctx_cam **cam_list) if ((config_parms[indx].parm_name == "camera_dir") && (indx_cam == 0)) { fprintf(conffile, "%s\n", config_parms[indx].parm_help.c_str()); if (parm_val == "") { - parm_val = cam_list[0]->conf_filename; + parm_val = motapp->cam_list[0]->conf_filename; parm_val = parm_val.substr(0, parm_val.find_last_of("/")+1) + "conf.d"; } if (parm_val.compare(0, 1, " ") == 0) { @@ -4237,8 +4103,8 @@ void conf_parms_write(struct ctx_cam **cam_list) conffile = NULL; MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO - ,_("Configuration written to %s") - ,cam_list[indx_cam]->conf_filename); + , _("Configuration written to %s") + , motapp->cam_list[indx_cam]->conf_filename); } } diff --git a/src/conf.hpp b/src/conf.hpp index 3f94f480..3aa99908 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -153,12 +153,6 @@ std::string webcontrol_html; /* Live stream configuration parameters */ - int stream_port; - int stream_localhost; - int stream_auth_method; - std::string stream_authentication; - int stream_tls; - std::string stream_cors_header; int stream_preview_scale; int stream_preview_newline; int stream_preview_method; @@ -227,7 +221,7 @@ const std::string parm_help; /* short explanation for parameter */ int main_thread; /* belong only to main thread when value>0 */ enum PARM_TYP parm_type; /* enum of parm_typ for bool,int or string. */ - enum PARM_CAT parm_cat; /* enum of parm_cat for 00 to 05 for grouping. */ + enum PARM_CAT parm_cat; /* enum of parm_cat for grouping. */ int webui_level; /* Enum to display in webui: 0,1,2,3,99(always to never)*/ }; @@ -246,7 +240,7 @@ void conf_init_cams(struct ctx_motapp *motapp); void conf_deinit(struct ctx_motapp *motapp); void conf_parms_log(struct ctx_cam **cam_list); - void conf_parms_write(struct ctx_cam **cam_list); + void conf_parms_write(struct ctx_motapp *motapp); void conf_camera_add(struct ctx_motapp *motapp); void conf_edit_set(struct ctx_motapp *motapp, bool ismotapp, int threadnbr diff --git a/src/motion_loop.cpp b/src/motion_loop.cpp index fc76a66c..97ef7983 100644 --- a/src/motion_loop.cpp +++ b/src/motion_loop.cpp @@ -330,7 +330,7 @@ void mlp_cam_close(struct ctx_cam *cam) if (cam->netcam) { /* This also cleans up high resolution */ MOTION_LOG(INF, TYPE_VIDEO, NO_ERRNO,_("calling netcam_cleanup")); - netcam_cleanup(cam, 0); + netcam_cleanup(cam, false); return; } @@ -371,7 +371,7 @@ int mlp_cam_start(struct ctx_cam *cam) MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Opening Netcam")); dev = netcam_setup(cam); if (dev < 0) { - netcam_cleanup(cam, 1); + netcam_cleanup(cam, true); MOTION_LOG(ERR, TYPE_VIDEO, NO_ERRNO,_("Netcam failed to open")); } return dev; @@ -555,7 +555,8 @@ static void mlp_init_buffers(struct ctx_cam *cam) static void mlp_init_values(struct ctx_cam *cam) { - cam->event_nr=1; + cam->event_nr = 1; + cam->prev_event = 0; clock_gettime(CLOCK_REALTIME, &cam->frame_curr_ts); clock_gettime(CLOCK_REALTIME, &cam->frame_last_ts); @@ -634,6 +635,7 @@ static void mlp_init_ref(struct ctx_cam *cam) /** mlp_init */ static int mlp_init(struct ctx_cam *cam) { + MOTION_LOG(WRN, TYPE_ALL, NO_ERRNO,_("initialize.")); mythreadname_set("ml",cam->threadnr,cam->conf->camera_name.c_str()); diff --git a/src/motionplus.cpp b/src/motionplus.cpp index 46042ba3..908e83b6 100644 --- a/src/motionplus.cpp +++ b/src/motionplus.cpp @@ -43,7 +43,7 @@ static void motion_signal_process(struct ctx_motapp *motapp) indx = 0; while (motapp->cam_list[indx] != NULL) { if (motapp->cam_list[indx]->conf->snapshot_interval){ - motapp->cam_list[indx]->snapshot = TRUE; + motapp->cam_list[indx]->snapshot = true; } indx++; } @@ -53,26 +53,26 @@ static void motion_signal_process(struct ctx_motapp *motapp) if (motapp->cam_list != NULL) { indx = 0; while (motapp->cam_list[indx] != NULL){ - motapp->cam_list[indx]->event_stop = TRUE; + motapp->cam_list[indx]->event_stop = true; indx++; } } break; case MOTION_SIGNAL_SIGHUP: /* Restart the threads */ - motapp->restart_all = TRUE; + motapp->restart_all = true; /*FALLTHROUGH*/ case MOTION_SIGNAL_SIGTERM: /* Quit application */ if (motapp->cam_list != NULL) { indx = 0; while (motapp->cam_list[indx]) { - motapp->webcontrol_finish = TRUE; - motapp->cam_list[indx]->event_stop = TRUE; - motapp->cam_list[indx]->finish_cam = TRUE; - motapp->cam_list[indx]->restart_cam = FALSE; + motapp->webcontrol_finish = true; + motapp->cam_list[indx]->event_stop = true; + motapp->cam_list[indx]->finish_cam = true; + motapp->cam_list[indx]->restart_cam = false; indx++; } } - motapp->finish_all = TRUE; + motapp->finish_all = true; default: break; } @@ -166,7 +166,7 @@ static void motion_remove_pid(struct ctx_motapp *motapp) if ((motapp->daemon) && (motapp->pid_file != "") && - (motapp->restart_all == FALSE)) { + (motapp->restart_all == false)) { if (!unlink(motapp->pid_file.c_str())){ MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Removed process id file (pid file).")); } else{ @@ -266,7 +266,6 @@ static void motion_daemon(struct ctx_motapp *motapp) static void motion_shutdown(struct ctx_motapp *motapp) { - motion_remove_pid(motapp); log_deinit(motapp); @@ -296,13 +295,13 @@ static void motion_camera_ids(struct ctx_cam **cam_list) indx++; } - invalid_ids = FALSE; + invalid_ids = false; indx = 0; while (cam_list[indx] != NULL){ - if (cam_list[indx]->camera_id > 32000) invalid_ids = TRUE; + if (cam_list[indx]->camera_id > 32000) invalid_ids = true; indx2 = indx + 1; while (cam_list[indx2] != NULL){ - if (cam_list[indx]->camera_id == cam_list[indx2]->camera_id) invalid_ids = TRUE; + if (cam_list[indx]->camera_id == cam_list[indx2]->camera_id) invalid_ids = true; indx2++; } indx++; @@ -427,7 +426,7 @@ static void motion_start_thread(struct ctx_motapp *motapp, int indx) if (pthread_create(&motapp->cam_list[indx]->thread_id , &thread_attr, &motion_loop, motapp->cam_list[indx])) { /* thread create failed, undo running state */ - motapp->cam_list[indx]->running_cam = FALSE; + motapp->cam_list[indx]->running_cam = false; pthread_mutex_lock(&motapp->global_lock); motapp->threads_running--; pthread_mutex_unlock(&motapp->global_lock); @@ -445,10 +444,10 @@ static void motion_restart(struct ctx_motapp *motapp, int argc, char **argv) SLEEP(2, 0); - motion_startup(motapp, FALSE, argc, argv); + motion_startup(motapp, false, argc, argv); MOTION_LOG(WRN, TYPE_ALL, NO_ERRNO,_("Motion restarted")); - motapp->restart_all = FALSE; + motapp->restart_all = false; } @@ -477,8 +476,8 @@ static void motion_watchdog(struct ctx_motapp *motapp, int indx) MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO ,_("Thread %d - Watchdog timeout. Trying to do a graceful restart") , motapp->cam_list[indx]->threadnr); - motapp->cam_list[indx]->event_stop = TRUE; /* Trigger end of event */ - motapp->cam_list[indx]->finish_cam = TRUE; + motapp->cam_list[indx]->event_stop = true; /* Trigger end of event */ + motapp->cam_list[indx]->finish_cam = true; } if (motapp->cam_list[indx]->watchdog == (0 - motapp->cam_list[indx]->conf->watchdog_kill) ) { @@ -505,11 +504,11 @@ static void motion_watchdog(struct ctx_motapp *motapp, int indx) (motapp->cam_list[indx]->netcam != NULL)){ if (!motapp->cam_list[indx]->netcam->handler_finished && pthread_kill(motapp->cam_list[indx]->netcam->thread_id, 0) == ESRCH) { - motapp->cam_list[indx]->netcam->handler_finished = TRUE; + motapp->cam_list[indx]->netcam->handler_finished = true; pthread_mutex_lock(&motapp->global_lock); motapp->threads_running--; pthread_mutex_unlock(&motapp->global_lock); - netcam_cleanup(motapp->cam_list[indx],FALSE); + netcam_cleanup(motapp->cam_list[indx],false); } else { pthread_kill(motapp->cam_list[indx]->netcam->thread_id, SIGVTALRM); } @@ -518,11 +517,11 @@ static void motion_watchdog(struct ctx_motapp *motapp, int indx) (motapp->cam_list[indx]->netcam_high != NULL)){ if (!motapp->cam_list[indx]->netcam_high->handler_finished && pthread_kill(motapp->cam_list[indx]->netcam_high->thread_id, 0) == ESRCH) { - motapp->cam_list[indx]->netcam_high->handler_finished = TRUE; + motapp->cam_list[indx]->netcam_high->handler_finished = true; pthread_mutex_lock(&motapp->global_lock); motapp->threads_running--; pthread_mutex_unlock(&motapp->global_lock); - netcam_cleanup(motapp->cam_list[indx], FALSE); + netcam_cleanup(motapp->cam_list[indx], false); } else { pthread_kill(motapp->cam_list[indx]->netcam_high->thread_id, SIGVTALRM); } @@ -536,8 +535,8 @@ static void motion_watchdog(struct ctx_motapp *motapp, int indx) motapp->threads_running--; pthread_mutex_unlock(&motapp->global_lock); mlp_cleanup(motapp->cam_list[indx]); - motapp->cam_list[indx]->running_cam = FALSE; - motapp->cam_list[indx]->finish_cam = FALSE; + motapp->cam_list[indx]->running_cam = false; + motapp->cam_list[indx]->finish_cam = false; } else { pthread_kill(motapp->cam_list[indx]->thread_id,SIGVTALRM); } @@ -565,21 +564,9 @@ static int motion_check_threadcount(struct ctx_motapp *motapp) } } - /* If the web control/streams are in finish/shutdown, we - * do not want to count them. They will be completely closed - * by the process outside of loop that is checking the counts - * of threads. If the webcontrol is not in a finish / shutdown - * then we want to keep them in the tread count to allow user - * to restart the cameras and keep Motion running. - */ - indx = 0; - while (motapp->cam_list[indx] != NULL){ - if ((motapp->webcontrol_finish == FALSE) && - ((motapp->webcontrol_daemon != NULL) || - (motapp->cam_list[indx]->stream.daemon != NULL))) { - thrdcnt++; - } - indx++; + if ((motapp->webcontrol_finish == false) && + (motapp->webcontrol_daemon != NULL)) { + thrdcnt++; } if (((thrdcnt == 0) && motapp->finish_all) || @@ -603,30 +590,30 @@ static void motion_init(struct ctx_motapp *motapp) pthread_mutex_init(&motapp->mutex_camlst, NULL); motapp->threads_running = 0; - motapp->finish_all = FALSE; - motapp->restart_all = FALSE; + motapp->finish_all = false; + motapp->restart_all = false; motapp->argc = 0; motapp->argv = NULL; - motapp->daemon = FALSE; + motapp->daemon = false; motapp->conf_filename=""; motapp->pid_file=""; motapp->log_file=""; motapp->log_type_str=""; motapp->log_level=0; motapp->log_type=0; - motapp->setup_mode = FALSE; - motapp->pause = FALSE; - motapp->native_language = FALSE; + motapp->setup_mode = false; + motapp->pause = false; + motapp->native_language = false; - motapp->cam_add = FALSE; + motapp->cam_add = false; motapp->cam_delete = 0; - motapp->webcontrol_running = FALSE; - motapp->webcontrol_finish = FALSE; + motapp->webcontrol_running = false; + motapp->webcontrol_finish = false; motapp->webcontrol_daemon = NULL; - memset(motapp->webcontrol_digest_rand,0,8); + memset(motapp->webcontrol_digest_rand, 0, sizeof(motapp->webcontrol_digest_rand)); pthread_key_create(&tls_key_threadnr, NULL); pthread_setspecific(tls_key_threadnr, (void *)(0)); @@ -638,7 +625,7 @@ static void motion_cam_add(struct ctx_motapp *motapp) { int indx_cam, indx; - if (motapp->cam_add == FALSE) { + if (motapp->cam_add == false) { return; } @@ -660,9 +647,8 @@ static void motion_cam_add(struct ctx_motapp *motapp) motapp->cam_list[indx_cam]->camera_id = indx; motapp->cam_list[indx_cam]->dbse = (struct ctx_dbse *)mymalloc(sizeof(struct ctx_dbse)); motapp->cam_list[indx_cam]->conf->webcontrol_port = 0; - motapp->cam_list[indx_cam]->conf->stream_port = 0; - motapp->cam_add = FALSE; + motapp->cam_add = false; } @@ -687,12 +673,6 @@ static void motion_cam_delete(struct ctx_motapp *motapp) return; } - /* Stop stream if needed */ - if (motapp->cam_list[motapp->cam_delete]->stream.daemon != NULL) { - MHD_stop_daemon (motapp->cam_list[motapp->cam_delete]->stream.daemon); - } - motapp->cam_list[motapp->cam_delete]->stream.daemon = NULL; - /* Free database context */ if (motapp->cam_list[motapp->cam_delete]->dbse != NULL) { free(motapp->cam_list[motapp->cam_delete]->dbse); @@ -742,11 +722,11 @@ int main (int argc, char **argv) setup_signals(); - motion_startup(motapp, TRUE, argc, argv); + motion_startup(motapp, true, argc, argv); movie_global_init(); - while (TRUE) { + while (true) { if (motapp->restart_all) { motion_restart(motapp, argc, argv); @@ -760,7 +740,7 @@ int main (int argc, char **argv) MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO ,_("Waiting for threads to finish, pid: %d"), getpid()); - while (TRUE) { + while (true) { SLEEP(1, 0); if (motion_check_threadcount(motapp)) { @@ -791,7 +771,7 @@ int main (int argc, char **argv) /* If there are no cameras running, this allows for adding */ motion_cam_add(motapp); - motapp->finish_all = FALSE; + motapp->finish_all = false; MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, _("Threads finished")); diff --git a/src/motionplus.hpp b/src/motionplus.hpp index 1d298f33..c79f9e78 100644 --- a/src/motionplus.hpp +++ b/src/motionplus.hpp @@ -264,10 +264,6 @@ struct ctx_stream_data { struct ctx_stream { pthread_mutex_t mutex; - struct MHD_Daemon *daemon; - char digest_rand[8]; - int finish; - struct ctx_stream_data norm; /* Copy of the image to use for web stream*/ struct ctx_stream_data sub; /* Copy of the image to use for web stream*/ struct ctx_stream_data motion; /* Copy of the image to use for web stream*/ @@ -413,12 +409,7 @@ struct ctx_motapp { volatile int webcontrol_running; volatile int webcontrol_finish; struct MHD_Daemon *webcontrol_daemon; - char webcontrol_digest_rand[8]; - - volatile int webstream_running; - volatile int webstream_finish; - struct MHD_Daemon *webstream_daemon; /*Picture stream when using single port */ - char webstream_digest_rand[8]; /*Digest for the stream when using single port*/ + char webcontrol_digest_rand[12]; int parms_changed; /*bool indicating if the parms have changed */ pthread_mutex_t mutex_parms; /* mutex used to lock when changing parms */ diff --git a/src/netcam.cpp b/src/netcam.cpp index e1095c60..8115c8c8 100644 --- a/src/netcam.cpp +++ b/src/netcam.cpp @@ -308,6 +308,7 @@ static void netcam_null_context(struct ctx_netcam *netcam) netcam->format_context = NULL; netcam->transfer_format = NULL; netcam->hw_device_ctx = NULL; + netcam->pktarray = NULL; } @@ -380,8 +381,8 @@ static void netcam_pktarray_resize(struct ctx_cam *cam, int is_highres) tmp[indx].packet.data=NULL; tmp[indx].packet.size=0; tmp[indx].idnbr = 0; - tmp[indx].iskey = FALSE; - tmp[indx].iswritten = FALSE; + tmp[indx].iskey = false; + tmp[indx].iswritten = false; } if (netcam->pktarray != NULL) free(netcam->pktarray); @@ -429,18 +430,18 @@ static void netcam_pktarray_add(struct ctx_netcam *netcam) MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO ,_("%s: av_copy_packet: %s ,Interrupt: %s") ,netcam->cameratype - ,errstr, netcam->interrupted ? _("True"):_("False")); + ,errstr, netcam->interrupted ? _("true"):_("false")); mypacket_unref(netcam->pktarray[indx_next].packet); netcam->pktarray[indx_next].packet.data = NULL; netcam->pktarray[indx_next].packet.size = 0; } if (netcam->pktarray[indx_next].packet.flags & AV_PKT_FLAG_KEY) { - netcam->pktarray[indx_next].iskey = TRUE; + netcam->pktarray[indx_next].iskey = true; } else { - netcam->pktarray[indx_next].iskey = FALSE; + netcam->pktarray[indx_next].iskey = false; } - netcam->pktarray[indx_next].iswritten = FALSE; + netcam->pktarray[indx_next].iswritten = false; clock_gettime(CLOCK_REALTIME, &netcam->pktarray[indx_next].timestamp_ts); netcam->pktarray_index = indx_next; @@ -955,22 +956,22 @@ static int netcam_interrupt(void *ctx) struct ctx_netcam *netcam = (struct ctx_netcam *)ctx; if (netcam->finish){ - netcam->interrupted = TRUE; - return TRUE; + netcam->interrupted = true; + return true; } if (netcam->status == NETCAM_CONNECTED) { - return FALSE; + return false; } else if (netcam->status == NETCAM_READINGIMAGE) { clock_gettime(CLOCK_REALTIME, &netcam->interruptcurrenttime); if ((netcam->interruptcurrenttime.tv_sec - netcam->interruptstarttime.tv_sec ) > netcam->interruptduration){ MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO ,_("%s: Camera reading (%s) timed out") , netcam->cameratype, netcam->camera_name); - netcam->interrupted = TRUE; - return TRUE; + netcam->interrupted = true; + return true; } else{ - return FALSE; + return false; } } else { /* This is for NOTCONNECTED and RECONNECTING status. We give these @@ -983,15 +984,15 @@ static int netcam_interrupt(void *ctx) MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO ,_("%s: Camera (%s) timed out") , netcam->cameratype, netcam->camera_name); - netcam->interrupted = TRUE; - return TRUE; + netcam->interrupted = true; + return true; } else{ - return FALSE; + return false; } } /* should not be possible to get here */ - return FALSE; + return false; } static int netcam_open_sws(struct ctx_netcam *netcam) @@ -1177,7 +1178,7 @@ static int netcam_read_image(struct ctx_netcam *netcam) netcam->packet_recv.data = NULL; netcam->packet_recv.size = 0; - netcam->interrupted=FALSE; + netcam->interrupted=false; clock_gettime(CLOCK_REALTIME, &netcam->interruptstarttime); netcam->interruptduration = 10; @@ -1185,7 +1186,7 @@ static int netcam_read_image(struct ctx_netcam *netcam) netcam->img_recv->used = 0; size_decoded = 0; errcnt = 0; - haveimage = FALSE; + haveimage = false; while ((!haveimage) && (!netcam->interrupted)) { retcd = av_read_frame(netcam->format_context, &netcam->packet_recv); @@ -1219,7 +1220,7 @@ static int netcam_read_image(struct ctx_netcam *netcam) } } if (size_decoded > 0 ){ - haveimage = TRUE; + haveimage = true; } else if (size_decoded == 0){ /* Did not fail, just didn't get anything. Try again */ mypacket_unref(netcam->packet_recv); @@ -1466,14 +1467,14 @@ static void netcam_set_parms (struct ctx_cam *cam, struct ctx_netcam *netcam ) netcam->imgsize.height = 0; snprintf(netcam->cameratype, 29, "%s",_("High")); netcam->params = (ctx_params*)mymalloc(sizeof(struct ctx_params)); - netcam->params->update_params = TRUE; + netcam->params->update_params = true; util_parms_parse(netcam->params, cam->conf->netcam_high_params); } else { netcam->imgsize.width = cam->conf->width; netcam->imgsize.height = cam->conf->height; snprintf(netcam->cameratype, 29, "%s",_("Norm")); netcam->params = (ctx_params*)mymalloc(sizeof(struct ctx_params)); - netcam->params->update_params = TRUE; + netcam->params->update_params = true; util_parms_parse(netcam->params, cam->conf->netcam_params); } @@ -1491,8 +1492,8 @@ static void netcam_set_parms (struct ctx_cam *cam, struct ctx_netcam *netcam ) netcam->pktarray_size = 0; netcam->pktarray_index = -1; netcam->pktarray = NULL; - netcam->handler_finished = TRUE; - netcam->first_image = TRUE; + netcam->handler_finished = true; + netcam->first_image = true; netcam->reconnect_count = 0; netcam->src_fps = -1; /* Default to neg so we know it has not been set */ netcam->capture_rate = -1; @@ -1514,7 +1515,7 @@ static void netcam_set_parms (struct ctx_cam *cam, struct ctx_netcam *netcam ) /* If this is the norm and we have a highres, then disable passthru on the norm */ if ((!netcam->high_resolution) && (cam->conf->netcam_high_url != "")) { - netcam->passthrough = FALSE; + netcam->passthrough = false; } else { netcam->passthrough = mycheck_passthrough(cam); } @@ -1525,7 +1526,7 @@ static void netcam_set_parms (struct ctx_cam *cam, struct ctx_netcam *netcam ) clock_gettime(CLOCK_REALTIME, &netcam->interruptcurrenttime); netcam->interruptduration = 5; - netcam->interrupted = FALSE; + netcam->interrupted = false; clock_gettime(CLOCK_REALTIME, &netcam->frame_curr_tm); clock_gettime(CLOCK_REALTIME, &netcam->frame_prev_tm); @@ -1631,7 +1632,7 @@ static int netcam_open_context(struct ctx_netcam *netcam) netcam->format_context = avformat_alloc_context(); netcam->format_context->interrupt_callback.callback = netcam_interrupt; netcam->format_context->interrupt_callback.opaque = netcam; - netcam->interrupted = FALSE; + netcam->interrupted = false; clock_gettime(CLOCK_REALTIME, &netcam->interruptstarttime); @@ -1724,7 +1725,7 @@ static int netcam_open_context(struct ctx_netcam *netcam) ,_("%s: Failed to copy stream for pass-through.") ,netcam->cameratype); } - netcam->passthrough = FALSE; + netcam->passthrough = false; } } @@ -1889,7 +1890,7 @@ static void *netcam_handler(void *arg) struct ctx_netcam *netcam =(struct ctx_netcam *) arg; - netcam->handler_finished = FALSE; + netcam->handler_finished = false; mythreadname_set("nc",netcam->threadnbr, netcam->camera_name); @@ -1927,7 +1928,7 @@ static void *netcam_handler(void *arg) MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO ,_("%s: Exiting"),netcam->cameratype); - netcam->handler_finished = TRUE; + netcam->handler_finished = true; pthread_exit(NULL); } @@ -2006,7 +2007,7 @@ int netcam_setup(struct ctx_cam *cam) return -1; } netcam = cam->netcam; - netcam->high_resolution = FALSE; /* Set flag for this being the normal resolution camera */ + netcam->high_resolution = false; /* Set flag for this being the normal resolution camera */ } else { cam->netcam_high = netcam_new_context(); if (cam->netcam_high == NULL) { @@ -2015,7 +2016,7 @@ int netcam_setup(struct ctx_cam *cam) return -1; } netcam = cam->netcam_high; - netcam->high_resolution = TRUE; /* Set flag for this being the high resolution camera */ + netcam->high_resolution = true; /* Set flag for this being the high resolution camera */ } netcam_null_context(netcam); @@ -2034,7 +2035,7 @@ int netcam_setup(struct ctx_cam *cam) /* When running dual, there seems to be contamination across norm/high with codec functions. */ netcam_close_context(netcam); /* Close in this thread to open it again within handler thread */ netcam->status = NETCAM_RECONNECTING; /* Set as reconnecting to avoid excess messages when starting */ - netcam->first_image = FALSE; /* Set flag that we are not processing our first image */ + netcam->first_image = false; /* Set flag that we are not processing our first image */ /* For normal resolution, we resize the image to the config parms so we do not need * to set the dimension parameters here (it is done in the set_parms). For high res @@ -2064,7 +2065,7 @@ int netcam_next(struct ctx_cam *cam, struct ctx_image_data *img_data) return 1; } pthread_mutex_lock(&cam->netcam->mutex); - netcam_pktarray_resize(cam, FALSE); + netcam_pktarray_resize(cam, false); memcpy(img_data->image_norm , cam->netcam->img_latest->ptr , cam->netcam->img_latest->used); @@ -2076,7 +2077,7 @@ int netcam_next(struct ctx_cam *cam, struct ctx_image_data *img_data) (cam->netcam_high->status == NETCAM_NOTCONNECTED)) return 1; pthread_mutex_lock(&cam->netcam_high->mutex); - netcam_pktarray_resize(cam, TRUE); + netcam_pktarray_resize(cam, true); if (!(cam->netcam_high->high_resolution && cam->netcam_high->passthrough)) { memcpy(img_data->image_high ,cam->netcam_high->img_latest->ptr @@ -2124,7 +2125,7 @@ void netcam_cleanup(struct ctx_cam *cam, int init_retry_flag) * This is shutting down the thread so for the moment, we are not worrying about the * cross threading and protecting these variables with mutex's */ - netcam->finish = TRUE; + netcam->finish = true; netcam->interruptduration = 0; wait_counter = 0; while ((!netcam->handler_finished) && (wait_counter < 10)) { @@ -2165,6 +2166,8 @@ void netcam_cleanup(struct ctx_cam *cam, int init_retry_flag) } cam->netcam = NULL; cam->netcam_high = NULL; - cam->running_cam = FALSE; + if (init_retry_flag == false) { + cam->running_cam = false; + } } diff --git a/src/webu.cpp b/src/webu.cpp index 1a04e53e..c323179b 100644 --- a/src/webu.cpp +++ b/src/webu.cpp @@ -17,26 +17,6 @@ * Copyright 2020 MotionMrDave@gmail.com */ - -/* - * Function naming scheme: - * webu* - All functions in this module have this prefix. - * webu_start - Entry point to start the daemon. - * webu_stop - Entry point to stop the daemon - * webu_mhd* - Functions related to libmicrohttd implementation - * webu_process_action - Performs most items under the action menu - * webu_process_config - Saves the parameter values into Motion. - * webu_process_track - Performs the tracking functions. - * - * Some function names are long and are not expected to contain any - * logger message that would display the function name to the user. - * - * Functions are generally kept to under one page in length - * - * Known Issues: - * The tracking is "best effort" since developer does not have tracking camera. - */ - #include #include #include @@ -47,8 +27,9 @@ #include "util.hpp" #include "webu.hpp" #include "webu_html.hpp" -#include "webu_text.hpp" #include "webu_stream.hpp" +#include "webu_json.hpp" +#include "webu_post.hpp" #include "track.hpp" #include "video_v4l2.hpp" @@ -56,10 +37,8 @@ /* Context to pass the parms to functions to start mhd */ struct mhdstart_ctx { struct ctx_motapp *motapp; - char *tls_cert; - char *tls_key; - int ctrl; - int indxthrd; + std::string tls_cert; + std::string tls_key; struct MHD_OptionItem *mhd_ops; int mhd_opt_nbr; unsigned int mhd_flags; @@ -68,41 +47,36 @@ struct mhdstart_ctx { struct sockaddr_in6 lpbk_ipv6; }; -static void webu_context_init(struct ctx_motapp *motapp, struct ctx_cam *cam, struct webui_ctx *webui) +/* Set defaults for the webui context */ +static void webu_context_init(struct ctx_motapp *motapp, struct webui_ctx *webui) { - int indx; - webui->url = (char*)mymalloc(WEBUI_LEN_URLI); - webui->uri_camid = (char*)mymalloc(WEBUI_LEN_PARM); - webui->uri_cmd1 = (char*)mymalloc(WEBUI_LEN_PARM); - webui->uri_cmd2 = (char*)mymalloc(WEBUI_LEN_PARM); - webui->uri_parm1 = (char*)mymalloc(WEBUI_LEN_PARM); - webui->uri_value1 = (char*)mymalloc(WEBUI_LEN_PARM); - webui->uri_parm2 = (char*)mymalloc(WEBUI_LEN_PARM); - webui->uri_value2 = (char*)mymalloc(WEBUI_LEN_PARM); - webui->clientip = (char*)mymalloc(WEBUI_LEN_URLI); - webui->hostname = (char*)mymalloc(WEBUI_LEN_PARM); - webui->auth_denied = (char*)mymalloc(WEBUI_LEN_RESP); + webui->url = ""; + webui->uri_camid = ""; + webui->uri_cmd1 = ""; + webui->uri_cmd2 = ""; + webui->clientip = ""; + webui->lang = ""; /* Two digit lang code */ + webui->auth_opaque = (char*)mymalloc(WEBUI_LEN_PARM); webui->auth_realm = (char*)mymalloc(WEBUI_LEN_PARM); - webui->text_eol = (char*)mymalloc(WEBUI_LEN_PARM); - webui->auth_user = NULL; /* Buffer to hold the user name*/ - webui->auth_pass = NULL; /* Buffer to hold the password */ - webui->authenticated = FALSE; /* boolean for whether we are authenticated*/ - webui->lang = (char*)mymalloc(3); /* Two digit lang code plus null terminator */ - webui->lang_full = (char*)mymalloc(6); /* lang code, e.g US_en */ - webui->resp_size = WEBUI_LEN_RESP * 10; /* The size of the resp_page buffer. May get adjusted */ - webui->resp_used = 0; /* How many bytes used so far in resp_page*/ - webui->stream_pos = 0; /* Stream position of image being sent */ - webui->stream_fps = 1; /* Stream rate */ - webui->resp_page = (char*)mymalloc(webui->resp_size); /* The response being constructed */ + webui->auth_user = NULL; /* Buffer to hold the user name*/ + webui->auth_pass = NULL; /* Buffer to hold the password */ + webui->authenticated = false; /* boolean for whether we are authenticated*/ + webui->resp_size = WEBUI_LEN_RESP * 10; /* The size of the resp_page buffer. May get adjusted */ + webui->resp_used = 0; /* How many bytes used so far in resp_page*/ + webui->resp_image = NULL; /* Buffer for sending the images */ + webui->stream_pos = 0; /* Stream position of image being sent */ + webui->stream_fps = 1; /* Stream rate */ + webui->resp_page = ""; /* The response being constructed */ webui->post_info = NULL; webui->post_sz = 0; - webui->motapp = motapp; /* The motion application context */ - webui->cam = cam; /* The context pointer for a single camera */ + webui->motapp = motapp; /* The motion application context */ + webui->cam = NULL; /* The context pointer for a single camera */ webui->cnct_type = WEBUI_CNCT_UNKNOWN; - webui->resptype = 0; /* Default to html response */ + webui->resp_type = WEBUI_RESP_HTML; /* Default to html response */ + webui->cnct_method = WEBUI_METHOD_GET; /* get the number of cameras and threads */ indx = 0; @@ -118,17 +92,12 @@ static void webu_context_init(struct ctx_motapp *motapp, struct ctx_cam *cam, st webui->cam_count--; } - /* 1 thread, 1 camera = just motion.conf. - * 2 thread, 1 camera, then using motion.conf plus a separate camera file */ - snprintf(webui->lang_full, 6,"%s", getenv("LANGUAGE")); - snprintf(webui->lang, 3,"%s",webui->lang_full); - - memset(webui->hostname,'\0',WEBUI_LEN_PARM); - memset(webui->resp_page,'\0',webui->resp_size); + webui->lang.assign(getenv("LANGUAGE"), 2); return; } +/* Free a char variable and set to null */ static void webu_free_var(char *parm) { if (parm != NULL) { @@ -137,29 +106,16 @@ static void webu_free_var(char *parm) parm = NULL; } +/* Free the variables in the webui context */ static void webu_context_free(struct webui_ctx *webui) { int indx; - webu_free_var(webui->hostname); - webu_free_var(webui->url); - webu_free_var(webui->uri_camid); - webu_free_var(webui->uri_cmd1); - webu_free_var(webui->uri_cmd2); - webu_free_var(webui->uri_parm1); - webu_free_var(webui->uri_value1); - webu_free_var(webui->uri_parm2); - webu_free_var(webui->uri_value2); - webu_free_var(webui->lang); - webu_free_var(webui->lang_full); - webu_free_var(webui->resp_page); webu_free_var(webui->auth_user); webu_free_var(webui->auth_pass); - webu_free_var(webui->auth_denied); webu_free_var(webui->auth_opaque); webu_free_var(webui->auth_realm); - webu_free_var(webui->clientip); - webu_free_var(webui->text_eol); + webu_free_var(webui->resp_image); for (indx = 0; indxpost_sz; indx++) { webu_free_var(webui->post_info[indx].key_nm); @@ -168,1079 +124,134 @@ static void webu_context_free(struct webui_ctx *webui) free(webui->post_info); webui->post_info = NULL; - free(webui); - - return; -} - -static void webu_badreq(struct webui_ctx *webui) -{ - /* This function is used in this webu module as a central function when there is a bad - * request. Since sometimes we will be unable to determine what camera context (stream - * or camera) originated the request and we have NULL for camlist and cam, we default the - * response to be HTML. Otherwise, we do know the type and we send back to the user the - * bad request response either with or without the HTML tags. - */ - if (webui->resptype == 1) { - webu_text_badreq(webui); - } else { - webu_html_badreq(webui); - } -} - -void webu_write(struct webui_ctx *webui, const char *buf) -{ - /* Copy the buf data to our response buffer. If the response buffer is not large enough to - * accept our new data coming in, then expand it in chunks of 10 - */ - int resp_len; - char *temp_resp; - size_t temp_size; - - resp_len = strlen(buf); - - temp_size = webui->resp_size; - while ((resp_len + webui->resp_used) > temp_size) { - temp_size = temp_size + (WEBUI_LEN_RESP * 10); - } - - if (temp_size > webui->resp_size) { - temp_resp = (char*)mymalloc(webui->resp_size); - memcpy(temp_resp, webui->resp_page, webui->resp_size); - free(webui->resp_page); - webui->resp_page = (char*)mymalloc(temp_size); - memset(webui->resp_page,'\0',temp_size); - memcpy(webui->resp_page, temp_resp, webui->resp_size); - webui->resp_size = temp_size; - free(temp_resp); - } - - memcpy(webui->resp_page + webui->resp_used, buf, resp_len); - webui->resp_used = webui->resp_used + resp_len; + delete webui; return; } +/* Edit the parameters specified in the url sent */ static void webu_parms_edit(struct webui_ctx *webui) { - - /* Determine the thread number provided. - * If no thread provided, assign it to -1 - * Samples: - * http://localhost:8081/0/stream (camlist will be populated and this function will set cam) - * http://localhost:8081/stream (camlist will be null, cam will be populated) - * http://localhost:8081/ (camlist will be null, cam will be populated) - */ int indx, is_nbr; - if (strlen(webui->uri_camid) > 0) { - is_nbr = TRUE; - for (indx=0; indx < (int)strlen(webui->uri_camid); indx++) { + if (webui->uri_camid.length() > 0) { + is_nbr = true; + for (indx=0; indx < (int)webui->uri_camid.length(); indx++) { if ((webui->uri_camid[indx] > '9') || (webui->uri_camid[indx] < '0')) { - is_nbr = FALSE; + is_nbr = false; } } if (is_nbr) { - webui->thread_nbr = atoi(webui->uri_camid); + webui->threadnbr = atoi(webui->uri_camid.c_str()); } else { - webui->thread_nbr = -1; + webui->threadnbr = -1; } } else { - webui->thread_nbr = -1; + webui->threadnbr = -1; } - /* Set the single context pointer to thread we are answering - * If the connection is for a single stream (legacy method of a port - * per stream), then the camlist will be null and the camera context - * will already be assigned into webui->cam. This is part of the - * init function which is called for MHD and it has the different - * variations depending upon how the port and cameras were specified. - * Also set/convert the camid into the thread number. - */ - - if (webui->motapp->cam_list != NULL) { - if (webui->thread_nbr < 0) { - webui->cam = webui->motapp->cam_list[0]; - webui->thread_nbr = 0; - } else { - indx = 0; - while (webui->motapp->cam_list[indx] != NULL) { - if (webui->motapp->cam_list[indx]->camera_id == webui->thread_nbr) { - webui->thread_nbr = indx; - break; - } - indx++; + if (webui->threadnbr < 0) { + webui->cam = webui->motapp->cam_list[0]; + webui->threadnbr = 0; + } else { + indx = 0; + while (webui->motapp->cam_list[indx] != NULL) { + if (webui->motapp->cam_list[indx]->camera_id == webui->threadnbr) { + webui->threadnbr = indx; + break; } - /* This may be null, in which case we will not answer the request */ - webui->cam = webui->motapp->cam_list[indx]; + indx++; } + /* This may be null, in which case we will not answer the request */ + webui->cam = webui->motapp->cam_list[indx]; } - if (webui->cam != NULL) { - if (webui->cam->conf->webcontrol_interface == 1) { - webui->resptype = 1; - } else { - webui->resptype = 0; - } - } - -} - -static void webu_parseurl_parms(struct webui_ctx *webui, char *st_pos) -{ - - /* Parse the parameters of the URI - * Earlier functions have assigned the st_pos to the slash after the action and it is - * pointing at the set/get when this function is invoked. - * Samples (MHD takes off the IP:port) - * /{camid}/config/set?{parm}={value1} - * /{camid}/config/get?query={parm} - * /{camid}/track/set?x={value1}&y={value2} - * /{camid}/track/set?pan={value1}&tilt={value2} - * /{camid}/{cmd1}/{cmd2}?{parm1}={value1}&{parm2}={value2} - */ - - int parm_len, last_parm; - char *en_pos; - - - /* First parse out the "set","get","pan","tilt","x","y" - * from the uri and put them into the cmd2. - * st_pos is at the beginning of the command - * If there is no ? then we are done parsing - * Note that each section is looking for a different - * delimitter. (?, =, &, =, &) - */ - last_parm = FALSE; - en_pos = strstr(st_pos,"?"); - if (en_pos != NULL) { - parm_len = en_pos - st_pos + 1; - if (parm_len >= WEBUI_LEN_PARM) { - return; - } - snprintf(webui->uri_cmd2, parm_len,"%s", st_pos); - - /* Get the parameter name */ - st_pos = st_pos + parm_len; /* Move past the command */ - en_pos = strstr(st_pos,"="); - if (en_pos == NULL) { - parm_len = strlen(webui->url) - parm_len; - last_parm = TRUE; - } else { - parm_len = en_pos - st_pos + 1; - } - if (parm_len >= WEBUI_LEN_PARM) { - return; - } - snprintf(webui->uri_parm1, parm_len,"%s", st_pos); - - if (!last_parm) { - /* Get the parameter value */ - st_pos = st_pos + parm_len; /* Move past the equals sign */ - en_pos = strstr(st_pos,"&"); - if (en_pos == NULL) { - parm_len = strlen(webui->url) - parm_len; - last_parm = TRUE; - } else { - parm_len = en_pos - st_pos + 1; - } - if (parm_len >= WEBUI_LEN_PARM) { - return; - } - snprintf(webui->uri_value1, parm_len,"%s", st_pos); - } - - if (!last_parm) { - /* Get the next parameter name */ - st_pos = st_pos + parm_len; /* Move past the previous command */ - en_pos = strstr(st_pos,"="); - if (en_pos == NULL) { - parm_len = strlen(webui->url) - parm_len; - last_parm = TRUE; - } else { - parm_len = en_pos - st_pos + 1; - } - if (parm_len >= WEBUI_LEN_PARM) { - return; - } - snprintf(webui->uri_parm2, parm_len,"%s", st_pos); - } - - if (!last_parm) { - /* Get the next parameter value */ - st_pos = st_pos + parm_len; /* Move past the equals sign */ - if (!strcasecmp(webui->uri_parm1,"x") || !strcasecmp(webui->uri_parm1,"pan")) { - en_pos = strstr(st_pos,"&"); - } else { - en_pos = NULL; - } - if (en_pos == NULL) { - parm_len = strlen(webui->url) - parm_len; - last_parm = TRUE; - } else { - parm_len = en_pos - st_pos + 1; - } - if (parm_len >= WEBUI_LEN_PARM) { - return; - } - snprintf(webui->uri_value2, parm_len,"%s", st_pos); - } - - } - -} - -static void webu_parseurl_reset(struct webui_ctx *webui) -{ - - /* Reset the variables to empty strings*/ - - memset(webui->uri_camid,'\0',WEBUI_LEN_PARM); - memset(webui->uri_cmd1,'\0',WEBUI_LEN_PARM); - memset(webui->uri_cmd2,'\0',WEBUI_LEN_PARM); - memset(webui->uri_parm1,'\0',WEBUI_LEN_PARM); - memset(webui->uri_value1,'\0',WEBUI_LEN_PARM); - memset(webui->uri_parm2,'\0',WEBUI_LEN_PARM); - memset(webui->uri_value2,'\0',WEBUI_LEN_PARM); + MOTION_LOG(DBG, TYPE_STREAM, NO_ERRNO + , "camid: >%s< thread: >%d< cmd1: >%s< cmd2: >%s<" + , webui->uri_camid.c_str(), webui->threadnbr + , webui->uri_cmd1.c_str(), webui->uri_cmd2.c_str()); + } +/* Extract the camid and cmds from the url */ static int webu_parseurl(struct webui_ctx *webui) { - /* Parse the sent URI into the commands and parameters - * so we can check the resulting strings in later functions - * and determine what actions to take. - * Samples - * / - * /{camid} - * /{camid}/config/set?log_level=6 - * /{camid}/config/set?{parm}={value1} - * /{camid}/config/get?query={parm} - * /{camid}/track/set?x={value1}&y={value2} - * /{camid}/track/set?pan={value1}&tilt={value2} - * /{camid}/{cmd1}/{cmd2}?{parm1}={value1}&{parm2}={value2} - */ - - int retcd, parm_len, last_slash; - char *st_pos, *en_pos; + int retcd; + char *tmpurl; + size_t pos_slash1, pos_slash2; + /* Example: /camid/cmd1/cmd2 */ retcd = 0; + webui->uri_camid = ""; + webui->uri_cmd1 = ""; + webui->uri_cmd2 = ""; - MOTION_LOG(DBG, TYPE_STREAM, NO_ERRNO, _("Sent url: %s"),webui->url); - - webu_parseurl_reset(webui); - - if (strlen(webui->url) == 0) { + if (webui->url.length() == 0) { return -1; } - MHD_http_unescape(webui->url); + if (webui->url == "/favicon.ico") { + return -1; + } - MOTION_LOG(DBG, TYPE_STREAM, NO_ERRNO, _("Decoded url: %s"),webui->url); + MOTION_LOG(DBG, TYPE_STREAM, NO_ERRNO, _("Sent url: %s"),webui->url.c_str()); - /* Home page */ - if (strlen(webui->url) == 1) { + tmpurl = (char*)mymalloc(webui->url.length()+1); + memcpy(tmpurl, webui->url.c_str(), webui->url.length()); + + MHD_http_unescape(tmpurl); + + webui->url.assign(tmpurl); + free(tmpurl); + + MOTION_LOG(DBG, TYPE_STREAM, NO_ERRNO, _("Decoded url: %s"),webui->url.c_str()); + + if (webui->url.length() == 1) { return 0; } - last_slash = 0; - - /* Get the camid number and which sometimes this will contain an action if the user - * is setting the port for a particular camera and requests the - * stream by using http://localhost:port/stream - */ - st_pos = webui->url + 1; /* Move past the first "/" */ - if (*st_pos == '-') { - /* Never allow a negative number */ - return -1; - } - en_pos = strstr(st_pos,"/"); - if (en_pos == NULL) { - parm_len = strlen(webui->url); - last_slash = 1; + pos_slash1 = webui->url.find("/", 1); + if (pos_slash1 != std::string::npos) { + webui->uri_camid = webui->url.substr(1, pos_slash1 - 1); } else { - parm_len = en_pos - st_pos + 1; - } - if (parm_len >= WEBUI_LEN_PARM) { - /* var was malloc'd to WEBUI_LEN_PARM */ - return -1; - } - snprintf(webui->uri_camid, parm_len,"%s", st_pos); - - if (!last_slash) { - /* Get cmd1 or action */ - st_pos = st_pos + parm_len; /* Move past the camid */ - en_pos = strstr(st_pos,"/"); - if (en_pos == NULL) { - parm_len = strlen(webui->url) - parm_len ; - last_slash = 1; - } else { - parm_len = en_pos - st_pos + 1; - } - if (parm_len >= WEBUI_LEN_PARM) { - /* var was malloc'd to WEBUI_LEN_PARM */ - return -1; - } - snprintf(webui->uri_cmd1, parm_len,"%s", st_pos); + webui->uri_camid = webui->url.substr(1); + return 0; } - if (!last_slash) { - /* Get cmd2 or action */ - st_pos = st_pos + parm_len; /* Move past the first command */ - en_pos = strstr(st_pos,"/"); - if (en_pos == NULL) { - parm_len = strlen(webui->url) - parm_len; - last_slash = 1; - } else { - parm_len = en_pos - st_pos + 1; - } - if (parm_len >= WEBUI_LEN_PARM) { - /* var was malloc'd to WEBUI_LEN_PARM */ - return -1; - } - snprintf(webui->uri_cmd2, parm_len,"%s", st_pos); + pos_slash1++; + if (pos_slash1 >= webui->url.length()) { + return 0; } - if ((mystreq(webui->uri_cmd1,"config") || - mystreq(webui->uri_cmd1,"track")) && - (strlen(webui->uri_cmd2) > 0)) { - webu_parseurl_parms(webui, st_pos); - } - - MOTION_LOG(DBG, TYPE_STREAM, NO_ERRNO, - "camid: >%s< cmd1: >%s< cmd2: >%s< parm1:>%s< val1:>%s< parm2:>%s< val2:>%s<" - ,webui->uri_camid - ,webui->uri_cmd1, webui->uri_cmd2 - ,webui->uri_parm1, webui->uri_value1 - ,webui->uri_parm2, webui->uri_value2); - - - return retcd; - -} - -static void webu_process_add(struct webui_ctx *webui) -{ - int indx, maxcnt; - - MOTION_LOG(INF, TYPE_ALL, NO_ERRNO, "Adding camera."); - - maxcnt = 100; - - /* webu_html_main locks it at the top of that function but for this action, we need to unlock it */ - pthread_mutex_unlock(&webui->motapp->mutex_camlst); - - webui->motapp->cam_add = TRUE; - indx = 0; - while ((webui->motapp->cam_add == TRUE) && (indx < maxcnt)) { - SLEEP(0, 50000000) - indx++; - } - - if (indx == maxcnt) { - webui->motapp->cam_add = TRUE; - MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "Error adding camera. Timed out"); - return; - } - - /* Now lock it back up so that webu_html_main can unlock it upon exit from that function */ - pthread_mutex_lock(&webui->motapp->mutex_camlst); - - MOTION_LOG(INF, TYPE_ALL, NO_ERRNO, "New camera added."); - -} - -static void webu_process_delete(struct webui_ctx *webui) -{ - int indx, maxcnt; - - if (webui->thread_nbr == 0) { - MOTION_LOG(INF, TYPE_ALL, NO_ERRNO, "No camera specified for deletion." ); - return; + pos_slash2 = webui->url.find("/", pos_slash1); + if (pos_slash2 != std::string::npos) { + webui->uri_cmd1 = webui->url.substr(pos_slash1, pos_slash2 - pos_slash1); } else { - MOTION_LOG(INF, TYPE_ALL, NO_ERRNO, "Deleting camera."); + webui->uri_cmd1 = webui->url.substr(pos_slash1); + return 0; } - maxcnt = 100; - - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO, - _("Stopping cam %d"),webui->cam->camera_id); - webui->cam->restart_cam = FALSE; - webui->cam->finish_cam = TRUE; - - indx = 0; - while ((webui->cam->running_cam) && (indx < maxcnt)) { - SLEEP(0, 50000000) - indx++; + pos_slash1 = ++pos_slash2; + if (pos_slash1 >= webui->url.length()) { + return 0; } - if (indx == maxcnt) { - webui->motapp->cam_delete = 0; - MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "Error deleting camera. Timed out shutting down"); - return; - } - MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, "Camera stopped"); - - /* webu_html_main and webu_text_main lock the mutex at beginning of their functions. - * We need it unlocked so that the add/delete will work - */ - pthread_mutex_unlock(&webui->motapp->mutex_camlst); - - webui->motapp->cam_delete = webui->thread_nbr; - - indx = 0; - while ((webui->motapp->cam_delete > 0) && (indx < maxcnt)) { - SLEEP(0, 50000000) - indx++; - } - if (indx == maxcnt) { - webui->motapp->cam_delete = 0; - MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "Error deleting camera. Timed out"); - return; - } - webui->cam = NULL; - - /* We now lock the mutex so that the "unlock" at the bottom of - * webu_html_main, webu_text_main will work. - */ - pthread_mutex_lock(&webui->motapp->mutex_camlst); - -} - -/* Process the actions from the webcontrol that the user requested */ -void webu_process_action(struct webui_ctx *webui) -{ - int indx; - - if ((mystreq(webui->uri_cmd2,"makemovie")) || - (mystreq(webui->uri_cmd2,"eventend"))) { - if (webui->thread_nbr == 0 && webui->cam_threads > 1) { - indx = 1; - while (webui->motapp->cam_list[indx]) { - webui->motapp->cam_list[indx]->event_stop = TRUE; - indx++; - } - } else { - webui->cam->event_stop = TRUE; - } - - } else if (mystreq(webui->uri_cmd2,"eventstart")) { - if (webui->thread_nbr == 0 && webui->cam_threads > 1) { - indx = 1; - while (webui->motapp->cam_list[indx]) { - webui->motapp->cam_list[indx]->event_user = TRUE; - indx++; - } - } else { - webui->cam->event_user = TRUE; - } - - } else if (mystreq(webui->uri_cmd2,"snapshot")) { - if (webui->thread_nbr == 0 && webui->cam_threads > 1) { - indx = 1; - while (webui->motapp->cam_list[indx]) { - webui->motapp->cam_list[indx]->snapshot = 1; - indx++; - } - } else { - webui->cam->snapshot = 1; - } - - - } else if (mystreq(webui->uri_cmd2,"restart")) { - if (webui->thread_nbr == 0) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO, _("Restarting all threads")); - indx = 1; - while (webui->motapp->cam_list[indx]) { - webui->motapp->cam_list[indx]->restart_cam = TRUE; - if (webui->motapp->cam_list[indx]->running_cam) { - webui->motapp->cam_list[indx]->event_stop = TRUE; - webui->motapp->cam_list[indx]->finish_cam = TRUE; - } - indx++; - } - } else { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO, - _("Restarting thread %d"),webui->thread_nbr); - webui->cam->restart_cam = TRUE; - if (webui->cam->running_cam) { - webui->cam->event_stop = TRUE; - webui->cam->finish_cam = TRUE; - } - - } - - } else if (mystreq(webui->uri_cmd2,"stop")) { - if (webui->thread_nbr == 0 && webui->cam_threads > 1) { - indx = 1; - while (webui->motapp->cam_list[indx]) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO, - _("Stopping cam %d"),webui->motapp->cam_list[indx]->camera_id); - webui->motapp->cam_list[indx]->restart_cam = FALSE; - webui->motapp->cam_list[indx]->event_stop = TRUE; - webui->motapp->cam_list[indx]->event_user = TRUE; - webui->motapp->cam_list[indx]->finish_cam = TRUE; - indx++; - } - } else { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO, - _("Stopping cam %d"),webui->cam->camera_id); - webui->cam->restart_cam = FALSE; - webui->cam->event_stop = TRUE; - webui->cam->event_user = TRUE; - webui->cam->finish_cam = TRUE; - } - - } else if (mystreq(webui->uri_cmd2,"end")) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO, _("Motion terminating")); - indx = 0; - while (webui->motapp->cam_list[indx]) { - webui->motapp->cam_list[indx]->restart_cam = FALSE; - webui->motapp->cam_list[indx]->event_stop = TRUE; - webui->motapp->cam_list[indx]->event_user = TRUE; - webui->motapp->cam_list[indx]->finish_cam = TRUE; - indx++; - } - - } else if (mystreq(webui->uri_cmd2,"resume")) { - if (webui->thread_nbr == 0 && webui->cam_threads > 1) { - indx = 0; - while (webui->motapp->cam_list[indx]) { - webui->motapp->cam_list[indx]->pause = 0; - indx++; - }; - } else { - webui->cam->pause = 0; - } - - } else if (mystreq(webui->uri_cmd2,"pause")) { - if (webui->thread_nbr == 0 && webui->cam_threads > 1) { - indx = 0; - while (webui->motapp->cam_list[indx]) { - webui->motapp->cam_list[indx]->pause = 1; - indx++; - }; - } else { - webui->cam->pause = 1; - } - - } else if (mystreq(webui->uri_cmd2,"connection")) { - webu_text_connection(webui); - - } else if (mystreq(webui->uri_cmd2,"status")) { - webu_text_status(webui); - - } else if (mystreq(webui->uri_cmd2,"write") || - mystreq(webui->uri_cmd2,"writeyes")) { - conf_parms_write(webui->motapp->cam_list); - - } else if (mystreq(webui->uri_cmd2,"add")) { - webu_process_add(webui); - - } else if (mystreq(webui->uri_cmd2,"delete")) { - webu_process_delete(webui); + pos_slash2 = webui->url.find("/", pos_slash1); + if (pos_slash2 != std::string::npos) { + webui->uri_cmd2 = webui->url.substr(pos_slash1, pos_slash2 - pos_slash1); } else { - MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO, - _("Invalid action requested: >%s< >%s< >%s<") - , webui->uri_camid, webui->uri_cmd1, webui->uri_cmd2); - return; - } -} - -static int webu_process_config_set(struct webui_ctx *webui) -{ - /* Process the request to change the configuration parameters. Used - * both the html and text interfaces. If the parameter was found, then - * we return 0 otherwise a -1 to tell the calling function whether it - * was a valid parm to change. - */ - int indx, retcd; - char temp_name[WEBUI_LEN_PARM]; - - /* Search through the depreciated parms and if applicable, - * get the new parameter name so we can check its webcontrol_parms level - */ - snprintf(temp_name, WEBUI_LEN_PARM, "%s", webui->uri_parm1); - indx=0; - while (config_parms_depr[indx].parm_name != "") { - if (mystreq(config_parms_depr[indx].parm_name.c_str() ,webui->uri_parm1)) { - snprintf(temp_name, WEBUI_LEN_PARM, "%s", config_parms_depr[indx].newname.c_str()); - break; - } - indx++; - } - /* Ignore any request to change an option that is designated above the - * webcontrol_parms level. - */ - indx=0; - while (config_parms[indx].parm_name != "") { - if (((webui->thread_nbr != 0) && (config_parms[indx].main_thread)) || - (config_parms[indx].webui_level > webui->motapp->cam_list[0]->conf->webcontrol_parms) || - (config_parms[indx].webui_level == WEBUI_LEVEL_NEVER) ) { - indx++; - continue; - } - if (mystreq(temp_name, config_parms[indx].parm_name.c_str())) { - break; - } - indx++; - } - /* If we found the parm, assign it. If the loop above did not find the parm - * then we ignore the request - */ - if (config_parms[indx].parm_name != "") { - if (strlen(webui->uri_value1) > 0) { - conf_edit_set(webui->motapp, false, webui->thread_nbr - ,config_parms[indx].parm_name, webui->uri_value1); - - /*If we are updating vid parms, set the flag to update the device.*/ - if ((config_parms[indx].parm_name == "v4l2_parms") && - (webui->motapp->cam_list[webui->thread_nbr]->v4l2cam->params != NULL)) { - webui->motapp->cam_list[webui->thread_nbr]->v4l2cam->params->update_params = TRUE; - } - - /* If changing language, do it now */ - if (config_parms[indx].parm_name == "native_language") { - if (webui->motapp->cam_list[webui->thread_nbr]->motapp->native_language) { - mytranslate_text("", 1); - MOTION_LOG(INF, TYPE_ALL, NO_ERRNO,_("Native Language : on")); - } else { - mytranslate_text("", 0); - MOTION_LOG(INF, TYPE_ALL, NO_ERRNO,_("Native Language : off")); - } - } - } else { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO,_("Set the value to null/zero")); - } - retcd = 0; - } else { - retcd = -1; - } - - return retcd; - -} - -static void webu_process_json_parm(struct webui_ctx *webui, int indx_cam, int indx_parm) -{ - int indx_orig, indx_val; - char response[WEBUI_LEN_RESP]; - char parm_orig[PATH_MAX], parm_val[PATH_MAX], parm_list[PATH_MAX]; - - memset(parm_orig, '\0',PATH_MAX); - memset(parm_val, '\0',PATH_MAX); - memset(parm_list, '\0',PATH_MAX); - - conf_edit_get(webui->motapp->cam_list[indx_cam] - , config_parms[indx_parm].parm_name.c_str() - , parm_orig - , config_parms[indx_parm].parm_cat); - - if (strstr(parm_orig, "\"")) { - indx_val = 0; - for (indx_orig = 0; indx_orig < (int)strlen(parm_orig); indx_orig++){ - if (parm_orig[indx_orig] == '"') { - parm_val[indx_val] = '\\'; - indx_val++; - } - parm_val[indx_val] = parm_orig[indx_orig]; - indx_val++; - if (indx_val == PATH_MAX) { - break; - } - } - } else { - memcpy(parm_val, parm_orig, PATH_MAX); - } - - if (config_parms[indx_parm].parm_type == PARM_TYP_INT) { - snprintf(response, sizeof (response) - , "\"%s\":{\"value\": %s,\"enabled\":true" - ",\"category\":%d, \"type\":\"%s\"}" - , config_parms[indx_parm].parm_name.c_str() - , parm_val - , config_parms[indx_parm].parm_cat - , conf_type_desc(config_parms[indx_parm].parm_type).c_str() - ); - } else if (config_parms[indx_parm].parm_type == PARM_TYP_BOOL) { - if (mystreq(parm_val, "on")) { - snprintf(response, sizeof (response) - , "\"%s\":{\"value\": true,\"enabled\":true" - ",\"category\":%d, \"type\":\"%s\"}" - , config_parms[indx_parm].parm_name.c_str() - , config_parms[indx_parm].parm_cat - , conf_type_desc(config_parms[indx_parm].parm_type).c_str() - ); - } else { - snprintf(response, sizeof (response) - , "\"%s\":{\"value\": false,\"enabled\":true" - ",\"category\":%d, \"type\":\"%s\"}" - , config_parms[indx_parm].parm_name.c_str() - , config_parms[indx_parm].parm_cat - , conf_type_desc(config_parms[indx_parm].parm_type).c_str() - ); - } - } else if (config_parms[indx_parm].parm_type == PARM_TYP_LIST) { - conf_edit_list(webui->motapp->cam_list[indx_cam] - , config_parms[indx_parm].parm_name.c_str() - , parm_list - , config_parms[indx_parm].parm_cat); - - snprintf(response, sizeof (response) - , "\"%s\":{\"value\": \"%s\",\"enabled\":true" - ",\"category\":%d, \"type\":\"%s\",\"list\":%s }" - , config_parms[indx_parm].parm_name.c_str() - , parm_val - , config_parms[indx_parm].parm_cat - , conf_type_desc(config_parms[indx_parm].parm_type).c_str() - , parm_list - ); - - } else { - snprintf(response, sizeof (response) - , "\"%s\":{\"value\": \"%s\",\"enabled\":true" - ",\"category\":%d, \"type\":\"%s\"}" - , config_parms[indx_parm].parm_name.c_str() - , parm_val - , config_parms[indx_parm].parm_cat - , conf_type_desc(config_parms[indx_parm].parm_type).c_str() - ); - } - webu_write(webui, response); - -} - -static void webu_process_json_parms(struct webui_ctx *webui, int indx_cam) -{ - int indx_parm, first; - char response[WEBUI_LEN_RESP]; - - indx_parm = 0; - first = true; - while ((config_parms[indx_parm].parm_name != "") ) { - if ((config_parms[indx_parm].webui_level == WEBUI_LEVEL_NEVER)) { - indx_parm++; - continue; - } - if (first) { - first = false; - snprintf(response, sizeof (response), "%s","{"); - webu_write(webui, response); - } else { - snprintf(response, sizeof (response), "%s",","); - webu_write(webui, response); - } - if (config_parms[indx_parm].webui_level > webui->motapp->cam_list[0]->conf->webcontrol_parms) { - snprintf(response, sizeof (response) - , "\"%s\":{\"value\":\"\",\"enabled\":false" - ",\"category\":%d, \"type\":\"%s\"}" - , config_parms[indx_parm].parm_name.c_str() - , config_parms[indx_parm].parm_cat - , conf_type_desc(config_parms[indx_parm].parm_type).c_str() - ); - webu_write(webui, response); - } else { - webu_process_json_parm(webui, indx_cam, indx_parm); - } - indx_parm++; - } - snprintf(response, sizeof (response), "%s","}"); - webu_write(webui, response); - -} - -static void webu_process_json_config(struct webui_ctx *webui) -{ - int indx_cam, first; - char response[WEBUI_LEN_RESP]; - - indx_cam = 0; - first = true; - while (webui->motapp->cam_list[indx_cam] != NULL) { - if (first) { - first = false; - snprintf(response, sizeof (response), "%s","{"); - webu_write(webui, response); - } else { - snprintf(response, sizeof (response), "%s",","); - webu_write(webui, response); - } - snprintf(response, sizeof (response) - , "\"cam%d\": ",webui->motapp->cam_list[indx_cam]->conf->camera_id); - webu_write(webui, response); - - webu_process_json_parms(webui, indx_cam); - - indx_cam++; - } - snprintf(response, sizeof (response), "%s","}"); - webu_write(webui, response); - - return; - -} - -static void webu_process_json_cameras(struct webui_ctx *webui) -{ - int indx_cam; - char response[WEBUI_LEN_RESP]; - - /* Get the count */ - indx_cam = 0; - while (webui->motapp->cam_list[indx_cam] != NULL) { - indx_cam++; - } - snprintf(response, sizeof (response) - ,"{\"count\" : %d", indx_cam - 1); - webu_write(webui, response); - - indx_cam = 0; - while (webui->motapp->cam_list[indx_cam] != NULL) { - snprintf(response, sizeof(response), ",\"%d\": ", indx_cam) ; - webu_write(webui, response); - - if (indx_cam == 0) { - snprintf(response, sizeof(response), "{\"name\": \"default\" "); - } else if (webui->motapp->cam_list[indx_cam]->conf->camera_name == "") { - snprintf(response, sizeof(response), "{\"name\": \"camera %d\" " - , webui->motapp->cam_list[indx_cam]->conf->camera_id); - } else { - snprintf(response, sizeof(response), "{\"name\": \"%s\" " - , webui->motapp->cam_list[indx_cam]->conf->camera_name.c_str()); - } - webu_write(webui, response); - - snprintf(response, sizeof(response), ",\"id\": %d " - , webui->motapp->cam_list[indx_cam]->conf->camera_id); - webu_write(webui, response); - - if (indx_cam == 0) { - snprintf(response, sizeof(response), "%s","}"); - } else { - if (webui->motapp->cam_list[0]->conf->stream_port != 0) { - snprintf(response, sizeof(response) - , ",\"url\": \"%s://%s:%d/%d/\"} " - , webui->hostproto, webui->hostname - , webui->motapp->cam_list[0]->conf->stream_port - , webui->motapp->cam_list[indx_cam]->conf->camera_id); - } else { - snprintf(response, sizeof(response) - , ",\"url\": \"%s://%s:%d/\"} " - , webui->hostproto - , webui->hostname - , webui->motapp->cam_list[indx_cam]->conf->stream_port); - } - } - webu_write(webui, response); - - indx_cam++; - } - snprintf(response, sizeof (response), "%s","}"); - webu_write(webui, response); - - return; - -} - -static void webu_process_json_categories(struct webui_ctx *webui) -{ - int indx_cat; - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof(response),"%s","{"); - webu_write(webui, response); - - indx_cat = 0; - while (indx_cat != PARM_CAT_MAX) { - if (indx_cat != 0) { - snprintf(response, sizeof(response),"%s",","); - webu_write(webui, response); - } - snprintf(response, sizeof(response), "\"%d\": ", indx_cat) ; - webu_write(webui, response); - - if (indx_cat == PARM_CAT_00) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"system\",\"display\":\"System\"}"); - } else if (indx_cat == PARM_CAT_01) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"camera\",\"display\":\"Camera\"}"); - } else if (indx_cat == PARM_CAT_02) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"source\",\"display\":\"Camera Source\"}"); - } else if (indx_cat == PARM_CAT_03) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"image\",\"display\":\"Image\"}"); - } else if (indx_cat == PARM_CAT_04) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"overlay\",\"display\":\"Overlays\"}"); - } else if (indx_cat == PARM_CAT_05) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"method\",\"display\":\"Method\"}"); - } else if (indx_cat == PARM_CAT_06) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"masks\",\"display\":\"Masks\"}"); - } else if (indx_cat == PARM_CAT_07) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"detect\",\"display\":\"Detection\"}"); - } else if (indx_cat == PARM_CAT_08) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"scripts\",\"display\":\"Scripts\"}"); - } else if (indx_cat == PARM_CAT_09) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"picture\",\"display\":\"Picture\"}"); - } else if (indx_cat == PARM_CAT_10) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"movie\",\"display\":\"Movie\"}"); - } else if (indx_cat == PARM_CAT_11) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"timelapse\",\"display\":\"Timelapse\"}"); - } else if (indx_cat == PARM_CAT_12) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"pipes\",\"display\":\"Pipes\"}"); - } else if (indx_cat == PARM_CAT_13) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"webcontrol\",\"display\":\"Web Control\"}"); - } else if (indx_cat == PARM_CAT_14) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"streams\",\"display\":\"Web Stream\"}"); - } else if (indx_cat == PARM_CAT_15) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"database\",\"display\":\"Database\"}"); - } else if (indx_cat == PARM_CAT_16) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"sql\",\"display\":\"SQL\"}"); - } else if (indx_cat == PARM_CAT_17) { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"track\",\"display\":\"Tracking\"}"); - } else { - snprintf(response, sizeof(response),"%s" - , "{\"name\":\"unk\",\"display\":\"Unknown\"}"); - } - webu_write(webui, response); - - indx_cat++; - } - - snprintf(response, sizeof(response), "%s","}"); - webu_write(webui, response); - - return; - -} - -int webu_process_json(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webui->resptype = 2; - - snprintf(response, sizeof (response),"%s" - ,"{\"version\" : \"" VERSION "\""); - webu_write(webui, response); - - snprintf(response, sizeof (response), "%s",",\"cameras\" : "); - webu_write(webui, response); - - webu_process_json_cameras(webui); - - snprintf(response, sizeof (response), "%s",",\"configuration\" : "); - webu_write(webui, response); - - webu_process_json_config(webui); - - snprintf(response, sizeof (response), "%s",",\"categories\" : "); - webu_write(webui, response); - - webu_process_json_categories(webui); - - snprintf(response, sizeof (response), "%s","}"); - webu_write(webui, response); - - return 0; - -} - -int webu_process_config(struct webui_ctx *webui) -{ - - int retcd; - - retcd = 0; - - if (mystreq(webui->uri_cmd1,"config") && - mystreq(webui->uri_cmd2,"set")) { - retcd = webu_process_config_set(webui); - - } else if (mystreq(webui->uri_cmd1,"config") && - mystreq(webui->uri_cmd2,"get")) { - webu_text_get_query(webui); - - } else if (mystreq(webui->uri_cmd1,"config") && - mystreq(webui->uri_cmd2,"list")) { - webu_text_list(webui); - - } else { - MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO, - _("Invalid action requested: >%s< >%s< >%s<") - , webui->uri_camid, webui->uri_cmd1, webui->uri_cmd2); - - } - - return retcd; - -} - -int webu_process_track(struct webui_ctx *webui) -{ - /* Call the tracking move functions as requested */ - struct ctx_coord cent; - int retcd; - - if (mystreq(webui->uri_cmd2, "center")) { - webui->motapp->cam_list[webui->thread_nbr]->frame_skip = track_center(webui->motapp->cam_list[webui->thread_nbr], 0, 1, 0, 0); - retcd = 0; - } else if (mystreq(webui->uri_cmd2, "set")) { - if (mystreq(webui->uri_parm1, "pan")) { - cent.width = webui->motapp->cam_list[webui->thread_nbr]->imgs.width; - cent.height = webui->motapp->cam_list[webui->thread_nbr]->imgs.height; - cent.x = atoi(webui->uri_value1); - cent.y = 0; - webui->motapp->cam_list[webui->thread_nbr]->frame_skip = track_move(webui->motapp->cam_list[webui->thread_nbr] - ,webui->motapp->cam_list[webui->thread_nbr]->video_dev - ,¢, &webui->motapp->cam_list[webui->thread_nbr]->imgs, 1); - - cent.width = webui->motapp->cam_list[webui->thread_nbr]->imgs.width; - cent.height = webui->motapp->cam_list[webui->thread_nbr]->imgs.height; - cent.x = 0; - cent.y = atoi(webui->uri_value2); - webui->motapp->cam_list[webui->thread_nbr]->frame_skip = track_move(webui->motapp->cam_list[webui->thread_nbr] - ,webui->motapp->cam_list[webui->thread_nbr]->video_dev - ,¢, &webui->motapp->cam_list[webui->thread_nbr]->imgs, 1); - retcd = 0; - } else if (mystrceq(webui->uri_parm1, "x")) { - webui->motapp->cam_list[webui->thread_nbr]->frame_skip = track_center(webui->motapp->cam_list[webui->thread_nbr] - , webui->motapp->cam_list[webui->thread_nbr]->video_dev, 1 - , atoi(webui->uri_value1), atoi(webui->uri_value2)); - retcd = 0; - } else { - retcd = -1; - } - } else { - retcd = -1; + webui->uri_cmd2 = webui->url.substr(pos_slash1); + return 0; } return retcd; } +/* Log the ip of the client connecting*/ static void webu_clientip(struct webui_ctx *webui) { - /* Extract the IP of the client that is connecting. When the - * user specifies Motion to use IPV6 and a IPV4 address comes to us - * the IPv4 address is prepended with a ::ffff: We then trim that off - * so we don't confuse our users. - */ const union MHD_ConnectionInfo *con_info; char client[WEBUI_LEN_URLI]; const char *ip_dst; @@ -1248,15 +259,9 @@ static void webu_clientip(struct webui_ctx *webui) struct sockaddr_in *con_socket4; int is_ipv6; - is_ipv6 = FALSE; - if (webui->cam != NULL ) { - if (webui->cam->conf->webcontrol_ipv6) { - is_ipv6 = TRUE; - } - } else { - if (webui->motapp->cam_list[0]->conf->webcontrol_ipv6) { - is_ipv6 = TRUE; - } + is_ipv6 = false; + if (webui->motapp->cam_list[0]->conf->webcontrol_ipv6) { + is_ipv6 = true; } con_info = MHD_get_connection_info(webui->connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS); @@ -1264,93 +269,70 @@ static void webu_clientip(struct webui_ctx *webui) con_socket6 = (struct sockaddr_in6 *)con_info->client_addr; ip_dst = inet_ntop(AF_INET6, &con_socket6->sin6_addr, client, WEBUI_LEN_URLI); if (ip_dst == NULL) { - snprintf(webui->clientip, WEBUI_LEN_URLI, "%s", "Unknown"); + webui->clientip = "Unknown"; } else { - if (strncmp(client,"::ffff:",7) == 0) { - snprintf(webui->clientip, WEBUI_LEN_URLI, "%s", client + 7); - } else { - snprintf(webui->clientip, WEBUI_LEN_URLI, "%s", client); + webui->clientip.assign(client); + if (webui->clientip.substr(0, 7) == "::ffff:") { + webui->clientip = webui->clientip.substr(7); } } } else { con_socket4 = (struct sockaddr_in *)con_info->client_addr; ip_dst = inet_ntop(AF_INET, &con_socket4->sin_addr, client, WEBUI_LEN_URLI); if (ip_dst == NULL) { - snprintf(webui->clientip, WEBUI_LEN_URLI, "%s", "Unknown"); + webui->clientip = "Unknown"; } else { - snprintf(webui->clientip,WEBUI_LEN_URLI,"%s",client); + webui->clientip.assign(client); } } - MOTION_LOG(INF,TYPE_ALL, NO_ERRNO, _("Connection from: %s"),webui->clientip); + MOTION_LOG(INF,TYPE_ALL, NO_ERRNO, _("Connection from: %s"),webui->clientip.c_str()); } -static void webu_hostname(struct webui_ctx *webui, int ctrl) +/* Get the hostname */ +static void webu_hostname(struct webui_ctx *webui) { - - /* use the hostname the browser used to connect to us when - * constructing links to the stream ports. If available - * (which it is in all modern browsers) it is more likely to - * work than the result of gethostname(), which is reliant on - * the machine we're running on having it's hostname setup - * correctly and corresponding DNS in place. */ - const char *hdr; - char *en_pos; - int host_len; + std::string hostname; - hdr = MHD_lookup_connection_value (webui->connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_HOST); + hostname = "localhost"; + + hdr = MHD_lookup_connection_value(webui->connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_HOST); if (hdr != NULL) { - snprintf(webui->hostname, WEBUI_LEN_PARM, "%s", hdr); - /* IPv6 addresses have :'s in them so special case them */ - if (webui->hostname[0] == '[') { - en_pos = strstr(webui->hostname, "]"); - if (en_pos != NULL) { - host_len = en_pos - webui->hostname + 2; - snprintf(webui->hostname, host_len, "%s", hdr); - } - } else { - en_pos = strstr(webui->hostname, ":"); - if (en_pos != NULL) { - host_len = en_pos - webui->hostname + 1; - snprintf(webui->hostname, host_len, "%s", hdr); - } + hostname.assign(hdr); + if ((hdr[0] == '[') && (hostname.find("]") != std::string::npos)) { + hostname = hostname.substr(0, hostname.find("]") + 1); + } else if ((hdr[0] != '[') && (hostname.find(":") != std::string::npos)) { + hostname = hostname.substr(0, hostname.find(":")); } - } else { - gethostname(webui->hostname, WEBUI_LEN_PARM - 1); } - /* Assign the type of protocol that is associated with the host - * so we can use this protocol as we are building the html page or - * streams. - */ - if (ctrl) { - if (webui->cam->conf->webcontrol_tls) { - snprintf(webui->hostproto,6,"%s","https"); - } else { - snprintf(webui->hostproto,6,"%s","http"); - } + if (webui->motapp->cam_list[0]->conf->webcontrol_tls) { + webui->hostfull = "https"; } else { - if (webui->cam->conf->stream_tls) { - snprintf(webui->hostproto,6,"%s","https"); - } else { - snprintf(webui->hostproto,6,"%s","http"); - } + webui->hostfull = "http"; } + webui->hostfull += "://" + hostname + ":" + + std::to_string(webui->motapp->cam_list[0]->conf->webcontrol_port); + + MOTION_LOG(DBG,TYPE_ALL, NO_ERRNO, _("Full Host: %s"), webui->hostfull.c_str()); return; } +/* Create a authorization denied response to user*/ static mhdrslt webu_mhd_digest_fail(struct webui_ctx *webui,int signal_stale) { - /* Create a denied response to user*/ struct MHD_Response *response; mhdrslt retcd; - webui->authenticated = FALSE; + webui->authenticated = false; - response = MHD_create_response_from_buffer(strlen(webui->auth_denied) - ,(void *)webui->auth_denied, MHD_RESPMEM_PERSISTENT); + webui->resp_page = "Access denied" + "Access denied"; + + response = MHD_create_response_from_buffer(webui->resp_page.length() + ,(void *)webui->resp_page.c_str(), MHD_RESPMEM_PERSISTENT); if (response == NULL) { return MHD_NO; @@ -1365,9 +347,10 @@ static mhdrslt webu_mhd_digest_fail(struct webui_ctx *webui,int signal_stale) return retcd; } +/* Perform digest authentication */ static mhdrslt webu_mhd_digest(struct webui_ctx *webui) { - /* Perform the digest authentication. This function gets called a couple of + /* This function gets called a couple of * times by MHD during the authentication process. */ int retcd; @@ -1382,7 +365,7 @@ static mhdrslt webu_mhd_digest(struct webui_ctx *webui) /* Check for valid user name */ if (mystrne(user, webui->auth_user)) { MOTION_LOG(ALR, TYPE_STREAM, NO_ERRNO - ,_("Failed authentication from %s"), webui->clientip); + ,_("Failed authentication from %s"), webui->clientip.c_str()); if (user != NULL) { free(user); } @@ -1398,28 +381,31 @@ static mhdrslt webu_mhd_digest(struct webui_ctx *webui) if (retcd == MHD_NO) { MOTION_LOG(ALR, TYPE_STREAM, NO_ERRNO - ,_("Failed authentication from %s"), webui->clientip); + ,_("Failed authentication from %s"), webui->clientip.c_str()); } if ( (retcd == MHD_INVALID_NONCE) || (retcd == MHD_NO) ) { return webu_mhd_digest_fail(webui, retcd); } - webui->authenticated = TRUE; + webui->authenticated = true; return MHD_YES; } +/* Create a authorization denied response to user*/ static mhdrslt webu_mhd_basic_fail(struct webui_ctx *webui) { - /* Create a denied response to user*/ struct MHD_Response *response; int retcd; - webui->authenticated = FALSE; + webui->authenticated = false; - response = MHD_create_response_from_buffer(strlen(webui->auth_denied) - ,(void *)webui->auth_denied, MHD_RESPMEM_PERSISTENT); + webui->resp_page = "Access denied" + "Access denied"; + + response = MHD_create_response_from_buffer(webui->resp_page.length() + ,(void *)webui->resp_page.c_str(), MHD_RESPMEM_PERSISTENT); if (response == NULL) { return MHD_NO; @@ -1437,9 +423,9 @@ static mhdrslt webu_mhd_basic_fail(struct webui_ctx *webui) } +/* Perform Basic Authentication. */ static mhdrslt webu_mhd_basic(struct webui_ctx *webui) { - /* Perform Basic Authentication. */ char *user, *pass; pass = NULL; @@ -1454,7 +440,7 @@ static mhdrslt webu_mhd_basic(struct webui_ctx *webui) if ((mystrne(user, webui->auth_user)) || (mystrne(pass, webui->auth_pass))) { MOTION_LOG(ALR, TYPE_STREAM, NO_ERRNO - ,_("Failed authentication from %s"),webui->clientip); + ,_("Failed authentication from %s"),webui->clientip.c_str()); webu_free_var(user); webu_free_var(pass); return webu_mhd_basic_fail(webui); @@ -1463,67 +449,44 @@ static mhdrslt webu_mhd_basic(struct webui_ctx *webui) webu_free_var(user); webu_free_var(pass); - webui->authenticated = TRUE; + webui->authenticated = true; return MHD_YES; } -static void webu_mhd_auth_parse(struct webui_ctx *webui, int ctrl) +/* Parse apart the user:pass provided*/ +static void webu_mhd_auth_parse(struct webui_ctx *webui) { int auth_len; char *col_pos; - /* Parse apart the user:pass provided*/ webu_free_var(webui->auth_user); webu_free_var(webui->auth_pass); - if (ctrl) { - auth_len = webui->cam->conf->webcontrol_authentication.length(); - col_pos =(char*) strstr(webui->cam->conf->webcontrol_authentication.c_str() ,":"); - if (col_pos == NULL) { - webui->auth_user = (char*)mymalloc(auth_len+1); - webui->auth_pass = (char*)mymalloc(2); - snprintf(webui->auth_user, auth_len + 1, "%s" - ,webui->cam->conf->webcontrol_authentication.c_str()); - snprintf(webui->auth_pass, 2, "%s",""); - } else { - webui->auth_user = (char*)mymalloc(auth_len - strlen(col_pos) + 1); - webui->auth_pass =(char*)mymalloc(strlen(col_pos)); - snprintf(webui->auth_user, auth_len - strlen(col_pos) + 1, "%s" - ,webui->cam->conf->webcontrol_authentication.c_str()); - snprintf(webui->auth_pass, strlen(col_pos), "%s", col_pos + 1); - } + auth_len = webui->motapp->cam_list[0]->conf->webcontrol_authentication.length(); + col_pos =(char*) strstr(webui->motapp->cam_list[0]->conf->webcontrol_authentication.c_str() ,":"); + if (col_pos == NULL) { + webui->auth_user = (char*)mymalloc(auth_len+1); + webui->auth_pass = (char*)mymalloc(2); + snprintf(webui->auth_user, auth_len + 1, "%s" + ,webui->motapp->cam_list[0]->conf->webcontrol_authentication.c_str()); + snprintf(webui->auth_pass, 2, "%s",""); } else { - auth_len = strlen(webui->cam->conf->stream_authentication.c_str()); - col_pos =(char*) strstr(webui->cam->conf->stream_authentication.c_str(),":"); - if (col_pos == NULL) { - webui->auth_user = (char*)mymalloc(auth_len+1); - webui->auth_pass = (char*)mymalloc(2); - snprintf(webui->auth_user, auth_len + 1, "%s" - ,webui->cam->conf->stream_authentication.c_str()); - snprintf(webui->auth_pass, 2, "%s",""); - } else { - webui->auth_user = (char*)mymalloc(auth_len - strlen(col_pos) + 1); - webui->auth_pass = (char*)mymalloc(strlen(col_pos)); - snprintf(webui->auth_user, auth_len - strlen(col_pos) + 1, "%s" - ,webui->cam->conf->stream_authentication.c_str()); - snprintf(webui->auth_pass, strlen(col_pos), "%s", col_pos + 1); - } + webui->auth_user = (char*)mymalloc(auth_len - strlen(col_pos) + 1); + webui->auth_pass =(char*)mymalloc(strlen(col_pos)); + snprintf(webui->auth_user, auth_len - strlen(col_pos) + 1, "%s" + ,webui->motapp->cam_list[0]->conf->webcontrol_authentication.c_str()); + snprintf(webui->auth_pass, strlen(col_pos), "%s", col_pos + 1); } } -static mhdrslt webu_mhd_auth(struct webui_ctx *webui, int ctrl) +/* Initialize for authorization */ +static mhdrslt webu_mhd_auth(struct webui_ctx *webui) { - - /* Set everything up for calling the authentication functions */ unsigned int rand1,rand2; - snprintf(webui->auth_denied, WEBUI_LEN_RESP, "%s" - ,"Access denied" - "Access denied"); - srand(time(NULL)); rand1 = (unsigned int)(42000000.0 * rand() / (RAND_MAX + 1.0)); rand2 = (unsigned int)(42000000.0 * rand() / (RAND_MAX + 1.0)); @@ -1531,95 +494,54 @@ static mhdrslt webu_mhd_auth(struct webui_ctx *webui, int ctrl) snprintf(webui->auth_realm, WEBUI_LEN_PARM, "%s","Motion"); - if (ctrl) { - /* Authentication for the webcontrol*/ - if (webui->cam->conf->webcontrol_authentication == "") { - webui->authenticated = TRUE; - if (webui->cam->conf->webcontrol_auth_method != 0) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("No webcontrol user:pass provided")); - } - return MHD_YES; - } - - if (webui->auth_user == NULL) { - webu_mhd_auth_parse(webui, ctrl); - } - - if (webui->cam->conf->webcontrol_auth_method == 1) { - return webu_mhd_basic(webui); - } else if (webui->cam->conf->webcontrol_auth_method == 2) { - return webu_mhd_digest(webui); - } - - } else { - /* Authentication for the streams */ - if (webui->cam->conf->stream_authentication == "") { - webui->authenticated = TRUE; - if (webui->cam->conf->stream_auth_method != 0) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("No stream user:pass provided")); - } - return MHD_YES; - } - - if (webui->auth_user == NULL) { - webu_mhd_auth_parse(webui, ctrl); - } - - if (webui->cam->conf->stream_auth_method == 1) { - return webu_mhd_basic(webui); - } else if (webui->cam->conf->stream_auth_method == 2) { - return webu_mhd_digest(webui); + if (webui->motapp->cam_list[0]->conf->webcontrol_authentication == "") { + webui->authenticated = true; + if (webui->motapp->cam_list[0]->conf->webcontrol_auth_method != 0) { + MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("No webcontrol user:pass provided")); } + return MHD_YES; } - webui->authenticated = TRUE; + if (webui->auth_user == NULL) { + webu_mhd_auth_parse(webui); + } + + if (webui->motapp->cam_list[0]->conf->webcontrol_auth_method == 1) { + return webu_mhd_basic(webui); + } else if (webui->motapp->cam_list[0]->conf->webcontrol_auth_method == 2) { + return webu_mhd_digest(webui); + } + + + webui->authenticated = true; return MHD_YES; } /* Send the response that we created back to the user. */ -static mhdrslt webu_mhd_send(struct webui_ctx *webui, int ctrl) +static mhdrslt webu_mhd_send(struct webui_ctx *webui) { - /* If the user - * provided a really bad URL, then we couldn't determine which Motion context - * they were wanting. In this situation, we have a webui->cam = NULL and we - * don't know whether it came from a html or text request. In this situation - * we use the MHD defaults and skip adding CORS/Content type. (There isn't any - * Motion context so we can't tell where to look) - * The ctrl parameter is a boolean which just says whether the request is for - * the webcontrol versus stream - */ mhdrslt retcd; struct MHD_Response *response; - response = MHD_create_response_from_buffer (strlen(webui->resp_page) - ,(void *)webui->resp_page, MHD_RESPMEM_PERSISTENT); + response = MHD_create_response_from_buffer(webui->resp_page.length() + ,(void *)webui->resp_page.c_str(), MHD_RESPMEM_PERSISTENT); if (!response) { MOTION_LOG(ERR, TYPE_STREAM, NO_ERRNO, _("Invalid response")); return MHD_NO; } if (webui->cam != NULL) { - if (ctrl) { - if (webui->cam->conf->webcontrol_cors_header != "") { - MHD_add_response_header (response, MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN - , webui->cam->conf->webcontrol_cors_header.c_str()); - } + if (webui->motapp->cam_list[0]->conf->webcontrol_cors_header != "") { + MHD_add_response_header (response, MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN + , webui->motapp->cam_list[0]->conf->webcontrol_cors_header.c_str()); + } - if (webui->resptype == 0) { - MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); - } else if (webui->resptype == 1) { - MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/plain;"); - } else if (webui->resptype == 2) { - MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "application/json;"); - } else { - MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); - } + if (webui->resp_type == WEBUI_RESP_TEXT) { + MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/plain;"); + } else if (webui->resp_type == WEBUI_RESP_JSON) { + MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "application/json;"); } else { - if (webui->cam->conf->stream_cors_header !="") { - MHD_add_response_header (response, MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN - , webui->cam->conf->stream_cors_header.c_str()); - } MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html"); } } @@ -1630,71 +552,24 @@ static mhdrslt webu_mhd_send(struct webui_ctx *webui, int ctrl) return retcd; } -/* Assign the type of stream that is being answered*/ -static void webu_answer_strm_type(struct webui_ctx *webui) -{ - if ((mystreq(webui->uri_cmd1,"stream")) || - (mystreq(webui->uri_camid,"stream")) || - (strlen(webui->uri_camid) == 0)) { - webui->cnct_type = WEBUI_CNCT_FULL; - - } else if ((mystreq(webui->uri_cmd1,"substream")) || - (mystreq(webui->uri_camid,"substream"))) { - webui->cnct_type = WEBUI_CNCT_SUB; - - } else if ((mystreq(webui->uri_cmd1,"motion")) || - (mystreq(webui->uri_camid,"motion"))) { - webui->cnct_type = WEBUI_CNCT_MOTION; - - } else if ((mystreq(webui->uri_cmd1,"source")) || - (mystreq(webui->uri_camid,"source"))) { - webui->cnct_type = WEBUI_CNCT_SOURCE; - - } else if ((mystreq(webui->uri_cmd1,"secondary")) || - (mystreq(webui->uri_camid,"secondary"))) { - if (webui->cam->algsec_inuse) { - webui->cnct_type = WEBUI_CNCT_SECONDARY; - } else { - webui->cnct_type = WEBUI_CNCT_UNKNOWN; - } - - } else if ((mystreq(webui->uri_cmd1,"current")) || - (mystreq(webui->uri_camid,"current"))) { - webui->cnct_type = WEBUI_CNCT_STATIC; - - } else if ((strlen(webui->uri_camid) > 0) && - (strlen(webui->uri_cmd1) == 0)) { - webui->cnct_type = WEBUI_CNCT_FULL; - - } else { - webui->cnct_type = WEBUI_CNCT_UNKNOWN; - } - -} /* Process the post data command */ -static mhdrslt webu_answer_ctrl_post(struct webui_ctx *webui) +static mhdrslt webu_answer_post(struct webui_ctx *webui) { mhdrslt retcd; - int indx; - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,"processing post"); + MOTION_LOG(DBG, TYPE_STREAM, NO_ERRNO ,"processing post"); - /* TODO: Handle more commands sent from the web page */ + webu_post_main(webui); - if (webui->post_cmd == 1) { - for (indx = 0; indx < webui->post_sz; indx++) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,"key: %s value: %s size: %ld " - , webui->post_info[indx].key_nm - , webui->post_info[indx].key_val - , webui->post_info[indx].key_sz - ); - } + if (webui->motapp->cam_list[0]->conf->webcontrol_interface == 3) { + webu_html_user(webui); + } else { + webu_html_page(webui); } - webu_html_main(webui); - retcd = webu_mhd_send(webui, true); + retcd = webu_mhd_send(webui); if (retcd == MHD_NO) { MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,"send post page failed"); } @@ -1759,19 +634,14 @@ static mhdrslt webu_iterate_post (void *ptr, enum MHD_ValueKind kind , const char *key, const char *filename, const char *content_type , const char *transfer_encoding, const char *data, uint64_t off, size_t datasz) { - struct webui_ctx *webui = (webui_ctx *)ptr; - (void) kind; /* Unused. Silent compiler warning. */ - (void) filename; /* Unused. Silent compiler warning. */ - (void) content_type; /* Unused. Silent compiler warning. */ - (void) transfer_encoding; /* Unused. Silent compiler warning. */ - (void) off; /* Unused. Silent compiler warning. */ - int indx; + (void) kind; + (void) filename; + (void) content_type; + (void) transfer_encoding; + (void) off; - if (mystreq(key, "cmdid")) { - webui->post_cmd = atoi(data); - } else if (mystreq(key, "trailer") && (datasz ==0)) { - return MHD_YES; - } + struct webui_ctx *webui = (webui_ctx *)ptr; + int indx; for (indx=0; indx < webui->post_sz; indx++) { if (mystreq(webui->post_info[indx].key_nm, key)) { @@ -1787,17 +657,17 @@ static mhdrslt webu_iterate_post (void *ptr, enum MHD_ValueKind kind return MHD_YES; } - -static mhdrslt webu_answer_ctrl_get(struct webui_ctx *webui) +/* Answer the get request from the user */ +static mhdrslt webu_answer_get(struct webui_ctx *webui) { int retcd; - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,"processing get"); + MOTION_LOG(DBG, TYPE_STREAM, NO_ERRNO ,"processing get"); /* Throw bad URLS back to user*/ - if ((webui->cam == NULL) || (strlen(webui->url) == 0)) { - webu_badreq(webui); - retcd = webu_mhd_send(webui, FALSE); + if ((webui->cam == NULL) || (webui->url.length() == 0)) { + webu_html_badreq(webui); + retcd = webu_mhd_send(webui); return retcd; } @@ -1806,35 +676,48 @@ static mhdrslt webu_answer_ctrl_get(struct webui_ctx *webui) return MHD_NO; } - if (strlen(webui->clientip) == 0) { + if (webui->clientip.length() == 0) { webu_clientip(webui); } - webu_hostname(webui, TRUE); + webu_hostname(webui); if (!webui->authenticated) { - retcd = webu_mhd_auth(webui, TRUE); + retcd = webu_mhd_auth(webui); if (!webui->authenticated) { return retcd; } } - if ((webui->motapp->cam_list[0]->conf->webcontrol_interface == 0) || - (webui->motapp->cam_list[0]->conf->webcontrol_interface == 3)) { - webu_html_main(webui); + retcd = MHD_NO; + if ((webui->uri_cmd1 == "mjpg") || + (webui->uri_cmd1 == "static")) { - } else if ((webui->motapp->cam_list[0]->conf->webcontrol_interface == 1) || - (webui->motapp->cam_list[0]->conf->webcontrol_interface == 2)) { - webu_text_main(webui); + retcd = webu_stream_main(webui); + if (retcd == MHD_NO) { + webu_html_badreq(webui); + retcd = webu_mhd_send(webui); + } - } else { /* Default */ - webu_html_main(webui); + } else if ((webui->uri_camid == "config.json") || + (webui->uri_cmd1 == "config.json")) { + webu_json_config(webui); + retcd = webu_mhd_send(webui); + if (retcd == MHD_NO) { + MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("send page failed.")); + } - } + } else { + if (webui->motapp->cam_list[0]->conf->webcontrol_interface == 3) { + webu_html_user(webui); + } else { + webu_html_page(webui); + } - retcd = webu_mhd_send(webui, TRUE); - if (retcd == MHD_NO) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("send page failed.")); + retcd = webu_mhd_send(webui); + if (retcd == MHD_NO) { + MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("send page failed.")); + } } return retcd; @@ -1842,33 +725,29 @@ static mhdrslt webu_answer_ctrl_get(struct webui_ctx *webui) } /* Answer the connection request for the webcontrol*/ -static mhdrslt webu_answer_ctrl(void *cls, struct MHD_Connection *connection, const char *url +static mhdrslt webu_answer(void *cls, struct MHD_Connection *connection, const char *url , const char *method, const char *version, const char *upload_data, size_t *upload_data_size , void **ptr) { - mhdrslt retcd; - struct webui_ctx *webui =(struct webui_ctx *) *ptr; - - /* Eliminate compiler warnings */ (void)cls; (void)url; (void)version; (void)upload_data; (void)upload_data_size; - /* Per MHD docs, this is called twice and we should process the second call */ - webui->cnct_type = WEBUI_CNCT_CONTROL; + mhdrslt retcd; + webui_ctx *webui =(struct webui_ctx *) *ptr; - mythreadname_set("wu", 0,NULL); + webui->cnct_type = WEBUI_CNCT_CONTROL; webui->connection = connection; if (webui->mhd_first) { - webui->mhd_first = FALSE; + webui->mhd_first = false; if (mystreq(method,"POST")) { - webui->postprocessor = MHD_create_post_processor (webui->connection - , POSTBUFFERSIZE, webu_iterate_post, (void *)webui); - if (webui->postprocessor == NULL) { + webui->post_processor = MHD_create_post_processor (webui->connection + , WEBUI_POST_BFRSZ, webu_iterate_post, (void *)webui); + if (webui->post_processor == NULL) { return MHD_NO; } webui->cnct_method = WEBUI_METHOD_POST; @@ -1881,177 +760,43 @@ static mhdrslt webu_answer_ctrl(void *cls, struct MHD_Connection *connection, co if (mystreq(method,"POST")) { if (*upload_data_size != 0) { - retcd = MHD_post_process (webui->postprocessor, upload_data, *upload_data_size); + retcd = MHD_post_process (webui->post_processor, upload_data, *upload_data_size); *upload_data_size = 0; } else { - retcd = webu_answer_ctrl_post(webui); + retcd = webu_answer_post(webui); } } else { - retcd = webu_answer_ctrl_get(webui); + retcd = webu_answer_get(webui); } return retcd; } -/* Answer the connection request for a stream */ -static mhdrslt webu_answer_strm(void *cls, struct MHD_Connection *connection, const char *url - , const char *method, const char *version, const char *upload_data, size_t *upload_data_size - , void **ptr) -{ - mhdrslt retcd; - struct webui_ctx *webui =(struct webui_ctx *) *ptr; - - /* Eliminate compiler warnings */ - (void)cls; - (void)url; - (void)version; - (void)upload_data; - (void)upload_data_size; - - /* Per docs, this is called twice and we should process the second call */ - if (webui->mhd_first) { - webui->mhd_first = FALSE; - return MHD_YES; - } - - if (mystrne(method, "GET")) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("Invalid Method requested: %s"),method); - return MHD_NO; - } - - mythreadname_set("st", 0,NULL); - - webui->connection = connection; - - /* Throw bad URLS back to user*/ - if ((webui->cam == NULL) || (strlen(webui->url) == 0)) { - webu_badreq(webui); - retcd = webu_mhd_send(webui, FALSE); - return retcd; - } - - if (webui->cam->finish_cam) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("Shutting down camera")); - return MHD_NO; - } - - - /* Do not answer a request until the motion loop has completed at least once */ - if (webui->cam->passflag == 0) { - return MHD_NO; - } - - if (strlen(webui->clientip) == 0) { - webu_clientip(webui); - } - - webu_hostname(webui, FALSE); - - if (!webui->authenticated) { - retcd = webu_mhd_auth(webui, FALSE); - if (!webui->authenticated) { - return retcd; - } - } - - webu_answer_strm_type(webui); - - if (webui->cnct_type == WEBUI_CNCT_STATIC) { - retcd = webu_stream_static(webui); - if (retcd == MHD_NO) { - webu_badreq(webui); - retcd = webu_mhd_send(webui, FALSE); - } - } else if (webui->cnct_type != WEBUI_CNCT_UNKNOWN) { - retcd = webu_stream_mjpeg(webui); - if (retcd == MHD_NO) { - webu_badreq(webui); - retcd = webu_mhd_send(webui, FALSE); - } - } else { - webu_badreq(webui); - retcd = webu_mhd_send(webui, FALSE); - } - - if (retcd == MHD_NO) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("send page failed %d"),retcd); - } - return retcd; - -} - -/* Initialize the MHD answer when it is the webcontrol or all streams on a single port */ +/* Initialize the MHD answer */ static void *webu_mhd_init(void *cls, const char *uri, struct MHD_Connection *connection) { - /* This is called at the very start of getting a request before the "answer" - * is processed. There are two variations of this and the difference is how - * we call the webu_context_init. When we are processing for the webcontrol or - * the stream port specified in the motion.conf file, we pass into the init function - * the motion application context. The other version of the init is used when the - * user specifies a unique port for each camera. In this situation, the full list - * context is passed in as a null and the context of the camera desired is passed - * instead. - * When this function is processed, we basically only have the URL that the user requested - * so we initialize everything and then parse out the URL to determine what the user is - * asking. - */ - struct ctx_motapp *motapp = (struct ctx_motapp *)cls; struct webui_ctx *webui; int retcd; (void)connection; - /* Set the thread name to connection until we know whether control or stream answers*/ - mythreadname_set("cn", 0,NULL); + mythreadname_set("wc", 0, NULL); - webui =(struct webui_ctx* ) malloc(sizeof(struct webui_ctx)); + webui = new webui_ctx; - webu_context_init(motapp, NULL, webui); - webui->mhd_first = TRUE; + webu_context_init(motapp, webui); - snprintf(webui->url,WEBUI_LEN_URLI,"%s",uri); + webui->mhd_first = true; + + webui->url.assign(uri); retcd = webu_parseurl(webui); if (retcd != 0) { - webu_parseurl_reset(webui); - memset(webui->url,'\0',WEBUI_LEN_URLI); - } - - webu_parms_edit(webui); - - return webui; -} - -/* Initialize the MHD answer when it is a connection for each camera */ -static void *webu_mhd_init_one(void *cls, const char *uri, struct MHD_Connection *connection) -{ - /* This function initializes all the webui variables as we are getting a request. This - * variation of the init is the one used when the user has specified a unique port number - * for each camera. The variation is in how the webu_context_init is invoked. This passes - * in a NULL for the motion app and instead assigns the particular camera context to webui->cam - */ - struct ctx_cam *cam =(struct ctx_cam *) cls; - struct webui_ctx *webui; - int retcd; - - (void)connection; - - /* Set the thread name to connection until we know whether control or stream answers*/ - mythreadname_set("cn", 0,NULL); - - webui =(struct webui_ctx*) malloc(sizeof(struct webui_ctx)); - - webu_context_init(NULL, cam, webui); - webui->mhd_first = TRUE; - - snprintf(webui->url,WEBUI_LEN_URLI,"%s",uri); - - retcd = webu_parseurl(webui); - if (retcd != 0) { - webu_parseurl_reset(webui); - memset(webui->url,'\0',WEBUI_LEN_URLI); + webui->uri_camid = ""; + webui->uri_cmd1 = ""; + webui->url = ""; } webu_parms_edit(webui); @@ -2065,7 +810,6 @@ static void webu_mhd_deinit(void *cls, struct MHD_Connection *connection { struct webui_ctx *webui =(struct webui_ctx *) *con_cls; - /* Eliminate compiler warnings */ (void)connection; (void)cls; (void)toe; @@ -2095,16 +839,11 @@ static void webu_mhd_deinit(void *cls, struct MHD_Connection *connection webui->cam->stream.secondary.cnct_count--; pthread_mutex_unlock(&webui->cam->stream.mutex); - } else if (webui->cnct_type == WEBUI_CNCT_STATIC ) { - pthread_mutex_lock(&webui->cam->stream.mutex); - webui->cam->stream.norm.cnct_count--; - pthread_mutex_unlock(&webui->cam->stream.mutex); - } if (webui != NULL) { if (webui->cnct_method == WEBUI_METHOD_POST) { - MHD_destroy_post_processor (webui->postprocessor); + MHD_destroy_post_processor (webui->post_processor); } webu_context_free(webui); } @@ -2123,14 +862,9 @@ static void webu_mhd_features_basic(struct mhdstart_ctx *mhdst) if (retcd == MHD_YES) { MOTION_LOG(DBG, TYPE_STREAM, NO_ERRNO ,_("Basic authentication: available")); } else { - if ((mhdst->ctrl) && - (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_auth_method == 1)) { + if (mhdst->motapp->cam_list[0]->conf->webcontrol_auth_method == 1) { MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("Basic authentication: disabled")); - mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_auth_method = 0; - } else if ((!mhdst->ctrl) && - (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_auth_method == 1)) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("Basic authentication: disabled")); - mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_auth_method = 0; + mhdst->motapp->cam_list[0]->conf->webcontrol_auth_method = 0; } else { MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO ,_("Basic authentication: disabled")); } @@ -2149,14 +883,9 @@ static void webu_mhd_features_digest(struct mhdstart_ctx *mhdst) if (retcd == MHD_YES) { MOTION_LOG(DBG, TYPE_STREAM, NO_ERRNO ,_("Digest authentication: available")); } else { - if ((mhdst->ctrl) && - (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_auth_method == 2)) { + if (mhdst->motapp->cam_list[0]->conf->webcontrol_auth_method == 2) { MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("Digest authentication: disabled")); - mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_auth_method = 0; - } else if ((!mhdst->ctrl) && - (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_auth_method == 2)) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("Digest authentication: disabled")); - mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_auth_method = 0; + mhdst->motapp->cam_list[0]->conf->webcontrol_auth_method = 0; } else { MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO ,_("Digest authentication: disabled")); } @@ -2192,12 +921,9 @@ static void webu_mhd_features_ipv6(struct mhdstart_ctx *mhdst) static void webu_mhd_features_tls(struct mhdstart_ctx *mhdst) { #if MHD_VERSION < 0x00094400 - if ((mhdst->ctrl) && (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_tls)) { + if (mhdst->motapp->cam_list[0]->conf->webcontrol_tls) { MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO ,_("libmicrohttpd libary too old SSL/TLS disabled")); - mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_tls = 0; - } else if ((!mhdst->ctrl) && (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_tls)) { - MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO ,_("libmicrohttpd libary too old SSL/TLS disabled")); - mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_tls = 0; + mhdst->motapp->cam_list[0]->conf->webcontrol_tls = 0; } #else mhdrslt retcd; @@ -2205,12 +931,9 @@ static void webu_mhd_features_tls(struct mhdstart_ctx *mhdst) if (retcd == MHD_YES) { MOTION_LOG(DBG, TYPE_STREAM, NO_ERRNO ,_("SSL/TLS: available")); } else { - if ((mhdst->ctrl) && (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_tls)) { + if (mhdst->motapp->cam_list[0]->conf->webcontrol_tls) { MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("SSL/TLS: disabled")); - mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_tls = 0; - } else if ((!mhdst->ctrl) && (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_tls)) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO ,_("SSL/TLS: disabled")); - mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_tls = 0; + mhdst->motapp->cam_list[0]->conf->webcontrol_tls = 0; } else { MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO ,_("SSL/TLS: disabled")); } @@ -2231,20 +954,17 @@ static void webu_mhd_features(struct mhdstart_ctx *mhdst) } /* Load a either the key or cert file for MHD*/ -static char *webu_mhd_loadfile(const char *fname) +static std::string webu_mhd_loadfile(std::string fname) { - /* This function loads the requested certificate and key files into memory so we - * can use them as needed if the user wants ssl/tls support. If the user did not - * specify a file in the configuration, then we return NULL. - */ - FILE *infile; - size_t file_size, read_size; - char * file_char; + /* This needs conversion to c++ stream */ + FILE *infile; + size_t file_size, read_size; + char *file_char; + std::string filestr; - if (fname == NULL) { - file_char = NULL; - } else { - infile = fopen(fname, "rb"); + filestr = ""; + if (fname != "") { + infile = fopen(fname.c_str() , "rb"); if (infile != NULL) { fseek(infile, 0, SEEK_END); file_size = ftell(infile); @@ -2254,51 +974,34 @@ static char *webu_mhd_loadfile(const char *fname) read_size = fread(file_char, file_size, 1, infile); if (read_size > 0 ) { file_char[file_size] = 0; + filestr.assign(file_char, file_size); } else { - free(file_char); - file_char = NULL; MOTION_LOG(ERR, TYPE_STREAM, NO_ERRNO ,_("Error reading file for SSL/TLS support.")); } - } else { - file_char = NULL; + free(file_char); } fclose(infile); - } else { - file_char = NULL; } } - return file_char; + return filestr; + } /* Validate that we have the files needed for tls*/ static void webu_mhd_checktls(struct mhdstart_ctx *mhdst) { - if (mhdst->ctrl) { - if (mhdst->motapp->cam_list[0]->conf->webcontrol_tls) { - if ((mhdst->motapp->cam_list[0]->conf->webcontrol_cert == "") || (mhdst->tls_cert == NULL)) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - ,_("SSL/TLS requested but no cert file provided. SSL/TLS disabled")); - mhdst->motapp->cam_list[0]->conf->webcontrol_tls = 0; - } - if ((mhdst->motapp->cam_list[0]->conf->webcontrol_key == "") || (mhdst->tls_key == NULL)) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - ,_("SSL/TLS requested but no key file provided. SSL/TLS disabled")); - mhdst->motapp->cam_list[0]->conf->webcontrol_tls = 0; - } + + if (mhdst->motapp->cam_list[0]->conf->webcontrol_tls) { + if ((mhdst->motapp->cam_list[0]->conf->webcontrol_cert == "") || (mhdst->tls_cert == "")) { + MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO + ,_("SSL/TLS requested but no cert file provided. SSL/TLS disabled")); + mhdst->motapp->cam_list[0]->conf->webcontrol_tls = 0; } - } else { - if (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_tls) { - if ((mhdst->motapp->cam_list[0]->conf->webcontrol_cert == "") || (mhdst->tls_cert == NULL)) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - ,_("SSL/TLS requested but no cert file provided. SSL/TLS disabled")); - mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_tls = 0; - } - if ((mhdst->motapp->cam_list[0]->conf->webcontrol_key == "") || (mhdst->tls_key == NULL)) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - ,_("SSL/TLS requested but no key file provided. SSL/TLS disabled")); - mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_tls = 0; - } + if ((mhdst->motapp->cam_list[0]->conf->webcontrol_key == "") || (mhdst->tls_key == "")) { + MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO + ,_("SSL/TLS requested but no key file provided. SSL/TLS disabled")); + mhdst->motapp->cam_list[0]->conf->webcontrol_tls = 0; } } @@ -2307,24 +1010,10 @@ static void webu_mhd_checktls(struct mhdstart_ctx *mhdst) /* Set the initialization function for MHD to call upon getting a connection */ static void webu_mhd_opts_init(struct mhdstart_ctx *mhdst) { - /* If the connection is related to the webcontrol or the stream specified in the - * motion.conf file, then we pass in the full motion application context. If - * the MHD connection is only going to be for a single camera (a unique port for - * each camera), then we call a different init function which only wants the single - * motion context for that particular camera. - */ - if ((!mhdst->ctrl) && (mhdst->indxthrd != 0)) { - mhdst->mhd_ops[mhdst->mhd_opt_nbr].option = MHD_OPTION_URI_LOG_CALLBACK; - mhdst->mhd_ops[mhdst->mhd_opt_nbr].value = (intptr_t)webu_mhd_init_one; - mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = mhdst->motapp->cam_list[mhdst->indxthrd]; - mhdst->mhd_opt_nbr++; - } else { - mhdst->mhd_ops[mhdst->mhd_opt_nbr].option = MHD_OPTION_URI_LOG_CALLBACK; - mhdst->mhd_ops[mhdst->mhd_opt_nbr].value = (intptr_t)webu_mhd_init; - mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = mhdst->motapp; - mhdst->mhd_opt_nbr++; - } - + mhdst->mhd_ops[mhdst->mhd_opt_nbr].option = MHD_OPTION_URI_LOG_CALLBACK; + mhdst->mhd_ops[mhdst->mhd_opt_nbr].value = (intptr_t)webu_mhd_init; + mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = mhdst->motapp; + mhdst->mhd_opt_nbr++; } /* Set the MHD option on the function to call when the connection closes */ @@ -2340,11 +1029,11 @@ static void webu_mhd_opts_deinit(struct mhdstart_ctx *mhdst) /* Set the MHD option on acceptable connections */ static void webu_mhd_opts_localhost(struct mhdstart_ctx *mhdst) { - if ((mhdst->ctrl) && (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_localhost)) { + if (mhdst->motapp->cam_list[0]->conf->webcontrol_localhost) { if (mhdst->ipv6) { memset(&mhdst->lpbk_ipv6, 0, sizeof(struct sockaddr_in6)); mhdst->lpbk_ipv6.sin6_family = AF_INET6; - mhdst->lpbk_ipv6.sin6_port = htons(mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_port); + mhdst->lpbk_ipv6.sin6_port = htons(mhdst->motapp->cam_list[0]->conf->webcontrol_port); mhdst->lpbk_ipv6.sin6_addr = in6addr_loopback; mhdst->mhd_ops[mhdst->mhd_opt_nbr].option = MHD_OPTION_SOCK_ADDR; @@ -2355,29 +1044,7 @@ static void webu_mhd_opts_localhost(struct mhdstart_ctx *mhdst) } else { memset(&mhdst->lpbk_ipv4, 0, sizeof(struct sockaddr_in)); mhdst->lpbk_ipv4.sin_family = AF_INET; - mhdst->lpbk_ipv4.sin_port = htons(mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_port); - mhdst->lpbk_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - - mhdst->mhd_ops[mhdst->mhd_opt_nbr].option = MHD_OPTION_SOCK_ADDR; - mhdst->mhd_ops[mhdst->mhd_opt_nbr].value = 0; - mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = (struct sockaddr *)(&mhdst->lpbk_ipv4); - mhdst->mhd_opt_nbr++; - } - } else if((!mhdst->ctrl) && (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_localhost)) { - if (mhdst->ipv6) { - memset(&mhdst->lpbk_ipv6, 0, sizeof(struct sockaddr_in6)); - mhdst->lpbk_ipv6.sin6_family = AF_INET6; - mhdst->lpbk_ipv6.sin6_port = htons(mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_port); - mhdst->lpbk_ipv6.sin6_addr = in6addr_loopback; - - mhdst->mhd_ops[mhdst->mhd_opt_nbr].option = MHD_OPTION_SOCK_ADDR; - mhdst->mhd_ops[mhdst->mhd_opt_nbr].value = 0; - mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = (struct sosockaddr *)(&mhdst->lpbk_ipv6); - mhdst->mhd_opt_nbr++; - } else { - memset(&mhdst->lpbk_ipv4, 0, sizeof(struct sockaddr_in)); - mhdst->lpbk_ipv4.sin_family = AF_INET; - mhdst->lpbk_ipv4.sin_port = htons(mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_port); + mhdst->lpbk_ipv4.sin_port = htons(mhdst->motapp->cam_list[0]->conf->webcontrol_port); mhdst->lpbk_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); mhdst->mhd_ops[mhdst->mhd_opt_nbr].option = MHD_OPTION_SOCK_ADDR; @@ -2393,20 +1060,11 @@ static void webu_mhd_opts_localhost(struct mhdstart_ctx *mhdst) static void webu_mhd_opts_digest(struct mhdstart_ctx *mhdst) { - if (((mhdst->ctrl) && (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_auth_method == 2)) || - ((!mhdst->ctrl) && (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_auth_method == 2))) { + if (mhdst->motapp->cam_list[0]->conf->webcontrol_auth_method == 2) { mhdst->mhd_ops[mhdst->mhd_opt_nbr].option = MHD_OPTION_DIGEST_AUTH_RANDOM; - if (mhdst->ctrl) { - mhdst->mhd_ops[mhdst->mhd_opt_nbr].value = sizeof(mhdst->motapp->webcontrol_digest_rand); - mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = mhdst->motapp->webcontrol_digest_rand; - } else if (mhdst->indxthrd == 0) { - mhdst->mhd_ops[mhdst->mhd_opt_nbr].value = sizeof(mhdst->motapp->webstream_digest_rand); - mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = mhdst->motapp->webstream_digest_rand; - } else { - mhdst->mhd_ops[mhdst->mhd_opt_nbr].value = sizeof(mhdst->motapp->cam_list[mhdst->indxthrd]->stream.digest_rand); - mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = mhdst->motapp->cam_list[mhdst->indxthrd]->stream.digest_rand; - } + mhdst->mhd_ops[mhdst->mhd_opt_nbr].value = sizeof(mhdst->motapp->webcontrol_digest_rand); + mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = mhdst->motapp->webcontrol_digest_rand; mhdst->mhd_opt_nbr++; mhdst->mhd_ops[mhdst->mhd_opt_nbr].option = MHD_OPTION_NONCE_NC_SIZE; @@ -2425,17 +1083,16 @@ static void webu_mhd_opts_digest(struct mhdstart_ctx *mhdst) /* Set the MHD options needed when we want TLS connections */ static void webu_mhd_opts_tls(struct mhdstart_ctx *mhdst) { - if ((( mhdst->ctrl) && (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_tls)) || - ((!mhdst->ctrl) && (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_tls))) { + if (mhdst->motapp->cam_list[0]->conf->webcontrol_tls) { mhdst->mhd_ops[mhdst->mhd_opt_nbr].option = MHD_OPTION_HTTPS_MEM_CERT; mhdst->mhd_ops[mhdst->mhd_opt_nbr].value = 0; - mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = mhdst->tls_cert; + mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = (void *)mhdst->tls_cert.c_str(); mhdst->mhd_opt_nbr++; mhdst->mhd_ops[mhdst->mhd_opt_nbr].option = MHD_OPTION_HTTPS_MEM_KEY; mhdst->mhd_ops[mhdst->mhd_opt_nbr].value = 0; - mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = mhdst->tls_key; + mhdst->mhd_ops[mhdst->mhd_opt_nbr].ptr_value = (void *)mhdst->tls_key.c_str(); mhdst->mhd_opt_nbr++; } @@ -2474,56 +1131,24 @@ static void webu_mhd_flags(struct mhdstart_ctx *mhdst) mhdst->mhd_flags = mhdst->mhd_flags | MHD_USE_DUAL_STACK; } - if ((mhdst->ctrl) && (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->webcontrol_tls)) { - mhdst->mhd_flags = mhdst->mhd_flags | MHD_USE_SSL; - } else if ((!mhdst->ctrl) && (mhdst->motapp->cam_list[mhdst->indxthrd]->conf->stream_tls)) { + if (mhdst->motapp->cam_list[0]->conf->webcontrol_tls) { mhdst->mhd_flags = mhdst->mhd_flags | MHD_USE_SSL; } } -/* Print to log what ports and urls are being used for the streams*/ -static void webu_strm_ntc(struct ctx_cam **camlst, int indxthrd) -{ - int indx; - - if (indxthrd == 0 ) { - if (camlst[1] != NULL) { - indx = 1; - while (camlst[indx] != NULL) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - ,_("Started camera %d stream on port/camera_id %d/%d") - ,camlst[indx]->camera_id - ,camlst[indxthrd]->conf->stream_port - ,camlst[indx]->camera_id); - indx++; - } - } else { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - ,_("Started camera %d stream on port %d") - ,camlst[indxthrd]->camera_id,camlst[indxthrd]->conf->stream_port); - } - } else { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - ,_("Started camera %d stream on port %d") - ,camlst[indxthrd]->camera_id,camlst[indxthrd]->conf->stream_port); - } -} - /* Start the webcontrol */ -static void webu_init_ctrl(struct ctx_motapp *motapp) +static void webu_init_webcontrol(struct ctx_motapp *motapp) { struct mhdstart_ctx mhdst; unsigned int randnbr; MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - ,_("Starting webcontrol on port %d") - ,motapp->cam_list[0]->conf->webcontrol_port); + , _("Starting webcontrol on port %d") + , motapp->cam_list[0]->conf->webcontrol_port); - mhdst.tls_cert = webu_mhd_loadfile(motapp->cam_list[0]->conf->webcontrol_cert.c_str()); - mhdst.tls_key = webu_mhd_loadfile(motapp->cam_list[0]->conf->webcontrol_key.c_str()); - mhdst.ctrl = TRUE; - mhdst.indxthrd = 0; + mhdst.tls_cert = webu_mhd_loadfile(motapp->cam_list[0]->conf->webcontrol_cert); + mhdst.tls_key = webu_mhd_loadfile(motapp->cam_list[0]->conf->webcontrol_key); mhdst.motapp = motapp; mhdst.ipv6 = motapp->cam_list[0]->conf->webcontrol_ipv6; @@ -2538,12 +1163,13 @@ static void webu_init_ctrl(struct ctx_motapp *motapp) webu_mhd_opts(&mhdst); webu_mhd_flags(&mhdst); - motapp->webcontrol_daemon = MHD_start_daemon (mhdst.mhd_flags - ,motapp->cam_list[0]->conf->webcontrol_port - ,NULL, NULL - ,&webu_answer_ctrl, motapp->cam_list - ,MHD_OPTION_ARRAY, mhdst.mhd_ops - ,MHD_OPTION_END); + motapp->webcontrol_daemon = MHD_start_daemon ( + mhdst.mhd_flags + , motapp->cam_list[0]->conf->webcontrol_port + , NULL, NULL + , &webu_answer, motapp->cam_list + , MHD_OPTION_ARRAY, mhdst.mhd_ops + , MHD_OPTION_END); free(mhdst.mhd_ops); if (motapp->webcontrol_daemon == NULL) { @@ -2554,188 +1180,24 @@ static void webu_init_ctrl(struct ctx_motapp *motapp) ,motapp->cam_list[0]->conf->webcontrol_port); } - webu_free_var(mhdst.tls_cert); - webu_free_var(mhdst.tls_key); - return; } -/* Start the webstreams for all cameras on a single port */ -static void webu_init_strm_oneport(struct ctx_motapp *motapp) -{ - struct mhdstart_ctx mhdst; - unsigned int randnbr; - - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - , _("Starting all camera streams on port %d") - , motapp->cam_list[0]->conf->stream_port); - - mhdst.tls_cert = webu_mhd_loadfile(motapp->cam_list[0]->conf->webcontrol_cert.c_str()); - mhdst.tls_key = webu_mhd_loadfile(motapp->cam_list[0]->conf->webcontrol_key.c_str()); - mhdst.ctrl = FALSE; - mhdst.indxthrd = 0; - mhdst.motapp = motapp; - mhdst.ipv6 = motapp->cam_list[0]->conf->webcontrol_ipv6; - - - /* Set the rand number for webstream digest if needed */ - srand(time(NULL)); - randnbr = (unsigned int)(42000000.0 * rand() / (RAND_MAX + 1.0)); - snprintf(motapp->webstream_digest_rand - ,sizeof(motapp->webstream_digest_rand),"%d",randnbr); - - mhdst.mhd_ops=(struct MHD_OptionItem*)mymalloc(sizeof(struct MHD_OptionItem)*WEBUI_MHD_OPTS); - webu_mhd_features(&mhdst); - webu_mhd_opts(&mhdst); - webu_mhd_flags(&mhdst); - - motapp->webstream_daemon = MHD_start_daemon ( - mhdst.mhd_flags - , motapp->cam_list[mhdst.indxthrd]->conf->stream_port - , NULL, NULL - , &webu_answer_strm, motapp->cam_list - , MHD_OPTION_ARRAY, mhdst.mhd_ops - , MHD_OPTION_END); - free(mhdst.mhd_ops); - if (motapp->webstream_daemon == NULL) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - , _("Unable to start stream for cameras")); - } else { - webu_strm_ntc(motapp->cam_list, mhdst.indxthrd); - } - webu_free_var(mhdst.tls_cert); - webu_free_var(mhdst.tls_key); - - -} - -/* Start the webstream with each camera on a different port*/ -static void webu_init_strm_multport(struct ctx_motapp *motapp, int indx) -{ - struct mhdstart_ctx mhdst; - unsigned int randnbr; - - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - , _("Starting camera %d stream on port %d") - , motapp->cam_list[indx]->camera_id - , motapp->cam_list[indx]->conf->stream_port); - - mhdst.tls_cert = webu_mhd_loadfile(motapp->cam_list[0]->conf->webcontrol_cert.c_str()); - mhdst.tls_key = webu_mhd_loadfile(motapp->cam_list[0]->conf->webcontrol_key.c_str()); - mhdst.ctrl = FALSE; - mhdst.indxthrd = indx; - mhdst.motapp = motapp; - mhdst.ipv6 = motapp->cam_list[0]->conf->webcontrol_ipv6; - - /* Set the rand number for webstream digest if needed */ - srand(time(NULL)); - randnbr = (unsigned int)(42000000.0 * rand() / (RAND_MAX + 1.0)); - snprintf(motapp->cam_list[mhdst.indxthrd]->stream.digest_rand - ,sizeof(motapp->cam_list[mhdst.indxthrd]->stream.digest_rand),"%d",randnbr); - - mhdst.mhd_ops=(struct MHD_OptionItem*)mymalloc(sizeof(struct MHD_OptionItem)*WEBUI_MHD_OPTS); - webu_mhd_features(&mhdst); - webu_mhd_opts(&mhdst); - webu_mhd_flags(&mhdst); - - motapp->cam_list[mhdst.indxthrd]->stream.daemon = MHD_start_daemon ( - mhdst.mhd_flags - , motapp->cam_list[mhdst.indxthrd]->conf->stream_port - , NULL, NULL - , &webu_answer_strm, motapp->cam_list[mhdst.indxthrd] - , MHD_OPTION_ARRAY, mhdst.mhd_ops - , MHD_OPTION_END); - - free(mhdst.mhd_ops); - if (motapp->cam_list[mhdst.indxthrd]->stream.daemon == NULL) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - , _("Unable to start stream for camera %d") - , motapp->cam_list[mhdst.indxthrd]->camera_id); - } else { - webu_strm_ntc(motapp->cam_list,mhdst.indxthrd); - } - - webu_free_var(mhdst.tls_cert); - webu_free_var(mhdst.tls_key); - -} - -/*Perform validation of the user specified ports for streams and webcontrol*/ -static void webu_init_ports(struct ctx_motapp *motapp) -{ - int indx, indx2; - - if (motapp->cam_list[0]->conf->webcontrol_port != 0) { - indx = 0; - while (motapp->cam_list[indx] != NULL){ - if ((motapp->cam_list[0]->conf->webcontrol_port == motapp->cam_list[indx]->conf->webcontrol_port) - && (indx > 0)) { - motapp->cam_list[indx]->conf->webcontrol_port = 0; - } - - if (motapp->cam_list[0]->conf->webcontrol_port == motapp->cam_list[indx]->conf->stream_port) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - , _("Duplicate port requested %d") - , motapp->cam_list[indx]->conf->stream_port); - motapp->cam_list[indx]->conf->stream_port = 0; - } - - indx++; - } - } - - /* Now check on the stream ports */ - indx = 0; - while (motapp->cam_list[indx] != NULL){ - if (motapp->cam_list[indx]->conf->stream_port != 0) { - indx2 = indx + 1; - while (motapp->cam_list[indx2] != NULL){ - if (motapp->cam_list[indx]->conf->stream_port == motapp->cam_list[indx2]->conf->stream_port) { - if (indx != 0) { - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - , _("Duplicate port requested %d") - , motapp->cam_list[indx2]->conf->stream_port); - } - motapp->cam_list[indx2]->conf->stream_port = 0; - } - indx2++; - } - } - indx++; - } -} - -/* Shut down the webcontrol and streams */ +/* Shut down the webcontrol */ void webu_deinit(struct ctx_motapp *motapp) { - int indx; if (motapp->webcontrol_daemon != NULL) { - motapp->webcontrol_finish = TRUE; + motapp->webcontrol_finish = true; MHD_stop_daemon (motapp->webcontrol_daemon); } - if (motapp->webstream_daemon != NULL) { - motapp->webstream_finish = TRUE; - MHD_stop_daemon (motapp->webstream_daemon); - } - - - indx = 0; - while (motapp->cam_list[indx] != NULL){ - if (motapp->cam_list[indx]->stream.daemon != NULL) { - MHD_stop_daemon (motapp->cam_list[indx]->stream.daemon); - } - motapp->cam_list[indx]->stream.daemon = NULL; - indx++; - } } /* Start the webcontrol and streams */ void webu_init(struct ctx_motapp *motapp) { struct sigaction act; - int indx; /* We need to block some signals otherwise MHD will not function correctly. */ /* set signal handlers TO IGNORE */ @@ -2746,36 +1208,11 @@ void webu_init(struct ctx_motapp *motapp) sigaction(SIGCHLD, &act, NULL); motapp->webcontrol_daemon = NULL; - motapp->webcontrol_finish = FALSE; + motapp->webcontrol_finish = false; - motapp->webstream_daemon = NULL; - motapp->webstream_finish = FALSE; - - indx = 0; - while (motapp->cam_list[indx] != NULL) { - motapp->cam_list[indx]->stream.daemon = NULL; - motapp->cam_list[indx]->stream.finish = FALSE; - indx++; - } - - webu_init_ports(motapp); - - /* Start the streams */ - if (motapp->cam_list[0]->conf->stream_port != 0 ) { - webu_init_strm_oneport(motapp); - } else { - indx = 1; - while (motapp->cam_list[indx] != NULL) { - if (motapp->cam_list[indx]->conf->stream_port != 0 ) { - webu_init_strm_multport(motapp, indx); - } - indx++; - } - } - - /* Start the webcontrol */ + /* Start the webcontrol */ if (motapp->cam_list[0]->conf->webcontrol_port != 0 ) { - webu_init_ctrl(motapp); + webu_init_webcontrol(motapp); } return; diff --git a/src/webu.hpp b/src/webu.hpp index 16355d36..82a060a1 100644 --- a/src/webu.hpp +++ b/src/webu.hpp @@ -25,11 +25,13 @@ #define WEBUI_LEN_URLI 512 /* Maximum URL permitted */ #define WEBUI_LEN_RESP 1024 /* Initial response size */ #define WEBUI_MHD_OPTS 10 /* Maximum number of options permitted for MHD */ - #define WEBUI_LEN_LNK 15 /* Maximum length for chars in strminfo */ - #define WEBUI_METHOD_GET 0 /* The method for the web interface */ - #define WEBUI_METHOD_POST 1 /* The method for the web interface */ - #define POSTBUFFERSIZE 512 + #define WEBUI_POST_BFRSZ 512 + + enum WEBUI_METHOD { + WEBUI_METHOD_GET = 0, + WEBUI_METHOD_POST = 1 + }; enum WEBUI_CNCT { WEBUI_CNCT_CONTROL = 0, @@ -37,73 +39,67 @@ WEBUI_CNCT_SUB = 2, WEBUI_CNCT_MOTION = 3, WEBUI_CNCT_SOURCE = 4, - WEBUI_CNCT_STATIC = 5, - WEBUI_CNCT_SECONDARY = 6, + WEBUI_CNCT_SECONDARY = 5, WEBUI_CNCT_UNKNOWN = 99 }; - struct ctx_key { - char *key_nm; /* Name of the key item */ - char *key_val; /* Value of the key item */ - size_t key_sz; /* The size of the value */ + enum WEBUI_RESP { + WEBUI_RESP_HTML = 0, + WEBUI_RESP_JSON = 1, + WEBUI_RESP_TEXT = 2 }; + struct ctx_key { + char *key_nm; /* Name of the key item */ + char *key_val; /* Value of the key item */ + size_t key_sz; /* The size of the value */ + }; struct webui_ctx { - char *url; /* The URL sent from the client */ - char *uri_camid; /* Parsed thread number from the url*/ - char *uri_cmd1; /* Parsed command(action) from the url*/ - char *uri_cmd2; /* Parsed command (set) from the url*/ - char *uri_parm1; /* Parameter 1 for the command */ - char *uri_value1; /* The value for parameter 1*/ - char *uri_parm2; /* Parameter 2 for the command */ - char *uri_value2; /* The value for parameter 2*/ + std::string url; /* The URL sent from the client */ + std::string uri_camid; /* Parsed camera number from the url eg /camid/cmd1/cmd2 */ + std::string uri_cmd1; /* Parsed command1 from the url eg /camid/cmd1/cmd2 */ + std::string uri_cmd2; /* Parsed command2 from the url eg /camid/cmd1/cmd2 */ - char *hostname; /* Host name provided from header content*/ - char hostproto[6]; /* Protocol for host http or https */ - char *clientip; /* IP of the connecting client */ - char *auth_denied; /* Denied access response to user*/ - char *auth_opaque; /* Opaque string for digest authentication*/ - char *auth_realm; /* Realm string for digest authentication*/ - char *auth_user; /* Parsed user from config authentication string*/ - char *auth_pass; /* Parsed password from config authentication string*/ - int authenticated; /* Boolean for whether authentication has been passed */ + std::string clientip; /* IP of the connecting client */ + std::string hostfull; /* Full http name for host with port number */ - int resptype; /* indicator for the type of response to provide. Html, text, json */ - int cam_count; /* Count of the number of cameras*/ - int cam_threads; /* Count of the number of camera threads running*/ - char *lang; /* Two character abbreviation for locale language*/ - char *lang_full; /* Five character abbreviation for language-country*/ - int thread_nbr; /* Thread number provided from the uri */ - char *text_eol; /* End of line for text interface either
or "" */ - enum WEBUI_CNCT cnct_type; /* Type of connection we are processing */ + char *auth_opaque; /* Opaque string for digest authentication*/ + char *auth_realm; /* Realm string for digest authentication*/ + char *auth_user; /* Parsed user from config authentication string*/ + char *auth_pass; /* Parsed password from config authentication string*/ + int authenticated; /* Boolean for whether authentication has been passed */ + + std::string resp_page; /* The response that will be sent */ + char *resp_image; /* Response image to provide to user */ + int resp_type; /* indicator for the type of response to provide. */ + size_t resp_size; /* The allocated size of the response */ + size_t resp_used; /* The amount of the response page used */ + + int cam_count; /* Count of the number of cameras*/ + int cam_threads; /* Count of the number of camera threads running*/ + std::string lang; /* Two character abbreviation for locale language*/ + int threadnbr; /* Thread number provided from the uri */ + enum WEBUI_CNCT cnct_type; /* Type of connection we are processing */ int post_sz; /* The number of entries in the post info */ - int post_cmd; /* The command sent with the post */ + std::string post_cmd; /* The command sent with the post */ struct ctx_key *post_info; /* Structure of the entries provided from the post data */ - int cnct_method; /* Connection method. Get or Post */ - struct MHD_PostProcessor *postprocessor; /* Processor for handling Post method connections */ + struct MHD_PostProcessor *post_processor; /* Processor for handling Post method connections */ - char *resp_page; /* The response that will be sent */ - size_t resp_size; /* The allocated size of the response */ - size_t resp_used; /* The amount of the response page used */ - uint64_t stream_pos; /* Stream position of sent image */ - int stream_fps; /* Stream rate per second */ - struct timespec time_last; /* Keep track of processing time for stream thread*/ - int mhd_first; /* Boolean for whether it is the first connection*/ + enum WEBUI_METHOD cnct_method; /* Connection method. Get or Post */ - struct MHD_Connection *connection; /* The MHD connection value from the client */ - struct ctx_motapp *motapp; - struct ctx_cam *cam; /* The ctx_cam information for the camera requested */ + uint64_t stream_pos; /* Stream position of sent image */ + int stream_fps; /* Stream rate per second */ + struct timespec time_last; /* Keep track of processing time for stream thread*/ + int mhd_first; /* Boolean for whether it is the first connection*/ + struct MHD_Connection *connection; /* The MHD connection value from the client */ + struct ctx_motapp *motapp; /* The motionplus context pointer */ + struct ctx_cam *cam; /* The ctx_cam information for the camera requested */ }; void webu_init(struct ctx_motapp *motapp); void webu_deinit(struct ctx_motapp *motapp); - void webu_process_action(struct webui_ctx *webui); - int webu_process_config(struct webui_ctx *webui); - int webu_process_json(struct webui_ctx *webui); - int webu_process_track(struct webui_ctx *webui); - void webu_write(struct webui_ctx *webui, const char *buf); #endif diff --git a/src/webu_html.cpp b/src/webu_html.cpp index 252315c4..39af05c4 100644 --- a/src/webu_html.cpp +++ b/src/webu_html.cpp @@ -17,34 +17,6 @@ * Copyright 2020 MotionMrDave@gmail.com */ -/* - * Functional naming scheme - * webu_html* - Functions that create the display webcontrol page. - * webu_html_main - Entry point from webu_ans_ctrl(in webu.c) - * webu_html_page - Create the web page - * webu_html_head - Header section of the page - * webu_html_style* - The style section of the web page - * webu_html_body - Calls all the functions to create the body - * webu_html_navbar* - The navbar section of the web page - * webu_html_config* - config parms of page - * webu_html_track* - Tracking functions - * webu_html_script* - The javascripts of the web page - * - * To debug, run code, open page, view source and make copy of html - * into a local file to revise changes then determine applicable section(s) - * in this code to modify to match modified version. - * Known HTML Issues: - * Single and double quotes are not consistently used. - * HTML ids do not follow any naming convention. - * After clicking restart, do something...Try to connect again? - * - * Additional functionality considerations: - * Notification to user of items that require restart when changed. - * Notification to user that item successfully implemented (config change/tracking) - * List MotionPlus parms somewhere so they can be found by xgettext - * - */ - #include "motionplus.hpp" #include "conf.hpp" #include "logger.hpp" @@ -53,129 +25,164 @@ #include "webu_html.hpp" -/* struct to save information regarding the links to include in html page */ -struct strminfo_ctx { - struct ctx_cam **camlst; - char lnk_ref[WEBUI_LEN_LNK]; - char lnk_src[WEBUI_LEN_LNK]; - char lnk_camid[WEBUI_LEN_LNK]; - char proto[WEBUI_LEN_LNK]; - int port; - int motion_images; -}; - +/* Create the CSS styles used in the navigation bar/side of the page */ static void webu_html_style_navbar(struct webui_ctx *webui) { - /* Write out the style section of the web page */ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", - " .navbar {\n" - " overflow: hidden;\n" - " background-color: #333;\n" - " font-family: Arial;\n" + webui->resp_page += + " .sidenav {\n" + " height: 100%;\n" + " width: 10rem;\n" + " position: fixed;\n" + " z-index: 1;\n" + " top: 0;\n" + " left: 0;\n" + " background-color: lightgrey;\n" + " overflow-x: hidden;\n" + " overflow: auto;\n" " }\n" - " .navbar a {\n" - " float: left;\n" - " font-size: 16px;\n" - " color: white;\n" - " text-align: center;\n" - " padding: 14px 16px;\n" + " .sidenav a, .dropbtn {\n" + " padding: 0.5rem 0rem 0.5em 1rem;\n" " text-decoration: none;\n" - " }\n" - " .navbar a:hover, {\n" - " background-color: darkgray;\n" - " }\n"); - webu_write(webui, response); - -} - -static void webu_html_style_dropdown(struct webui_ctx *webui) -{ - /* Write out the style section of the web page */ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", - " .dropdown {\n" - " float: left;\n" - " overflow: hidden;\n" - " }\n" - " .dropdown .dropbtn {\n" - " font-size: 16px;\n" + " font-size: 1rem;\n" + " display: block;\n" " border: none;\n" + " background: none;\n" + " width:100%;\n" + " text-align: left;\n" + " cursor: pointer;\n" " outline: none;\n" + " color: black;\n" + " background-color: lightgray;\n" + " }\n" + " .sidenav a:hover, .dropbtn:hover {\n" + " background-color: #555;\n" " color: white;\n" - " padding: 14px 16px;\n" - " background-color: inherit;\n" - " font-family: inherit;\n" - " margin: 0;\n" " }\n" " .dropdown-content {\n" " display: none;\n" - " position: absolute;\n" - " background-color: #f9f9f9;\n" - " min-width: 160px;\n" - " box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);\n" - " z-index: 1;\n" + " background-color:lightgray;\n" + " padding-left: 1rem;\n" " }\n" - " .dropdown-content a {\n" - " float: none;\n" - " color: black;\n" - " padding: 12px 16px;\n" + " .actionbtn {\n" + " padding: 0.25rem;\n" " text-decoration: none;\n" + " font-size: 0.5rem;\n" " display: block;\n" - " text-align: left;\n" - " }\n" - " .dropdown-content a:hover {\n" + " border: none;\n" + " background: none;\n" + " width: 3rem;\n" + " text-align: center;\n" + " cursor: pointer;\n" + " outline: none;\n" + " color: black;\n" " background-color: lightgray;\n" - " }\n" - " .dropdown:hover .dropbtn {\n" - " background-color: darkgray;\n" - " }\n" - " .border {\n" - " border-width: 2px;\n" - " border-color: white;\n" - " border-style: solid;\n" - " }\n"); - webu_write(webui, response); + " }\n"; + } -static void webu_html_style_input(struct webui_ctx *webui) +/* Create the css styles used in the config sections */ +static void webu_html_style_config(struct webui_ctx *webui) { - /* Write out the style section of the web page */ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", - " input , select {\n" - " width: 25%;\n" - " padding: 5px;\n" - " margin: 0;\n" - " display: inline-block;\n" - " border: 1px solid #ccc;\n" - " border-radius: 4px;\n" - " box-sizing: border-box;\n" - " height: 50%;\n" - " font-size: 75%;\n" - " margin-bottom: 5px;\n" + webui->resp_page += + " .cls_config {\n" + " background-color: #000000;\n" + " color: #fff;\n" + " text-align: center;\n" + " margin-top: 0rem;\n" + " margin-bottom: 0rem;\n" + " font-weight: normal;\n" + " font-size: 0.90rem;\n" " }\n" - " .frm-input{\n" - " text-align:center;\n" - " }\n"); - webu_write(webui, response); + " .cls_config table {\n" + " display: table;\n" + " border-spacing: 1rem;\n" + " margin: auto;\n" + " }\n" + " .cls_config label {\n" + " padding: 0rem;\n" + " text-align: right;\n" + " width: 10rem;\n" + " height: 2.5rem;\n" + " }\n" + " .cls_config textarea {\n" + " margin: auto;\n" + " text-align: center;\n" + " width: 15.5rem;\n" + " height: 2.5rem;\n" + " }\n" + " .cls_drop {\n" + " padding: 0rem;\n" + " text-align: right;\n" + " width: 10rem;\n" + " height: 2.25rem;\n" + " }\n" + " .cls_text {\n" + " padding: 0rem;\n" + " width: 10em;\n" + " text-align: right;\n" + " }\n" + " .cls_text_nbr {\n" + " padding: 0rem;\n" + " width: 10rem;\n" + " text-align: right;\n" + " }\n" + " .cls_text_wide {\n" + " padding: 0rem;\n" + " height: 3rem;\n" + " width: 20rem;\n" + " text-align: right;\n" + " }\n" + " .cls_camdrop {\n" + " /* Only used to identify all the cam drops on page */\n" + " }\n" + " .arrow {\n" + " border: solid black;\n" + " border-width: 0 1rem 1rem 0;\n" + " border: double black;\n" + " border-width: 0 0.75rem 0.75rem 0;\n" + " display: inline-block;\n" + " padding: 1rem;\n" + " font-size: 0.5rem;\n" + " }\n" + " .right {\n" + " transform: rotate(-45deg);\n" + " -webkit-transform: rotate(-45deg);\n" + " }\n" + " .left {\n" + " transform: rotate(135deg);\n" + " -webkit-transform: rotate(135deg);\n" + " }\n" + " .up {\n" + " transform: rotate(-135deg);\n" + " -webkit-transform: rotate(-135deg);\n" + " }\n" + " .down {\n" + " transform: rotate(45deg);\n" + " -webkit-transform: rotate(45deg);\n" + " }\n" + " .zoombtn {\n" + " font-size:1.25rem;\n" + " width: 3rem;\n" + " height: 1.5rem;\n" + " margin: 0;\n" + " }\n"; + } +/* Write out the starting style section of the web page */ static void webu_html_style_base(struct webui_ctx *webui) { - /* Write out the style section of the web page */ - char response[WEBUI_LEN_RESP]; - snprintf(response, sizeof (response),"%s", - " * {margin: 0; padding: 0; }\n" + webui->resp_page += + " * {\n" + " margin: 0;\n" + " padding: 0;\n" + " }\n" " body {\n" " padding: 0;\n" " margin: 0;\n" " font-family: Arial, Helvetica, sans-serif;\n" - " font-size: 16px;\n" + " font-size: 1rem;\n" " line-height: 1;\n" " color: #606c71;\n" " background-color: #159957;\n" @@ -184,34 +191,21 @@ static void webu_html_style_base(struct webui_ctx *webui) " margin-right:0.5% ;\n" " width: device-width ;\n" " }\n" - " img {\n" - " max-width: 100%;\n" - " max-height: 100%;\n" - " height: auto;\n" - " }\n" " .page-header {\n" " color: #fff;\n" " text-align: center;\n" " margin-top: 0rem;\n" " margin-bottom: 0rem;\n" " font-weight: normal;\n" - " }\n"); - webu_write(webui, response); - - snprintf(response, sizeof (response),"%s", - " .page-header h4 {\n" - " height: 2px;\n" + " }\n" + " .page-header h3 {\n" + " height: 2rem;\n" " padding: 0;\n" - " margin: 1rem 0;\n" + " margin: 1rem;\n" " border: 0;\n" " }\n" - " .main-content {\n" - " background-color: #000000;\n" - " text-align: center;\n" - " margin-top: 0rem;\n" - " margin-bottom: 0rem;\n" - " font-weight: normal;\n" - " font-size: 0.90em;\n" + " h3 {\n" + " margin-left: 10rem;\n" " }\n" " .header-right{\n" " float: right;\n" @@ -220,1127 +214,617 @@ static void webu_html_style_base(struct webui_ctx *webui) " .header-center {\n" " text-align: center;\n" " color: white;\n" - " margin-top: 10px;\n" - " margin-bottom: 10px;\n" - " }\n"); - webu_write(webui, response); + " margin-top: 1rem;\n" + " margin-bottom: 1rem;\n" + " }\n" + " .border {\n" + " border-width: 1rem;\n" + " border-color: white;\n" + " border-style: solid;\n" + " }\n"; + } +/* Write out the style section of the web page */ static void webu_html_style(struct webui_ctx *webui) { - /* Write out the style section of the web page */ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", " \n"); - webu_write(webui, response); + webui->resp_page += " \n"; } +/* Create the header section of the page */ static void webu_html_head(struct webui_ctx *webui) { - /* Write out the header section of the web page */ - char response[WEBUI_LEN_RESP]; - snprintf(response, sizeof (response),"%s","\n" - " \n" - " MotionPlus\n" - " \n"); - webu_write(webui, response); + webui->resp_page += " \n" + " \n" + "MotionPlus \n" + " \n"; webu_html_style(webui); - snprintf(response, sizeof (response),"%s", "\n"); - webu_write(webui, response); + webui->resp_page += "\n\n"; } -static void webu_html_navbar_camera(struct webui_ctx *webui) -{ - /*Write out the options included in the camera dropdown */ - char response[WEBUI_LEN_RESP]; - int indx; - - if (webui->cam_threads == 1){ - /* Only MotionPlus.conf file */ - if (webui->motapp->cam_list[0]->conf->camera_name == ""){ - snprintf(response, sizeof (response), - "
\n" - " \n" - "
\n" - " %s 1\n" - ,_("Cameras") - ,webui->motapp->cam_list[0]->camera_id - ,_("Camera")); - webu_write(webui, response); - } else { - snprintf(response, sizeof (response), - "
\n" - " \n" - "
\n" - " %s\n" - ,_("Cameras") - ,webui->motapp->cam_list[0]->camera_id - ,webui->motapp->cam_list[0]->conf->camera_name.c_str()); - webu_write(webui, response); - } - } else if (webui->cam_threads > 1){ - /* MotionPlus.conf + separate camera.conf file */ - snprintf(response, sizeof (response), - "
\n" - " \n" - "
\n" - " %s\n" - ,_("Cameras") - ,_("All")); - webu_write(webui, response); - - for (indx=1;indx <= webui->cam_count;indx++){ - if (webui->motapp->cam_list[indx]->conf->camera_name == ""){ - snprintf(response, sizeof (response), - " %s %d\n" - ,webui->motapp->cam_list[indx]->camera_id - , _("Camera"), webui->motapp->cam_list[indx]->camera_id); - } else { - snprintf(response, sizeof (response), - " %s\n" - ,webui->motapp->cam_list[indx]->camera_id - ,webui->motapp->cam_list[indx]->conf->camera_name.c_str() - ); - } - webu_write(webui, response); - } - } - - snprintf(response, sizeof (response),"%s", - "
\n" - "
\n"); - webu_write(webui, response); - -} - -static void webu_html_navbar_action(struct webui_ctx *webui) -{ - /* Write out the options included in the actions dropdown*/ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response), - "
\n" - " \n" - "
\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - " %s\n" - "
\n" - "
\n" - ,_("Action") - ,_("Start Event") - ,_("End Event") - ,_("Snapshot") - ,_("Add") - ,_("Delete") - ,_("Change Configuration") - ,_("Write Configuration") - ,_("Tracking") - ,_("Pause") - ,_("Resume") - ,_("Restart") - ,_("Stop")); - webu_write(webui, response); -} - +/* Create the navigation bar section of the page */ static void webu_html_navbar(struct webui_ctx *webui) { - /* Write the navbar section*/ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", - "
\n"); - webu_write(webui, response); - - webu_html_navbar_camera(webui); - - webu_html_navbar_action(webui); - - snprintf(response, sizeof (response), - " %s\n" - "

MotionPlus " VERSION "

\n" - "
\n" - ,_("Help")); - webu_write(webui, response); + webui->resp_page += + "
\n" + "
\n" + " MotionPlus 0.0.1\n" + "
\n" + " \n" + " \n" + " \n" + " Configuration\n" + " \n" + " \n" + "
\n\n"; } -static void webu_html_config_notice(struct webui_ctx *webui) +/* Create the javascript function dropchange_cam */ +static void webu_html_script_dropchange_cam(struct webui_ctx *webui) { - /* Print out the header description of which parameters are included based upon the - * webcontrol_parms that was specified - */ - char response[WEBUI_LEN_RESP]; - - if (webui->motapp->cam_list[0]->conf->webcontrol_parms == 0){ - snprintf(response, sizeof (response), - "

webcontrol_parms = 0 (%s)

\n" - ,_("No Configuration Options")); - } else if (webui->motapp->cam_list[0]->conf->webcontrol_parms == 1){ - snprintf(response, sizeof (response), - "

webcontrol_parms = 1 (%s)

\n" - ,_("Limited Configuration Options")); - } else if (webui->motapp->cam_list[0]->conf->webcontrol_parms == 2){ - snprintf(response, sizeof (response), - "

webcontrol_parms = 2 (%s)

\n" - ,_("Advanced Configuration Options")); - } else{ - snprintf(response, sizeof (response), - "

webcontrol_parms = 3 (%s)

\n" - ,_("Restricted Configuration Options")); - } - webu_write(webui, response); + webui->resp_page += + " /*Cascade camera change in one dropdown to all the others*/\n" + " function dropchange_cam(camobj) {\n" + " assign_vals(camobj.value);\n\n" + " var sect = document.getElementsByName('camdrop');\n" + " for (var indx = 0; indx < sect.length; indx++) {\n" + " sect.item(indx).selectedIndex =camobj.selectedIndex;\n" + " }\n" + " }\n\n"; } -static void webu_html_h3desc(struct webui_ctx *webui) +/* Create the javascript function submit_config */ +static void webu_html_script_submit_config(struct webui_ctx *webui) { - /* Write out the status description for the camera */ - char response[WEBUI_LEN_RESP]; - - if (webui->cam_threads == 1){ - snprintf(response, sizeof (response), - "
\n" - "

%s (%s)

\n" - "
\n" - ,_("All Cameras") - ,(!webui->motapp->cam_list[0]->running_cam)? _("Not running") : - (webui->motapp->cam_list[0]->lost_connection)? _("Lost connection"): - (webui->motapp->cam_list[0]->pause)? _("Paused"):_("Active") - ); - webu_write(webui,response); - } else { - snprintf(response, sizeof (response), - "
\n" - "

%s

\n" - "
\n" - ,_("All Cameras")); - webu_write(webui,response); - } -} - -static void webu_html_config(struct webui_ctx *webui) -{ - - /* Write out the options to put into the config dropdown - * We use html data attributes to store the values for the options - * We always set a cam_all00 attribute and if the value if different for - * any of our cameras, then we also add a cam_xxxxx which has the config - * value for camera xxxxx The javascript then decodes these to display - */ - - char response[WEBUI_LEN_RESP]; - int indx_parm, indx, diff_vals, retcd; - char val_main[PATH_MAX], val_thread[PATH_MAX]; - char *val_temp; - - - snprintf(response, sizeof (response),"%s", - "
\n"); - webu_write(webui, response); - - webu_html_config_notice(webui); - - snprintf(response, sizeof (response), - "
\n" - " \n" - " \n" - " \n" - "
\n" - "
\n" - ,_("Save")); - webu_write(webui, response); - -} - -static void webu_html_track(struct webui_ctx *webui) -{ - /* Write the section for handling the tracking function */ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response), - " \n" - ,_("Pan/Tilt") - ,_("Absolute Change") - ,_("Center") - ,_("Pan") - ,_("Tilt") - ,_("Save")); - webu_write(webui, response); - -} - -static void webu_html_strminfo(struct strminfo_ctx *strm_info, int indx) -{ - /* This determines all the items we need to know to specify links and - * stream sources for the page. The options are 0-3 as of this writing - * where 0 = full streams, 1 = substreams, 2 = static images and 3 is - * the legacy code for creating streams. So we need to assign not only - * what images are to be sent but also whether we have tls/ssl. - * There are WAY too many options for this. - */ - /* If using the main port,we need to insert a thread number into url*/ - if (strm_info->camlst[0]->conf->stream_port != 0) { - snprintf(strm_info->lnk_camid,WEBUI_LEN_LNK,"/%d" - ,strm_info->camlst[indx]->camera_id); - strm_info->port = strm_info->camlst[0]->conf->stream_port; - if (strm_info->camlst[0]->conf->stream_tls) { - snprintf(strm_info->proto,WEBUI_LEN_LNK,"%s","https"); - } else { - snprintf(strm_info->proto,WEBUI_LEN_LNK,"%s","http"); - } - } else { - snprintf(strm_info->lnk_camid,WEBUI_LEN_LNK,"%s",""); - strm_info->port = strm_info->camlst[indx]->conf->stream_port; - if (strm_info->camlst[indx]->conf->stream_tls) { - snprintf(strm_info->proto,WEBUI_LEN_LNK,"%s","https"); - } else { - snprintf(strm_info->proto,WEBUI_LEN_LNK,"%s","http"); - } - } - if (strm_info->motion_images){ - snprintf(strm_info->lnk_ref,WEBUI_LEN_LNK,"%s","/motion"); - snprintf(strm_info->lnk_src,WEBUI_LEN_LNK,"%s","/motion"); - } else { - /* Assign what images and links we want */ - if (strm_info->camlst[indx]->conf->stream_preview_method == 1){ - /* Substream for preview */ - snprintf(strm_info->lnk_ref,WEBUI_LEN_LNK,"%s","/stream"); - snprintf(strm_info->lnk_src,WEBUI_LEN_LNK,"%s","/substream"); - } else if (strm_info->camlst[indx]->conf->stream_preview_method == 2){ - /* Static image for preview */ - snprintf(strm_info->lnk_ref,WEBUI_LEN_LNK,"%s","/stream"); - snprintf(strm_info->lnk_src,WEBUI_LEN_LNK,"%s","/current"); - } else if (strm_info->camlst[indx]->conf->stream_preview_method == 4){ - /* Source image for preview */ - snprintf(strm_info->lnk_ref,WEBUI_LEN_LNK,"%s","/source"); - snprintf(strm_info->lnk_src,WEBUI_LEN_LNK,"%s","/source"); - } else { - /* Full stream for preview (method 0 or 3)*/ - snprintf(strm_info->lnk_ref,WEBUI_LEN_LNK,"%s","/stream"); - snprintf(strm_info->lnk_src,WEBUI_LEN_LNK,"%s","/stream"); - } - } - -} - -static void webu_html_preview(struct webui_ctx *webui) -{ - - /* Write the initial version of the preview section. The javascript - * will change this section when user selects a different camera */ - char response[WEBUI_LEN_RESP]; - int indx, indx_st, preview_scale; - struct strminfo_ctx strm_info; - - strm_info.camlst = webui->motapp->cam_list; - - snprintf(response, sizeof (response),"%s", - "
\n" - "
\n" - "
\n" - "

\n"); - webu_write(webui, response); - - indx_st = 1; - if (webui->cam_threads == 1) indx_st = 0; - - for (indx = indx_st; indxcam_threads; indx++){ - if (webui->motapp->cam_list[indx]->conf->stream_preview_newline){ - snprintf(response, sizeof (response),"%s","
\n"); - webu_write(webui, response); - } - - if (webui->motapp->cam_list[indx]->conf->stream_preview_method == 3){ - preview_scale = 45; - } else { - preview_scale = webui->motapp->cam_list[indx]->conf->stream_preview_scale; - } - - strm_info.motion_images = FALSE; - webu_html_strminfo(&strm_info,indx); - snprintf(response, sizeof (response), - " " - " \n" - ,strm_info.proto, webui->hostname, strm_info.port - ,strm_info.lnk_camid, strm_info.lnk_ref - ,strm_info.proto, webui->hostname, strm_info.port - ,strm_info.lnk_camid, strm_info.lnk_src - ,preview_scale); - webu_write(webui, response); - - if (webui->motapp->cam_list[indx]->conf->stream_preview_method == 3){ - strm_info.motion_images = TRUE; - webu_html_strminfo(&strm_info,indx); - snprintf(response, sizeof (response), - " " - " \n" - ,strm_info.proto, webui->hostname, strm_info.port - ,strm_info.lnk_camid, strm_info.lnk_ref - ,strm_info.proto, webui->hostname, strm_info.port - ,strm_info.lnk_camid, strm_info.lnk_src - ,preview_scale); - webu_write(webui, response); - } - - } - - snprintf(response, sizeof (response),"%s", - "

\n" - "
\n" - "
\n" - "
\n"); - webu_write(webui, response); - -} - -static void webu_html_script_action(struct webui_ctx *webui) -{ - /* Write the javascript action_click() function. - * We do not have a good notification section on the page so the successful - * submission and response is currently a empty if block for the future - * enhancement to somehow notify the user everything worked */ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", - " function event_reloadpage() {\n" - " window.location.reload();\n" - " }\n\n" - ); - webu_write(webui, response); - - snprintf(response, sizeof (response),"%s", - " function action_click(actval) {\n" - " if (actval == \"config\"){\n" - " document.getElementById('trk_form').style.display=\"none\";\n" - " document.getElementById('cfg_form').style.display=\"inline\";\n" - " } else if (actval == \"track\"){\n" - " document.getElementById('cfg_form').style.display=\"none\";\n" - " document.getElementById('trk_form').style.display=\"inline\";\n" - " } else {\n" - " document.getElementById('cfg_form').style.display=\"none\";\n" - " document.getElementById('trk_form').style.display=\"none\";\n" - " var camstr = document.getElementById('h3_cam').getAttribute('data-cam');\n" - " var camnbr = camstr.substring(4,9);\n" - " var http = new XMLHttpRequest();\n" - " if ((actval == \"/detection/pause\") || (actval == \"/detection/resume\")) {\n" - " http.addEventListener('load', event_reloadpage); \n" - " }\n" - ); - webu_write(webui, response); - - snprintf(response, sizeof (response), - " var url = \"%s://%s:%d/\"; \n" - ,webui->hostproto, webui->hostname - ,webui->motapp->cam_list[0]->conf->webcontrol_port); - webu_write(webui, response); - - snprintf(response, sizeof (response), - " if (camnbr == \"all00\"){\n" - " url = url + \"%05d\";\n" - " } else {\n" - " url = url + camnbr;\n" - " }\n" - " url = url + actval;\n" - ,webui->motapp->cam_list[0]->camera_id); - webu_write(webui, response); - - snprintf(response, sizeof (response),"%s", - " http.open(\"GET\", url, true);\n" - " http.onreadystatechange = function() {\n" - " if(http.readyState == 4 && http.status == 200) {\n" + webui->resp_page += + " function submit_config(category) {\n" + " var formData = new FormData();\n" + " var camid = document.getElementsByName('camdrop')[0].value;\n" + " var pCfg = pData['configuration']['cam'+camid];\n\n" + " formData.append('command', 'config');\n" + " formData.append('camid', camid);\n\n" + " for (jkey in pCfg) {\n" + " if (document.getElementsByName(jkey)[0] != null) {\n" + " if (pCfg[jkey].category == category) {\n" + " if (document.getElementsByName(jkey)[0].type == 'checkbox') {\n" + " formData.append(jkey, document.getElementsByName(jkey)[0].checked);\n" + " } else {\n" + " formData.append(jkey, document.getElementsByName(jkey)[0].value);\n" + " }\n" " }\n" " }\n" - " http.send(null);\n" " }\n" - " document.getElementById('act_btn').style.display=\"none\"; \n" - " document.getElementById('cfg_value').value = '';\n" - " document.getElementById('cfg_parms').value = 'default';\n" - " }\n\n"); - webu_write(webui, response); + " var request = new XMLHttpRequest();\n" + " request.open('POST', '" + webui->hostfull + "');\n" + " request.send(formData);\n\n" + " }\n\n"; } -static void webu_html_script_camera_thread(struct webui_ctx *webui) +/* Create the javascript function config_hideall */ +static void webu_html_script_config_hideall(struct webui_ctx *webui) { - /* Write the javascript thread IF conditions of camera_click() function */ - char response[WEBUI_LEN_RESP]; - int indx, indx_st, preview_scale; - struct strminfo_ctx strm_info; - - indx_st = 1; - if (webui->cam_threads == 1) indx_st = 0; - - strm_info.camlst = webui->motapp->cam_list; - - for (indx = indx_st; indxcam_threads; indx++){ - snprintf(response, sizeof (response), - " if (camid == \"cam_%05d\"){\n" - ,webui->motapp->cam_list[indx]->camera_id); - webu_write(webui, response); - - if (webui->motapp->cam_list[indx]->conf->stream_preview_method == 3){ - preview_scale = 45; - } else { - preview_scale = 95; - } - - strm_info.motion_images = FALSE; - webu_html_strminfo(&strm_info, indx); - snprintf(response, sizeof (response), - " preview=\" " - " \" \n" - ,strm_info.proto, webui->hostname, strm_info.port - ,strm_info.lnk_camid, strm_info.lnk_ref - ,strm_info.proto, webui->hostname,strm_info.port - ,strm_info.lnk_camid, strm_info.lnk_src, preview_scale); - webu_write(webui, response); - - if (webui->motapp->cam_list[indx]->conf->stream_preview_method == 3){ - strm_info.motion_images = TRUE; - webu_html_strminfo(&strm_info, indx); - snprintf(response, sizeof (response), - " preview=preview + \" " - " \" \n" - ,strm_info.proto, webui->hostname, strm_info.port - ,strm_info.lnk_camid, strm_info.lnk_ref - ,strm_info.proto, webui->hostname,strm_info.port - ,strm_info.lnk_camid, strm_info.lnk_src, preview_scale); - webu_write(webui, response); - } - - if (webui->motapp->cam_list[indx]->conf->camera_name == ""){ - snprintf(response, sizeof (response), - " header=\"

%s %d (%s)

\"\n" - ,_("Camera") - , webui->motapp->cam_list[indx]->camera_id - ,(!webui->motapp->cam_list[indx]->running_cam)? _("Not running") : - (webui->motapp->cam_list[indx]->lost_connection)? _("Lost connection"): - (webui->motapp->cam_list[indx]->pause)? _("Paused"):_("Active") - ); - } else { - snprintf(response, sizeof (response), - " header=\"

%s (%s)

\"\n" - , webui->motapp->cam_list[indx]->conf->camera_name.c_str() - ,(!webui->motapp->cam_list[indx]->running_cam)? _("Not running") : - (webui->motapp->cam_list[indx]->lost_connection)? _("Lost connection"): - (webui->motapp->cam_list[indx]->pause)? _("Paused"):_("Active") - ); - } - webu_write(webui, response); - - snprintf(response, sizeof (response),"%s"," }\n"); - webu_write(webui, response); - } - - return; -} - -static void webu_html_script_camera_all(struct webui_ctx *webui) -{ - /* Write the javascript "All" IF condition of camera_click() function */ - char response[WEBUI_LEN_RESP]; - int indx, indx_st, preview_scale; - struct strminfo_ctx strm_info; - - - indx_st = 1; - if (webui->cam_threads == 1) indx_st = 0; - - strm_info.camlst = webui->motapp->cam_list; - - snprintf(response, sizeof (response), " if (camid == \"cam_all00\"){\n"); - webu_write(webui, response); - - for (indx = indx_st; indxcam_threads; indx++){ - if (indx == indx_st){ - snprintf(response, sizeof (response),"%s"," preview = \"\";\n"); - webu_write(webui, response); - } - - if (webui->motapp->cam_list[indx]->conf->stream_preview_newline){ - snprintf(response, sizeof (response),"%s"," preview = preview + \"
\";\n"); - webu_write(webui, response); - } - - if (webui->motapp->cam_list[indx]->conf->stream_preview_method == 3){ - preview_scale = 45; - } else { - preview_scale = webui->motapp->cam_list[indx]->conf->stream_preview_scale; - } - - strm_info.motion_images = FALSE; - webu_html_strminfo(&strm_info, indx); - snprintf(response, sizeof (response), - " preview = preview + \" " - " \"; \n" - ,strm_info.proto, webui->hostname, strm_info.port - ,strm_info.lnk_camid, strm_info.lnk_ref - ,strm_info.proto, webui->hostname, strm_info.port - ,strm_info.lnk_camid, strm_info.lnk_src - ,preview_scale); - webu_write(webui, response); - - if (webui->motapp->cam_list[indx]->conf->stream_preview_method == 3){ - strm_info.motion_images = TRUE; - webu_html_strminfo(&strm_info, indx); - snprintf(response, sizeof (response), - " preview = preview + \" " - " \"; \n" - ,strm_info.proto, webui->hostname, strm_info.port - ,strm_info.lnk_camid, strm_info.lnk_ref - ,strm_info.proto, webui->hostname, strm_info.port - ,strm_info.lnk_camid, strm_info.lnk_src - ,preview_scale); - webu_write(webui, response); - } - } - - snprintf(response, sizeof (response), - " header=\"

%s

\"\n" + webui->resp_page += + " function config_hideall() {\n" + " var sect = document.getElementsByClassName('cls_config');\n" + " for (var i = 0; i < sect.length; i++) {\n" + " sect.item(i).style.display='none';\n" " }\n" - ,_("All Cameras")); - webu_write(webui, response); - - return; + " return;\n" + " }\n\n"; } -static void webu_html_script_camera(struct webui_ctx *webui) +/* Create the javascript function config_click */ +static void webu_html_script_config_click(struct webui_ctx *webui) { - /* Write the javascript camera_click() function */ - char response[WEBUI_LEN_RESP]; + webui->resp_page += + " function config_click(actval) {\n" + " config_hideall();\n" + " document.getElementById('div_cam').style.display='none';\n" + " document.getElementById('div_config').style.display='inline';\n" + " document.getElementById('div_' + actval).style.display='inline';\n" + " }\n\n"; +} - snprintf(response, sizeof (response),"%s", - " function camera_click(camid) {\n" - " var preview = \"\";\n" - " var header = \"\";\n"); - webu_write(webui, response); - - webu_html_script_camera_thread(webui); - - webu_html_script_camera_all(webui); - - snprintf(response, sizeof (response),"%s", - " document.getElementById(\"id_preview\").innerHTML = preview; \n" - " document.getElementById(\"id_header\").innerHTML = header; \n" - " document.getElementById('cfg_form').style.display=\"none\"; \n" - " document.getElementById('trk_form').style.display=\"none\"; \n" - " document.getElementById('cam_btn').style.display=\"none\"; \n" - " document.getElementById('cfg_value').value = '';\n" - " document.getElementById('cfg_parms').value = 'default';\n" - " }\n\n"); - webu_write(webui, response); +/* Create the javascript function assign_version */ +static void webu_html_script_assign_version(struct webui_ctx *webui) +{ + webui->resp_page += + " function assign_version() {\n" + " var verstr ='MotionPlus \\n'+pData['version'] +'';\n" + " document.getElementById('divnav_version').innerHTML = verstr;\n" + " }\n\n"; } -static void webu_html_script_menucam(struct webui_ctx *webui) +/* Create the javascript function assign_cams */ +static void webu_html_script_assign_cams(struct webui_ctx *webui) { - /* Write the javascript display_cameras() function */ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", - " function display_cameras() {\n" - " document.getElementById('act_btn').style.display = 'none';\n" - " if (document.getElementById('cam_btn').style.display == 'block'){\n" - " document.getElementById('cam_btn').style.display = 'none';\n" - " } else {\n" - " document.getElementById('cam_btn').style.display = 'block';\n" + webui->resp_page += + " function assign_cams() {\n" + " var camcnt = pData['cameras']['count'];\n" + " var html_drop = \"\\n\";\n" + " var html_nav = \"\\n\";\n\n" + " html_drop += \" \\n\";\n\n" + " var sect = document.getElementsByClassName(\"cls_camdrop\");\n" + " for (indx = 0; indx < sect.length; indx++) {\n" + " sect.item(indx).innerHTML = html_drop;\n" + " }\n\n" + " document.getElementById(\"divnav_cam\").innerHTML = html_nav;\n\n" + " return;\n" + " }\n\n"; } -static void webu_html_script_menuact(struct webui_ctx *webui) +/* Create the javascript function assign_vals */ +static void webu_html_script_assign_vals(struct webui_ctx *webui) { - /* Write the javascript display_actions() function */ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", - " function display_actions() {\n" - " document.getElementById('cam_btn').style.display = 'none';\n" - " if (document.getElementById('act_btn').style.display == 'block'){\n" - " document.getElementById('act_btn').style.display = 'none';\n" - " } else {\n" - " document.getElementById('act_btn').style.display = 'block';\n" - " }\n" - " }\n\n"); - webu_write(webui, response); - -} - -static void webu_html_script_evtclk(struct webui_ctx *webui) -{ - /* Write the javascript 'click' EventListener */ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", - " document.addEventListener('click', function(event) {\n" - " const dropCam = document.getElementById('cam_drop');\n" - " const dropAct = document.getElementById('act_drop');\n" - " if (!dropCam.contains(event.target) && !dropAct.contains(event.target)) {\n" - " document.getElementById('cam_btn').style.display = 'none';\n" - " document.getElementById('act_btn').style.display = 'none';\n" - " }\n" - " });\n\n"); - webu_write(webui, response); - -} - -static void webu_html_script_cfgclk(struct webui_ctx *webui) -{ - /* Write the javascript config_click function - * We do not have a good notification section on the page so the successful - * submission and response is currently a empty if block for the future - * enhancement to somehow notify the user everything worked */ - - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", - " function config_click() {\n" - " var camstr = document.getElementById('h3_cam').getAttribute('data-cam');\n" - " var camnbr = camstr.substring(4,9);\n" - " var opts = document.getElementById('cfg_parms');\n" - " var optsel = opts.options[opts.selectedIndex].value;\n" - " var baseval = document.getElementById('cfg_value').value;\n" - " var http = new XMLHttpRequest();\n"); - webu_write(webui, response); - - snprintf(response, sizeof (response), - " var url = \"%s://%s:%d/\"; \n" - ,webui->hostproto, webui->hostname - ,webui->motapp->cam_list[0]->conf->webcontrol_port); - webu_write(webui, response); - - snprintf(response, sizeof (response), - " var optval=encodeURI(baseval);\n" - " if (camnbr == \"all00\"){\n" - " url = url + \"%05d\";\n" - " } else {\n" - " url = url + camnbr;\n" - " }\n" - ,webui->motapp->cam_list[0]->camera_id); - webu_write(webui, response); - - snprintf(response, sizeof (response),"%s", - " url = url + \"/config/set?\" + optsel + \"=\" + optval;\n" - " http.open(\"GET\", url, true);\n" - " http.onreadystatechange = function() {\n" - " if(http.readyState == 4 && http.status == 200) {\n" + webui->resp_page += + " function assign_vals(camid) {\n" + " var pCfg = pData[\"configuration\"][\"cam\"+camid];\n\n" + " for (jkey in pCfg) {\n" + " if (document.getElementsByName(jkey)[0] != null) {\n" + " if (pCfg[jkey].enabled) {\n" + " document.getElementsByName(jkey)[0].disabled = false;\n" + " if (document.getElementsByName(jkey)[0].type == \"checkbox\") {\n" + " document.getElementsByName(jkey)[0].checked = pCfg[jkey].value;\n" + " } else {\n" + " document.getElementsByName(jkey)[0].value = pCfg[jkey].value;\n" + " }\n" + " } else {\n" + " document.getElementsByName(jkey)[0].disabled = true;\n" + " document.getElementsByName(jkey)[0].value = '';\n" + " }\n" + " } else {\n" + " console.log('Uncoded ' + jkey + ' : ' + pCfg[jkey].value);\n" " }\n" " }\n" - " http.send(null);\n" - " document.getElementById('cfg_value').value = \"\";\n" - " opts.options[opts.selectedIndex].setAttribute('data-'+camstr,baseval);\n" - " opts.value = 'default';\n" - " }\n\n"); - webu_write(webui, response); - + " }\n\n"; } -static void webu_html_script_cfgchg(struct webui_ctx *webui) +/* Create the javascript function assign_config */ +static void webu_html_script_assign_config(struct webui_ctx *webui) { - /* Write the javascript option_change function */ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", - " function config_change() {\n" - " var camSel = 'data-'+ document.getElementById('h3_cam').getAttribute('data-cam');\n" - " var opts = document.getElementById('cfg_parms');\n" - " var optval = opts.options[opts.selectedIndex].getAttribute(camSel);\n" - " if (optval == null){\n" - " optval = opts.options[opts.selectedIndex].getAttribute('data-cam_all00');\n" + webui->resp_page += + " function assign_config() {\n" + " var pCfg = pData['configuration']['cam0'];\n" + " var pCat = pData['categories'];\n" + " var html_cfg = \"\";\n" + " var html_nav = \"\\n\";\n" + " var indx_lst = 0;\n\n" + " for (jcat in pCat) {\n" + " html_nav += \"\";\n" + " html_nav += pCat[jcat][\"display\"]+\"\\n\";\n\n" + " html_cfg += \"\\n\";\n" " }\n" - " document.getElementById('cfg_value').value = optval;\n" - " }\n\n"); - webu_write(webui, response); + " document.getElementById(\"div_config\").innerHTML = html_cfg;\n" + " document.getElementById(\"divnav_config\").innerHTML = html_nav;\n\n" + " }\n\n"; } -static void webu_html_script_trkchg(struct webui_ctx *webui) +/* Create the javascript function init_form */ +static void webu_html_script_initform(struct webui_ctx *webui) { - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", - " function track_change() {\n" - " var opts = document.getElementById('trk_option');\n" - " var optval = opts.options[opts.selectedIndex].getAttribute('data-trk');\n" - " if (optval == 'pan'){\n" - " document.getElementById('trk_panx').disabled=false;\n" - " document.getElementById('trk_tilty').disabled = false;\n" - " document.getElementById('trk_lblx').style.display='none';\n" - " document.getElementById('trk_lbly').style.display='none';\n" - " document.getElementById('trk_lblpan').style.display='inline';\n" - " document.getElementById('trk_lbltilt').style.display='inline';\n"); - webu_write(webui, response); - - snprintf(response, sizeof (response),"%s", - " } else if (optval =='abs'){\n" - " document.getElementById('trk_panx').disabled=false;\n" - " document.getElementById('trk_tilty').disabled = false;\n" - " document.getElementById('trk_lblx').value = 'X';\n" - " document.getElementById('trk_lbly').value = 'Y';\n" - " document.getElementById('trk_lblpan').style.display='none';\n" - " document.getElementById('trk_lbltilt').style.display='none';\n" - " document.getElementById('trk_lblx').style.display='inline';\n" - " document.getElementById('trk_lbly').style.display='inline';\n"); - webu_write(webui, response); - - snprintf(response, sizeof (response),"%s", - " } else {\n" - " document.getElementById('cfg_form').style.display='none';\n" - " document.getElementById('trk_panx').disabled=true;\n" - " document.getElementById('trk_tilty').disabled = true;\n" - " }\n" - " }\n\n"); - webu_write(webui, response); - + webui->resp_page += + " function initform() {\n" + " var xmlhttp = new XMLHttpRequest();\n" + " xmlhttp.onreadystatechange = function() {\n" + " if (this.readyState == 4 && this.status == 200) {\n" + " pData = JSON.parse(this.responseText);\n" + " assign_config();\n" + " assign_version();\n" + " assign_vals(0);\n" + " assign_cams();\n" + " }\n" + " };\n" + " xmlhttp.open('GET', '" + webui->hostfull + "/config.json', true);\n" + " xmlhttp.send();\n" + " }\n\n"; } -static void webu_html_script_trkclk(struct webui_ctx *webui) +/* Create the javascript function display_cameras */ +static void webu_html_script_display_cameras(struct webui_ctx *webui) { - char response[WEBUI_LEN_RESP]; - snprintf(response, sizeof (response),"%s", - " function track_click() {\n" - " var camstr = document.getElementById('h3_cam').getAttribute('data-cam');\n" - " var camnbr = camstr.substring(4,9);\n" - " var opts = document.getElementById('trk_option');\n" - " var optsel = opts.options[opts.selectedIndex].getAttribute('data-trk');\n" - " var optval1 = document.getElementById('trk_panx').value;\n" - " var optval2 = document.getElementById('trk_tilty').value;\n" - " var http = new XMLHttpRequest();\n"); - webu_write(webui, response); - - snprintf(response, sizeof (response), - " var url = \"%s://%s:%d/\"; \n" - ,webui->hostproto, webui->hostname - ,webui->motapp->cam_list[0]->conf->webcontrol_port); - webu_write(webui, response); - - snprintf(response, sizeof (response), - " if (camnbr == \"all00\"){\n" - " url = url + \"%05d\";\n" + webui->resp_page += + " function display_cameras() {\n" + " document.getElementById('divnav_config').style.display = 'none';\n" + " if (document.getElementById('divnav_cam').style.display == 'block'){\n" + " document.getElementById('divnav_cam').style.display = 'none';\n" " } else {\n" - " url = url + camnbr;\n" + " document.getElementById('divnav_cam').style.display = 'block';\n" " }\n" - ,webui->motapp->cam_list[0]->camera_id); - webu_write(webui, response); + " }\n\n"; +} - snprintf(response, sizeof (response),"%s", - - " if (optsel == 'pan'){\n" - " url = url + '/track/set?pan=' + optval1 + '&tilt=' + optval2;\n" - " } else if (optsel == 'abs') {\n" - " url = url + '/track/set?x=' + optval1 + '&y=' + optval2;\n" +/* Create the javascript function display_config */ +static void webu_html_script_display_config(struct webui_ctx *webui) +{ + webui->resp_page += + " function display_config() {\n" + " document.getElementById('divnav_cam').style.display = 'none';\n" + " if (document.getElementById('divnav_config').style.display == 'block') {\n" + " document.getElementById('divnav_config').style.display = 'none';\n" " } else {\n" - " url = url + '/track/center'\n" + " document.getElementById('divnav_config').style.display = 'block';\n" " }\n" - " http.open(\"GET\", url, true);\n" - " http.onreadystatechange = function() {\n" - " if(http.readyState == 4 && http.status == 200) {\n" - " }\n" + " }\n\n"; +} + +/* Create the action_click javascript function */ +static void webu_html_script_action_click(struct webui_ctx *webui) +{ + webui->resp_page += + " function action_click(actval) {\n\n" + " config_hideall();\n\n" + " var formData = new FormData();\n" + " var camid = pData['cameras'][gIndexCam]['id'];\n\n" + " formData.append('command', actval);\n" + " formData.append('camid', camid);\n\n" + " var request = new XMLHttpRequest();\n" + " request.open('POST', '" + webui->hostfull + "');\n" + " request.send(formData);\n\n" + " return;\n" + " }\n\n"; +} + +/* Create the camera_click javascript function */ +static void webu_html_script_camera_click(struct webui_ctx *webui) +{ + webui->resp_page += + " function camera_click(index_cam) {\n\n" + " var html_preview = \"\";\n" + " var camid;\n\n" + " config_hideall();\n\n" + " gIndexCam = index_cam;\n\n" + " html_preview += \"\";\n" + " html_preview += \"\\n\";\n" + + " html_preview += \" \\n\";\n" + + " html_preview += \"\\n\";\n" + + " html_preview += \" \\n\";\n" + + " html_preview += \"\\n\";\n" + + " html_preview += \" \\n\";\n" + + " html_preview += \"\\n\";\n" + + " html_preview += \" \\n\";\n" + + " html_preview += \"\\n\";\n" + " html_preview += \"\\n\";\n" + + " html_preview += \" \\n\";\n" + + " html_preview += \"\\n\";\n" + + " html_preview += \" \\n\";\n" + + " html_preview += \"\\n\";\n" + + " html_preview += \" \\n\";\n" + + " html_preview += \"\\n\";\n" + + + " if (gIndexCam > 0) {\n" + " camid = pData['cameras'][index_cam].id;\n" + " html_preview += \"\\n\";\n" + " html_preview += \"\\n\";\n" + " html_preview += \"\\n\";\n" + " html_preview += \"\\n\";\n" + " html_preview += \"\\n\";\n" + " html_preview += \"\\n\";\n" + " html_preview += \"\\n\";\n" + " html_preview += \"\\n\";\n" + " html_preview += \"\\n\";\n" + + " html_preview += \"
  
  
  
  
    
  
    
    
\";\n" + " if (pData['configuration']['cam'+camid].stream_preview_method.value == 1) {\n" + " html_preview += \"\\n\";\n" + " } else { \n" + " html_preview += \"\\n\";\n" + " }\n" + " document.getElementById('div_config').style.display='none';\n" + " document.getElementById('div_cam').style.display='block';\n" + " document.getElementById('div_cam').innerHTML = html_preview;\n\n" + " } else if (gIndexCam == 0) {\n" + " var camcnt = pData['cameras']['count'];\n" + " html_preview += \"\";\n" + " for (var indx = 1; indx <= camcnt; indx++) {\n" + " camid = pData['cameras'][indx].id;\n" + " if (pData['configuration']['cam'+camid].stream_preview_method.value == 1) {\n" + " html_preview += \"\\n\";\n" + " if (pData['configuration']['cam'+camid].stream_preview_newline.value == true) {\n" + " html_preview += \"
\\n\";\n" + " }\n" + " } else { \n" + " html_preview += \"\\n\";\n" + " if (pData['configuration']['cam'+camid].stream_preview_newline.value == true) {\n" + " html_preview += \"
\\n\";\n" + " }\n" + " } \n" + " }\n" + " document.getElementById('div_config').style.display='none';\n" + " document.getElementById('div_cam').style.display='block';\n" + " document.getElementById('div_cam').innerHTML = html_preview;\n" + " }\n\n" + " timer.start();\n\n" + " }\n\n"; +} + +/* Create the timer_function javascript function */ +static void webu_html_script_timer_function(struct webui_ctx *webui) +{ + webui->resp_page += + " function Timer(fn, t) {\n" + " var timerObj = setInterval(fn, t);\n" + " this.stop = function() {\n" + " if (timerObj) {\n" + " clearInterval(timerObj);\n" + " timerObj = null;\n" + " }\n" + " return this;\n" " }\n" - " http.send(null);\n" - " }\n\n"); - webu_write(webui, response); + " this.start = function() {\n" + " if (!timerObj) {\n" + " this.stop();\n" + " timerObj = setInterval(fn, t);\n" + " }\n" + " return this;\n" + " }\n" + " }\n\n"; } +/* Create the pictimer_function javascript function */ +static void webu_html_script_timer_pic(struct webui_ctx *webui) +{ + webui->resp_page += + " var timer = new Timer(function() {\n" + " var picurl = \"\";\n" + " var img = new Image();\n\n" + " var camid;\n\n" + " if (gIndexCam > 0) {\n" + " camid = pData['cameras'][gIndexCam]['id'];\n\n" + " if (pData['configuration']['cam'+camid].stream_preview_method.value == 1) {\n" + " picurl = pData['cameras'][gIndexCam]['url'] + \"static/stream/t\" + new Date().getTime();\n" + " img.src = picurl;\n" + " document.getElementById('pic'+gIndexCam).src = picurl;\n" + " }\n " + " } else if (gIndexCam == 0) {\n" + " var camcnt = pData['cameras']['count'];\n" + " for (var indx = 1; indx <= camcnt; indx++) {\n" + " camid = pData['cameras'][indx]['id'];\n\n" + " if (pData['configuration']['cam'+camid].stream_preview_method.value == 1) {\n" + " picurl = pData['cameras'][indx]['url'] + \"static/stream/t\" + new Date().getTime();\n" + " img.src = picurl;\n" + " document.getElementById('pic'+indx).src = picurl;\n" + " }\n" + " }\n" + " }\n" + " }, 1000);\n\n"; + +} + +/* Call all the functions to create the java scripts of page*/ static void webu_html_script(struct webui_ctx *webui) { - /* Write the javascripts */ - char response[WEBUI_LEN_RESP]; + webui->resp_page += " \n"); - webu_write(webui, response); + webui->resp_page += " \n\n"; } +/* Create the body section of the web page */ static void webu_html_body(struct webui_ctx *webui) { - /* Write the body section of the form */ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s","\n"); - webu_write(webui, response); + webui->resp_page += "\n"; webu_html_navbar(webui); - webu_html_h3desc(webui); - - webu_html_config(webui); - - webu_html_track(webui); - - webu_html_preview(webui); + webui->resp_page += + "
\n" + " \n" + "
\n\n" + "
\n" + " \n" + "
\n\n"; webu_html_script(webui); - snprintf(response, sizeof (response),"%s", "\n"); - webu_write(webui, response); + webui->resp_page += "\n"; } -static void webu_html_page(struct webui_ctx *webui) +/* Create the default motionplus page */ +void webu_html_page(struct webui_ctx *webui) { - /* Write the main page html */ - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response), - "\n" - "\n",webui->lang); - webu_write(webui, response); + webui->resp_page += "\n" + "\n"; webu_html_head(webui); webu_html_body(webui); - snprintf(response, sizeof (response),"%s", "\n"); - webu_write(webui, response); - + webui->resp_page += "\n"; } +/*Create the bad request page*/ void webu_html_badreq(struct webui_ctx *webui) { - char response[WEBUI_LEN_RESP]; - - snprintf(response, sizeof (response),"%s", + webui->resp_page = "\n" "\n" "\n" "

Bad Request

\n" "

The server did not understand your request.

\n" "\n" - "\n"); - webu_write(webui, response); - - return; + "\n"; } /* Load a user provided html page */ -static void webu_html_user(struct webui_ctx *webui) +void webu_html_user(struct webui_ctx *webui) { char response[PATH_MAX]; FILE *fp = NULL; - fp = fopen(webui->cam->conf->webcontrol_html.c_str(), "r"); + fp = fopen(webui->motapp->cam_list[0]->conf->webcontrol_html.c_str(), "r"); if (fp == NULL) { MOTION_LOG(ERR, TYPE_STREAM, NO_ERRNO , _("Invalid user html file: %s") - , webui->cam->conf->webcontrol_html.c_str()); + , webui->motapp->cam_list[0]->conf->webcontrol_html.c_str()); webu_html_badreq(webui); return; } + webui->resp_page = ""; while (fgets(response, PATH_MAX-1, fp)) { - webu_write(webui, response); + webui->resp_page += response; } + myfclose(fp); } -/* Entry point for providing the html version of web page */ -void webu_html_main(struct webui_ctx *webui) -{ - int retcd; - - pthread_mutex_lock(&webui->motapp->mutex_camlst); - - retcd = 0; - if (strlen(webui->uri_camid) == 0) { - if (webui->motapp->cam_list[0]->conf->webcontrol_interface == 3) { - webu_html_user(webui); - } else { - webu_html_page(webui); - } - - } else if ((mystreq(webui->uri_cmd1,"config")) && - (mystreq(webui->uri_cmd2,"write"))) { - webu_process_action(webui); - - } else if (mystreq(webui->uri_cmd1,"config")) { - retcd = webu_process_config(webui); - - } else if (mystreq(webui->uri_cmd1,"action")){ - webu_process_action(webui); - - } else if (mystreq(webui->uri_cmd1,"detection")){ - webu_process_action(webui); - - } else if (mystreq(webui->uri_cmd1,"track")){ - retcd = webu_process_track(webui); - - } else if ((mystreq(webui->uri_cmd1,"config.json")) || - (mystreq(webui->uri_camid,"config.json"))) { - retcd = webu_process_json(webui); - - } else{ - MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO, - _("Invalid action requested: >%s< >%s< >%s<") - ,webui->uri_camid, webui->uri_cmd1, webui->uri_cmd2); - retcd = -1; - } - - if (retcd < 0) webu_html_badreq(webui); - - pthread_mutex_unlock(&webui->motapp->mutex_camlst); - - return; -} diff --git a/src/webu_html.hpp b/src/webu_html.hpp index ddd05f18..8f01a917 100644 --- a/src/webu_html.hpp +++ b/src/webu_html.hpp @@ -21,6 +21,7 @@ #define _INCLUDE_WEBU_HTML_H_ void webu_html_badreq(struct webui_ctx *webui); - void webu_html_main(struct webui_ctx *webui); + void webu_html_user(struct webui_ctx *webui); + void webu_html_page(struct webui_ctx *webui); #endif diff --git a/src/webu_json.cpp b/src/webu_json.cpp new file mode 100644 index 00000000..56d9806c --- /dev/null +++ b/src/webu_json.cpp @@ -0,0 +1,297 @@ +/* + * This file is part of MotionPlus. + * + * MotionPlus 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. + * + * MotionPlus 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 MotionPlus. If not, see . + * + * Copyright 2020 MotionMrDave@gmail.com +*/ + +#include "motionplus.hpp" +#include "conf.hpp" +#include "logger.hpp" +#include "util.hpp" +#include "webu.hpp" +#include "webu_json.hpp" + +static void webu_json_config_item(struct webui_ctx *webui, int indx_cam, int indx_parm) +{ + int indx; + std::string parm_orig, parm_val, parm_list; + + parm_orig = ""; + parm_val = ""; + parm_list = ""; + + conf_edit_get(webui->motapp->cam_list[indx_cam] + , config_parms[indx_parm].parm_name + , parm_orig + , config_parms[indx_parm].parm_cat); + + if (parm_orig.find("\"") != std::string::npos) { + for (indx = 0; indx < (int)parm_orig.length(); indx++){ + if (parm_orig[indx] == '"') { + parm_val += '\\'; + } + parm_val += parm_orig[indx]; + } + } else { + parm_val = parm_orig; + } + + if (config_parms[indx_parm].parm_type == PARM_TYP_INT) { + webui->resp_page += + "\"" + config_parms[indx_parm].parm_name + "\"" + + ":{" + + " \"value\":" + parm_val + + ",\"enabled\":true" + + ",\"category\":" + std::to_string(config_parms[indx_parm].parm_cat) + + ",\"type\":\"" + conf_type_desc(config_parms[indx_parm].parm_type) + "\"" + + "}"; + + } else if (config_parms[indx_parm].parm_type == PARM_TYP_BOOL) { + if (parm_val == "on") { + webui->resp_page += + "\"" + config_parms[indx_parm].parm_name + "\"" + + ":{" + + " \"value\":true" + + ",\"enabled\":true" + + ",\"category\":" + std::to_string(config_parms[indx_parm].parm_cat) + + ",\"type\":\"" + conf_type_desc(config_parms[indx_parm].parm_type) + "\""+ + "}"; + } else { + webui->resp_page += + "\"" + config_parms[indx_parm].parm_name + "\"" + + ":{" + + " \"value\":false" + + ",\"enabled\":true" + + ",\"category\":" + std::to_string(config_parms[indx_parm].parm_cat) + + ",\"type\":\"" + conf_type_desc(config_parms[indx_parm].parm_type) + "\"" + + "}"; + } + } else if (config_parms[indx_parm].parm_type == PARM_TYP_LIST) { + conf_edit_list(webui->motapp->cam_list[indx_cam] + , config_parms[indx_parm].parm_name + , parm_list + , config_parms[indx_parm].parm_cat); + + webui->resp_page += + "\"" + config_parms[indx_parm].parm_name + "\"" + + ":{" + + " \"value\": \"" + parm_val + "\"" + + ",\"enabled\":true" + + ",\"category\":" + std::to_string(config_parms[indx_parm].parm_cat) + + ",\"type\":\"" + conf_type_desc(config_parms[indx_parm].parm_type) + "\"" + + ",\"list\":" + parm_list + + "}"; + + } else { + webui->resp_page += + "\"" + config_parms[indx_parm].parm_name + "\"" + + ":{" + + " \"value\":\"" + parm_val + "\"" + + ",\"enabled\":true"+ + ",\"category\":" + std::to_string(config_parms[indx_parm].parm_cat) + + ",\"type\":\""+ conf_type_desc(config_parms[indx_parm].parm_type) + "\"" + + "}"; + } + +} + +static void webu_json_config_parms(struct webui_ctx *webui, int indx_cam) +{ + int indx_parm, first; + std::string response; + + indx_parm = 0; + first = true; + while ((config_parms[indx_parm].parm_name != "") ) { + if ((config_parms[indx_parm].webui_level == WEBUI_LEVEL_NEVER)) { + indx_parm++; + continue; + } + if (first) { + first = false; + webui->resp_page += "{"; + } else { + webui->resp_page += ","; + } + if (config_parms[indx_parm].webui_level > webui->motapp->cam_list[0]->conf->webcontrol_parms) { + webui->resp_page += + "\""+config_parms[indx_parm].parm_name+"\"" + + ":{" + + " \"value\":\"\"" + + ",\"enabled\":false" + + ",\"category\":" + std::to_string(config_parms[indx_parm].parm_cat) + + ",\"type\":\""+ conf_type_desc(config_parms[indx_parm].parm_type) + "\"" + + "}"; + } else { + webu_json_config_item(webui, indx_cam, indx_parm); + } + indx_parm++; + } + webui->resp_page += "}"; + +} + +static void webu_json_config_cam_parms(struct webui_ctx *webui) +{ + int indx_cam, first; + + indx_cam = 0; + first = true; + while (webui->motapp->cam_list[indx_cam] != NULL) { + if (first) { + first = false; + webui->resp_page += "{"; + } else { + webui->resp_page += ","; + } + webui->resp_page += "\"cam" + + std::to_string(webui->motapp->cam_list[indx_cam]->conf->camera_id) + "\": "; + + webu_json_config_parms(webui, indx_cam); + + indx_cam++; + } + webui->resp_page += "}"; + + return; + +} + +static void webu_json_config_cam_list(struct webui_ctx *webui) +{ + int indx_cam; + std::string response; + + /* Get the count */ + indx_cam = 0; + while (webui->motapp->cam_list[indx_cam] != NULL) { + indx_cam++; + } + webui->resp_page += "{\"count\" : " + std::to_string(indx_cam - 1); + + indx_cam = 0; + while (webui->motapp->cam_list[indx_cam] != NULL) { + webui->resp_page += ",\""+ std::to_string(indx_cam) + "\":"; + + if (indx_cam == 0) { + webui->resp_page += "{\"name\": \"default\" "; + } else if (webui->motapp->cam_list[indx_cam]->conf->camera_name == "") { + webui->resp_page += "{\"name\": \"camera " + + std::to_string(webui->motapp->cam_list[indx_cam]->conf->camera_id) + "\""; + } else { + webui->resp_page += "{\"name\": \"" + + webui->motapp->cam_list[indx_cam]->conf->camera_name + "\""; + } + + webui->resp_page += ",\"id\": " + + std::to_string(webui->motapp->cam_list[indx_cam]->conf->camera_id); + + if (indx_cam == 0) { + webui->resp_page += "}"; + } else { + webui->resp_page += + ",\"url\": \"" + webui->hostfull + + "/" + std::to_string(webui->motapp->cam_list[indx_cam]->conf->camera_id) + + "/\"} "; + } + + indx_cam++; + } + webui->resp_page += "}"; + + return; + +} + +static void webu_json_config_categories(struct webui_ctx *webui) +{ + int indx_cat; + + webui->resp_page += "{"; + + indx_cat = 0; + while (indx_cat != PARM_CAT_MAX) { + if (indx_cat != 0) { + webui->resp_page += ","; + } + webui->resp_page += "\"" + std::to_string(indx_cat) + "\": "; + + if (indx_cat == PARM_CAT_00) { + webui->resp_page += "{\"name\":\"system\",\"display\":\"System\"}"; + } else if (indx_cat == PARM_CAT_01) { + webui->resp_page += "{\"name\":\"camera\",\"display\":\"Camera\"}"; + } else if (indx_cat == PARM_CAT_02) { + webui->resp_page += "{\"name\":\"source\",\"display\":\"Camera Source\"}"; + } else if (indx_cat == PARM_CAT_03) { + webui->resp_page += "{\"name\":\"image\",\"display\":\"Image\"}"; + } else if (indx_cat == PARM_CAT_04) { + webui->resp_page += "{\"name\":\"overlay\",\"display\":\"Overlays\"}"; + } else if (indx_cat == PARM_CAT_05) { + webui->resp_page += "{\"name\":\"method\",\"display\":\"Method\"}"; + } else if (indx_cat == PARM_CAT_06) { + webui->resp_page += "{\"name\":\"masks\",\"display\":\"Masks\"}"; + } else if (indx_cat == PARM_CAT_07) { + webui->resp_page += "{\"name\":\"detect\",\"display\":\"Detection\"}"; + } else if (indx_cat == PARM_CAT_08) { + webui->resp_page += "{\"name\":\"scripts\",\"display\":\"Scripts\"}"; + } else if (indx_cat == PARM_CAT_09) { + webui->resp_page += "{\"name\":\"picture\",\"display\":\"Picture\"}"; + } else if (indx_cat == PARM_CAT_10) { + webui->resp_page += "{\"name\":\"movie\",\"display\":\"Movie\"}"; + } else if (indx_cat == PARM_CAT_11) { + webui->resp_page += "{\"name\":\"timelapse\",\"display\":\"Timelapse\"}"; + } else if (indx_cat == PARM_CAT_12) { + webui->resp_page += "{\"name\":\"pipes\",\"display\":\"Pipes\"}"; + } else if (indx_cat == PARM_CAT_13) { + webui->resp_page += "{\"name\":\"webcontrol\",\"display\":\"Web Control\"}"; + } else if (indx_cat == PARM_CAT_14) { + webui->resp_page += "{\"name\":\"streams\",\"display\":\"Web Stream\"}"; + } else if (indx_cat == PARM_CAT_15) { + webui->resp_page += "{\"name\":\"database\",\"display\":\"Database\"}"; + } else if (indx_cat == PARM_CAT_16) { + webui->resp_page += "{\"name\":\"sql\",\"display\":\"SQL\"}"; + } else if (indx_cat == PARM_CAT_17) { + webui->resp_page += "{\"name\":\"track\",\"display\":\"Tracking\"}"; + } else { + webui->resp_page += "{\"name\":\"unk\",\"display\":\"Unknown\"}"; + } + indx_cat++; + } + + webui->resp_page += "}"; + + return; + +} + +void webu_json_config(struct webui_ctx *webui) +{ + webui->resp_type = WEBUI_RESP_JSON; + + webui->resp_page += "{\"version\" : \"" VERSION "\""; + + webui->resp_page += ",\"cameras\" : "; + webu_json_config_cam_list(webui); + + webui->resp_page += ",\"configuration\" : "; + webu_json_config_cam_parms(webui); + + webui->resp_page += ",\"categories\" : "; + webu_json_config_categories(webui); + + webui->resp_page += "}"; + +} diff --git a/src/webu_text.hpp b/src/webu_json.hpp similarity index 67% rename from src/webu_text.hpp rename to src/webu_json.hpp index 2ef81347..cee9bc46 100644 --- a/src/webu_text.hpp +++ b/src/webu_json.hpp @@ -17,14 +17,9 @@ * Copyright 2020 MotionMrDave@gmail.com */ -#ifndef _INCLUDE_WEBU_TEXT_H_ -#define _INCLUDE_WEBU_TEXT_H_ +#ifndef _INCLUDE_WEBU_JSON_H_ +#define _INCLUDE_WEBU_JSON_H_ - void webu_text_badreq(struct webui_ctx *webui); - void webu_text_main(struct webui_ctx *webui); - void webu_text_status(struct webui_ctx *webui); - void webu_text_connection(struct webui_ctx *webui); - void webu_text_list(struct webui_ctx *webui); - void webu_text_get_query(struct webui_ctx *webui); + void webu_json_config(struct webui_ctx *webui); #endif diff --git a/src/webu_post.cpp b/src/webu_post.cpp new file mode 100644 index 00000000..e018e67f --- /dev/null +++ b/src/webu_post.cpp @@ -0,0 +1,405 @@ +/* + * This file is part of MotionPlus. + * + * MotionPlus 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. + * + * MotionPlus 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 MotionPlus. If not, see . + * + * Copyright 2020 MotionMrDave@gmail.com +*/ + +#include "motionplus.hpp" +#include "conf.hpp" +#include "logger.hpp" +#include "util.hpp" +#include "webu.hpp" +#include "webu_post.hpp" + +/* Process the add camera action */ +static void webu_post_cam_add(struct webui_ctx *webui) +{ + int indx, maxcnt; + + MOTION_LOG(INF, TYPE_ALL, NO_ERRNO, "Adding camera."); + + maxcnt = 100; + + webui->motapp->cam_add = true; + indx = 0; + while ((webui->motapp->cam_add == true) && (indx < maxcnt)) { + SLEEP(0, 50000000) + indx++; + } + + if (indx == maxcnt) { + webui->motapp->cam_add = true; + MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "Error adding camera. Timed out"); + return; + } + + MOTION_LOG(INF, TYPE_ALL, NO_ERRNO, "New camera added."); + +} +/* Process the delete camera action */ +static void webu_post_cam_delete(struct webui_ctx *webui) +{ + int indx, maxcnt; + + if (webui->threadnbr == 0) { + MOTION_LOG(INF, TYPE_ALL, NO_ERRNO, "No camera specified for deletion." ); + return; + } else { + MOTION_LOG(INF, TYPE_ALL, NO_ERRNO, "Deleting camera."); + } + + maxcnt = 100; + + MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO, + _("Stopping cam %d"),webui->cam->camera_id); + webui->motapp->cam_list[webui->threadnbr]->restart_cam = false; + webui->motapp->cam_list[webui->threadnbr]->finish_cam = true; + + indx = 0; + while ((webui->motapp->cam_list[webui->threadnbr]->running_cam) && (indx < maxcnt)) { + SLEEP(0, 50000000) + indx++; + } + if (indx == maxcnt) { + MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "Error stopping camera. Timed out shutting down"); + return; + } + MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO, "Camera stopped"); + + webui->motapp->cam_delete = webui->threadnbr; + + indx = 0; + while ((webui->motapp->cam_delete > 0) && (indx < maxcnt)) { + SLEEP(0, 50000000) + indx++; + } + + if (indx == maxcnt) { + webui->motapp->cam_delete = 0; + MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO, "Error deleting camera. Timed out"); + return; + } + +} + +/* Get the command and thread number from the post data */ +void webu_post_cmdthr(struct webui_ctx *webui) +{ + int indx, camid; + + webui->post_cmd = ""; + webui->threadnbr = -1; + camid = -1; + + for (indx = 0; indx < webui->post_sz; indx++) { + if (mystreq(webui->post_info[indx].key_nm, "command")) { + webui->post_cmd = webui->post_info[indx].key_val; + } + if (mystreq(webui->post_info[indx].key_nm, "camid")) { + camid = atoi(webui->post_info[indx].key_val); + } + + MOTION_LOG(DBG, TYPE_STREAM, NO_ERRNO ,"key: %s value: %s " + , webui->post_info[indx].key_nm + , webui->post_info[indx].key_val + ); + } + + if (webui->post_cmd == "") { + MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO + , "Invalid post request. No command"); + return; + } + if (camid == -1) { + MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO + , "Invalid post request. No camera id provided"); + return; + } + + indx = 0; + while (webui->motapp->cam_list[indx] != NULL) { + if (webui->motapp->cam_list[indx]->camera_id == camid) { + webui->threadnbr = indx; + break; + } + indx++; + } + if (webui->threadnbr == -1) { + MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO + , "Invalid post request. Camid: %d not found" + , camid); + return; + } + +} + +/* Process the event end action */ +void webu_post_action_eventend(struct webui_ctx *webui) +{ + int indx; + + if (webui->threadnbr == 0) { + indx = 1; + while (webui->motapp->cam_list[indx]) { + webui->motapp->cam_list[indx]->event_stop = true; + indx++; + } + } else { + webui->motapp->cam_list[webui->threadnbr]->event_stop = true; + } + +} + +/* Process the event start action */ +void webu_post_action_eventstart(struct webui_ctx *webui) +{ + int indx; + + if (webui->threadnbr == 0) { + indx = 1; + while (webui->motapp->cam_list[indx]) { + webui->motapp->cam_list[indx]->event_user = true; + indx++; + } + } else { + webui->motapp->cam_list[webui->threadnbr]->event_user = true; + } + +} + +/* Process the snapshot action */ +void webu_post_action_snapshot(struct webui_ctx *webui) +{ + int indx; + + if (webui->threadnbr == 0) { + indx = 1; + while (webui->motapp->cam_list[indx]) { + webui->motapp->cam_list[indx]->snapshot = true; + indx++; + } + } else { + webui->motapp->cam_list[webui->threadnbr]->snapshot = true; + } + +} + +/* Process the pause action */ +void webu_post_action_pause(struct webui_ctx *webui) +{ + int indx; + + if (webui->threadnbr == 0) { + indx = 1; + while (webui->motapp->cam_list[indx]) { + webui->motapp->cam_list[indx]->pause = true; + indx++; + }; + } else { + webui->motapp->cam_list[webui->threadnbr]->pause = true; + } + +} + +/* Process the unpause action */ +void webu_post_action_unpause(struct webui_ctx *webui) +{ + int indx; + + if (webui->threadnbr == 0) { + indx = 1; + while (webui->motapp->cam_list[indx]) { + webui->motapp->cam_list[indx]->pause = false; + indx++; + }; + } else { + webui->motapp->cam_list[webui->threadnbr]->pause = false; + } + +} + +/* Process the restart action */ +void webu_post_action_restart(struct webui_ctx *webui) +{ + int indx; + + if (webui->threadnbr == 0) { + MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO, _("Restarting all cameras")); + indx = 1; + while (webui->motapp->cam_list[indx]) { + webui->motapp->cam_list[indx]->restart_cam = true; + if (webui->motapp->cam_list[indx]->running_cam) { + webui->motapp->cam_list[indx]->event_stop = true; + webui->motapp->cam_list[indx]->finish_cam = true; + } + indx++; + } + } else { + MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO + , _("Restarting camera %d") + , webui->motapp->cam_list[webui->threadnbr]->camera_id); + webui->motapp->cam_list[webui->threadnbr]->restart_cam = true; + webui->motapp->cam_list[webui->threadnbr]->finish_cam = false; + } + +} + +/* Process the stop action */ +void webu_post_action_stop(struct webui_ctx *webui) +{ + int indx; + + if (webui->threadnbr == 0) { + indx = 1; + while (webui->motapp->cam_list[indx]) { + MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO, + _("Stopping cam %d"),webui->motapp->cam_list[indx]->camera_id); + webui->motapp->cam_list[indx]->restart_cam = false; + webui->motapp->cam_list[indx]->event_stop = true; + webui->motapp->cam_list[indx]->event_user = true; + webui->motapp->cam_list[indx]->finish_cam = true; + indx++; + } + } else { + MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO + , _("Stopping cam %d") + , webui->motapp->cam_list[webui->threadnbr]->camera_id); + webui->motapp->cam_list[webui->threadnbr]->restart_cam = false; + webui->motapp->cam_list[webui->threadnbr]->event_stop = true; + webui->motapp->cam_list[webui->threadnbr]->event_user = true; + webui->motapp->cam_list[webui->threadnbr]->finish_cam = true; + } + +} + +/* Process the configuration parameters */ +static void webu_post_config(struct webui_ctx *webui) +{ + int indx, indx2; + bool ismotapp; + std::string tmpname; + + for (indx = 0; indx < webui->post_sz; indx++) { + if (mystrne(webui->post_info[indx].key_nm, "command") && + mystrne(webui->post_info[indx].key_nm, "camid")) { + + tmpname = webui->post_info[indx].key_nm; + indx2=0; + while (config_parms_depr[indx2].parm_name != "") { + if (config_parms_depr[indx2].parm_name == tmpname) { + tmpname = config_parms_depr[indx2].newname; + break; + } + indx2++; + } + + /* Ignore any requests for parms above webcontrol_parms level. */ + indx2=0; + while (config_parms[indx2].parm_name != "") { + if ((config_parms[indx2].webui_level > webui->motapp->cam_list[0]->conf->webcontrol_parms) || + (config_parms[indx2].webui_level == WEBUI_LEVEL_NEVER) ) { + indx2++; + continue; + } + if (tmpname == config_parms[indx2].parm_name) { + break; + } + indx2++; + } + + if (config_parms[indx2].parm_name != "") { + + if (config_parms[indx2].parm_cat == PARM_CAT_00) { + ismotapp = true; + } else { + ismotapp = false; + } + + conf_edit_set(webui->motapp, ismotapp + , webui->threadnbr + , config_parms[indx2].parm_name + , webui->post_info[indx].key_val); + + /* If changing language, do it now */ + if (config_parms[indx2].parm_name == "native_language") { + if (webui->motapp->native_language) { + mytranslate_text("", true); + MOTION_LOG(INF, TYPE_ALL, NO_ERRNO,_("Native Language : on")); + } else { + mytranslate_text("", false); + MOTION_LOG(INF, TYPE_ALL, NO_ERRNO,_("Native Language : off")); + } + } + } + } + } + + + +} + +/* Process the actions from the webcontrol that the user requested */ +void webu_post_main(struct webui_ctx *webui) +{ + + webu_post_cmdthr(webui); + + if ((webui->post_cmd == "") || (webui->threadnbr == -1)) { + return; + } + + if (webui->post_cmd == "eventend") { + webu_post_action_eventend(webui); + + } else if (webui->post_cmd == "eventstart") { + webu_post_action_eventstart(webui); + + } else if (webui->post_cmd == "snapshot") { + webu_post_action_snapshot(webui); + + } else if (webui->post_cmd == "pause") { + webu_post_action_pause(webui); + + } else if (webui->post_cmd == "unpause") { + webu_post_action_unpause(webui); + + } else if (webui->post_cmd == "restart") { + webu_post_action_restart(webui); + + } else if (webui->post_cmd == "stop") { + webu_post_action_stop(webui); + + } else if (webui->post_cmd == "write") { + conf_parms_write(webui->motapp); + + } else if (webui->post_cmd == "add") { + webu_post_cam_add(webui); + + } else if (webui->post_cmd == "delete") { + webu_post_cam_delete(webui); + + } else if (webui->post_cmd == "config") { + webu_post_config(webui); + + } else { + MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO + , _("Invalid action requested: command: >%s< threadnbr : >%d< ") + , webui->post_cmd.c_str(), webui->threadnbr); + return; + } + +} + diff --git a/src/webu_post.hpp b/src/webu_post.hpp new file mode 100644 index 00000000..460ad195 --- /dev/null +++ b/src/webu_post.hpp @@ -0,0 +1,25 @@ +/* + * This file is part of MotionPlus. + * + * MotionPlus 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. + * + * MotionPlus 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 MotionPlus. If not, see . + * + * Copyright 2020 MotionMrDave@gmail.com +*/ + +#ifndef _INCLUDE_WEBU_POST_H_ +#define _INCLUDE_WEBU_POST_H_ + + void webu_post_main(struct webui_ctx *webui); + +#endif diff --git a/src/webu_stream.cpp b/src/webu_stream.cpp index 34808f24..9d568607 100644 --- a/src/webu_stream.cpp +++ b/src/webu_stream.cpp @@ -17,14 +17,6 @@ * Copyright 2020 MotionMrDave@gmail.com */ -/* - * Functional naming scheme - * webu_stream* - All functions in this module - * webu_stream_mjpeg* - Create the motion-jpeg stream for the user - * webu_stream_static* - Create the static jpg image for the user. - * webu_stream_checks - Edit/validate request from user - */ - #include "motionplus.hpp" #include "conf.hpp" #include "logger.hpp" @@ -39,9 +31,12 @@ static void webu_stream_mjpeg_checkbuffers(struct webui_ctx *webui) { if (webui->resp_size < (size_t)webui->cam->imgs.size_norm){ - if (webui->resp_page != NULL) free(webui->resp_page); - webui->resp_page =(char*) mymalloc(webui->cam->imgs.size_norm); - memset(webui->resp_page,'\0',webui->cam->imgs.size_norm); + if (webui->resp_image != NULL) { + free(webui->resp_image); + webui->resp_image = NULL; + } + webui->resp_image =(char*) mymalloc(webui->cam->imgs.size_norm); + memset(webui->resp_image,'\0',webui->cam->imgs.size_norm); webui->resp_size = webui->cam->imgs.size_norm; webui->resp_used = 0; } @@ -84,7 +79,7 @@ static void webu_stream_mjpeg_getimg(struct webui_ctx *webui) int header_len; struct ctx_stream_data *local_stream; - memset(webui->resp_page, '\0', webui->resp_size); + memset(webui->resp_image, '\0', webui->resp_size); /* Assign to a local pointer the stream we want */ if (webui->cnct_type == WEBUI_CNCT_FULL){ @@ -108,10 +103,11 @@ static void webu_stream_mjpeg_getimg(struct webui_ctx *webui) /* Copy jpg from the motion loop thread */ pthread_mutex_lock(&webui->cam->stream.mutex); - if ((!webui->cam->detecting_motion) && (webui->cam->conf->stream_motion)){ + if ((!webui->cam->detecting_motion) && + (webui->motapp->cam_list[webui->threadnbr]->conf->stream_motion)){ webui->stream_fps = 1; } else { - webui->stream_fps = webui->cam->conf->stream_maxrate; + webui->stream_fps = webui->motapp->cam_list[webui->threadnbr]->conf->stream_maxrate; } if (local_stream->jpeg_data == NULL) { pthread_mutex_unlock(&webui->cam->stream.mutex); @@ -123,18 +119,19 @@ static void webu_stream_mjpeg_getimg(struct webui_ctx *webui) "Content-type: image/jpeg\r\n" "Content-Length: %9ld\r\n\r\n" ,jpeg_size); - memcpy(webui->resp_page, resp_head, header_len); - memcpy(webui->resp_page + header_len + memcpy(webui->resp_image, resp_head, header_len); + memcpy(webui->resp_image + header_len ,local_stream->jpeg_data ,jpeg_size); /* Copy in the terminator after the jpg data at the end*/ - memcpy(webui->resp_page + header_len + jpeg_size,"\r\n",2); + memcpy(webui->resp_image + header_len + jpeg_size,"\r\n",2); webui->resp_used = header_len + jpeg_size + 2; local_stream->consumed = true; pthread_mutex_unlock(&webui->cam->stream.mutex); } +/* Callback function for mhd to get stream */ static ssize_t webu_stream_mjpeg_response (void *cls, uint64_t pos, char *buf, size_t max) { /* This is the callback response function for MHD streams. It is kept "open" and @@ -169,7 +166,7 @@ static ssize_t webu_stream_mjpeg_response (void *cls, uint64_t pos, char *buf, s sent_bytes = webui->resp_used - webui->stream_pos; } - memcpy(buf, webui->resp_page + webui->stream_pos, sent_bytes); + memcpy(buf, webui->resp_image + webui->stream_pos, sent_bytes); webui->stream_pos = webui->stream_pos + sent_bytes; if (webui->stream_pos >= webui->resp_used){ @@ -180,23 +177,45 @@ static ssize_t webu_stream_mjpeg_response (void *cls, uint64_t pos, char *buf, s } -/* Obtain the current image, compress it to a JPG and put into webui->resp_page */ +/* Obtain the current image, compress it to a JPG and put into webui->resp_image */ static void webu_stream_static_getimg(struct webui_ctx *webui) { - webui->resp_used = 0; - memset(webui->resp_page, '\0', webui->resp_size); + struct ctx_stream_data *local_stream; + + webui->resp_used = 0; + memset(webui->resp_image, '\0', webui->resp_size); + + /* Assign to a local pointer the stream we want */ + if (webui->cnct_type == WEBUI_CNCT_FULL){ + local_stream = &webui->cam->stream.norm; + + } else if (webui->cnct_type == WEBUI_CNCT_SUB){ + local_stream = &webui->cam->stream.sub; + + } else if (webui->cnct_type == WEBUI_CNCT_MOTION){ + local_stream = &webui->cam->stream.motion; + + } else if (webui->cnct_type == WEBUI_CNCT_SOURCE){ + local_stream = &webui->cam->stream.source; + + } else if (webui->cnct_type == WEBUI_CNCT_SECONDARY){ + local_stream = &webui->cam->stream.secondary; + + } else { + return; + } pthread_mutex_lock(&webui->cam->stream.mutex); - if (webui->cam->stream.norm.jpeg_data == NULL){ + if (local_stream->jpeg_data == NULL){ pthread_mutex_unlock(&webui->cam->stream.mutex); return; } - memcpy(webui->resp_page - ,webui->cam->stream.norm.jpeg_data - ,webui->cam->stream.norm.jpeg_size); - webui->resp_used = webui->cam->stream.norm.jpeg_size; - webui->cam->stream.norm.consumed = true; + memcpy(webui->resp_image + ,local_stream->jpeg_data + ,local_stream->jpeg_size); + webui->resp_used =local_stream->jpeg_size; + local_stream->consumed = true; pthread_mutex_unlock(&webui->cam->stream.mutex); } @@ -205,45 +224,20 @@ static void webu_stream_static_getimg(struct webui_ctx *webui) static int webu_stream_checks(struct webui_ctx *webui) { pthread_mutex_lock(&webui->motapp->mutex_camlst); - if ((webui->motapp->cam_list != NULL) && (webui->thread_nbr >= webui->cam_threads)){ + if (webui->threadnbr >= webui->cam_threads) { MOTION_LOG(ERR, TYPE_STREAM, NO_ERRNO , _("Invalid thread specified: %s"),webui->url); pthread_mutex_unlock(&webui->motapp->mutex_camlst); return -1; } - if ((webui->motapp->cam_list != NULL) && (webui->thread_nbr < 0) && (webui->cam_threads > 1)){ + if (webui->threadnbr <= 0) { MOTION_LOG(ERR, TYPE_STREAM, NO_ERRNO , _("Invalid thread specified: %s"),webui->url); pthread_mutex_unlock(&webui->motapp->mutex_camlst); return -1; } - /* Thread numbers are not used for ctx_cam specific ports. */ - if ((webui->motapp->cam_list == NULL) && (webui->thread_nbr >= 0)) { - MOTION_LOG(ERR, TYPE_STREAM, NO_ERRNO - , _("Invalid URL for a camera specific port: %s"),webui->url); - pthread_mutex_unlock(&webui->motapp->mutex_camlst); - return -1; - } - - /* If multiple threads then thread zero is invalid. */ - if ((webui->cam_threads > 1) && (webui->thread_nbr == 0)) { - MOTION_LOG(ERR, TYPE_STREAM, NO_ERRNO - , _("URL for thread 0 is not valid when using camera specific files.: %s") - ,webui->url); - pthread_mutex_unlock(&webui->motapp->mutex_camlst); - return -1; - } - - /* Thread numbers are not used for ctx_cam specific ports. */ - if ((webui->motapp->cam_list == NULL) && (strlen(webui->uri_cmd1) > 0)) { - MOTION_LOG(ERR, TYPE_STREAM, NO_ERRNO - , _("Bad URL for a camera specific port: %s"),webui->url); - pthread_mutex_unlock(&webui->motapp->mutex_camlst); - return -1; - } - pthread_mutex_unlock(&webui->motapp->mutex_camlst); return 0; @@ -280,7 +274,7 @@ static void webu_stream_cnct_count(struct webui_ctx *webui) pthread_mutex_unlock(&webui->cam->stream.mutex); } else { - /* Stream, Static */ + /* Stream */ pthread_mutex_lock(&webui->cam->stream.mutex); webui->cam->stream.norm.cnct_count++; cnct_count = webui->cam->stream.norm.cnct_count; @@ -296,7 +290,38 @@ static void webu_stream_cnct_count(struct webui_ctx *webui) } -mhdrslt webu_stream_mjpeg(struct webui_ctx *webui) +/* Assign the type of stream that is being answered*/ +static void webu_stream_type(struct webui_ctx *webui) +{ + if (webui->uri_cmd2 == "stream") { + webui->cnct_type = WEBUI_CNCT_FULL; + + } else if (webui->uri_cmd2 == "substream") { + webui->cnct_type = WEBUI_CNCT_SUB; + + } else if (webui->uri_cmd2 == "motion") { + webui->cnct_type = WEBUI_CNCT_MOTION; + + } else if (webui->uri_cmd2 == "source") { + webui->cnct_type = WEBUI_CNCT_SOURCE; + + } else if (webui->uri_cmd2 == "secondary") { + if (webui->cam->algsec_inuse) { + webui->cnct_type = WEBUI_CNCT_SECONDARY; + } else { + webui->cnct_type = WEBUI_CNCT_UNKNOWN; + } + + } else if (webui->uri_cmd2 == "") { + webui->cnct_type = WEBUI_CNCT_FULL; + + } else { + webui->cnct_type = WEBUI_CNCT_UNKNOWN; + } + +} + +static mhdrslt webu_stream_mjpeg(struct webui_ctx *webui) { /* Create the stream for the motion jpeg */ mhdrslt retcd; @@ -317,11 +342,9 @@ mhdrslt webu_stream_mjpeg(struct webui_ctx *webui) return MHD_NO; } - MHD_add_response_header(response, MHD_HTTP_HEADER_CACHE_CONTROL, "no-store"); - - if (webui->cam->conf->stream_cors_header != ""){ + if (webui->motapp->cam_list[0]->conf->webcontrol_cors_header != ""){ MHD_add_response_header(response, MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN - , webui->cam->conf->stream_cors_header.c_str()); + , webui->motapp->cam_list[0]->conf->webcontrol_cors_header.c_str()); } MHD_add_response_header(response, MHD_HTTP_HEADER_CONTENT_TYPE @@ -334,17 +357,15 @@ mhdrslt webu_stream_mjpeg(struct webui_ctx *webui) return retcd; } -mhdrslt webu_stream_static(struct webui_ctx *webui) +/* Create the response for the static image request*/ +static mhdrslt webu_stream_static(struct webui_ctx *webui) { - /* Create the response for the static image request*/ mhdrslt retcd; struct MHD_Response *response; char resp_used[20]; if (webu_stream_checks(webui) == -1) return MHD_NO; - webui->cam->stream.norm.consumed = true; - webu_stream_cnct_count(webui); webu_stream_mjpeg_checkbuffers(webui); @@ -357,17 +378,15 @@ mhdrslt webu_stream_static(struct webui_ctx *webui) } response = MHD_create_response_from_buffer (webui->resp_size - ,(void *)webui->resp_page, MHD_RESPMEM_MUST_COPY); + ,(void *)webui->resp_image, MHD_RESPMEM_MUST_COPY); if (!response){ MOTION_LOG(ERR, TYPE_STREAM, NO_ERRNO, _("Invalid response")); return MHD_NO; } - MHD_add_response_header(response, MHD_HTTP_HEADER_CACHE_CONTROL, "no-store"); - - if (webui->cam->conf->stream_cors_header != ""){ + if (webui->motapp->cam_list[0]->conf->webcontrol_cors_header != ""){ MHD_add_response_header (response, MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN - , webui->cam->conf->stream_cors_header.c_str()); + , webui->motapp->cam_list[0]->conf->webcontrol_cors_header.c_str()); } MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "image/jpeg"); @@ -380,12 +399,31 @@ mhdrslt webu_stream_static(struct webui_ctx *webui) return retcd; } +/* Entry point for answering stream*/ +mhdrslt webu_stream_main(struct webui_ctx *webui) +{ + mhdrslt retcd; + + if (webui->cam->passflag == 0) { + return MHD_NO; + } + + webu_stream_type(webui); + + if (webui->uri_cmd1 == "static") { + retcd = webu_stream_static(webui); + } else { + retcd = webu_stream_mjpeg(webui); + } + + return retcd; +} + +/* Initial the stream context items for the camera */ void webu_stream_init(struct ctx_cam *cam) { + /* NOTE: This runs on the motion_loop thread. */ - /* The image buffers are allocated in event_stream_put if needed - * NOTE: This runs on the motion_loop thread. - */ pthread_mutex_init(&cam->stream.mutex, NULL); cam->imgs.image_substream = NULL; @@ -393,36 +431,34 @@ void webu_stream_init(struct ctx_cam *cam) cam->stream.norm.jpeg_size = 0; cam->stream.norm.jpeg_data = NULL; cam->stream.norm.cnct_count = 0; - cam->stream.norm.consumed = false; + cam->stream.norm.consumed = true; cam->stream.sub.jpeg_size = 0; cam->stream.sub.jpeg_data = NULL; cam->stream.sub.cnct_count = 0; - cam->stream.sub.consumed = false; + cam->stream.sub.consumed = true; cam->stream.motion.jpeg_size = 0; cam->stream.motion.jpeg_data = NULL; cam->stream.motion.cnct_count = 0; - cam->stream.motion.consumed = false; + cam->stream.motion.consumed = true; cam->stream.source.jpeg_size = 0; cam->stream.source.jpeg_data = NULL; cam->stream.source.cnct_count = 0; - cam->stream.source.consumed = false; + cam->stream.source.consumed = true; cam->stream.secondary.jpeg_size = 0; cam->stream.secondary.jpeg_data = NULL; cam->stream.secondary.cnct_count = 0; + cam->stream.source.consumed = true; } +/* Free the stream buffers and mutex for shutdown */ void webu_stream_deinit(struct ctx_cam *cam) { - - /* Need to check whether buffers were allocated since init - * function defers the allocations to event_stream_put - * NOTE: This runs on the motion_loop thread. - */ + /* NOTE: This runs on the motion_loop thread. */ pthread_mutex_destroy(&cam->stream.mutex); @@ -458,6 +494,7 @@ void webu_stream_deinit(struct ctx_cam *cam) } +/* Get a normal image from the motion loop and compress it*/ static void webu_stream_getimg_norm(struct ctx_cam *cam, struct ctx_image_data *img_data) { /*This is on the motion_loop thread */ @@ -477,6 +514,7 @@ static void webu_stream_getimg_norm(struct ctx_cam *cam, struct ctx_image_data * } +/* Get a substream image from the motion loop and compress it*/ static void webu_stream_getimg_sub(struct ctx_cam *cam, struct ctx_image_data *img_data) { /*This is on the motion_loop thread */ @@ -521,6 +559,7 @@ static void webu_stream_getimg_sub(struct ctx_cam *cam, struct ctx_image_data *i } +/* Get a motion image from the motion loop and compress it*/ static void webu_stream_getimg_motion(struct ctx_cam *cam) { /*This is on the motion_loop thread */ @@ -541,6 +580,7 @@ static void webu_stream_getimg_motion(struct ctx_cam *cam) } +/* Get a source image from the motion loop and compress it*/ static void webu_stream_getimg_source(struct ctx_cam *cam) { /*This is on the motion_loop thread */ @@ -561,6 +601,7 @@ static void webu_stream_getimg_source(struct ctx_cam *cam) } +/* Get a secondary image from the motion loop and compress it*/ static void webu_stream_getimg_secondary(struct ctx_cam *cam) { /*This is on the motion_loop thread */ @@ -582,6 +623,7 @@ static void webu_stream_getimg_secondary(struct ctx_cam *cam) } +/* Get image from the motion loop and compress it*/ void webu_stream_getimg(struct ctx_cam *cam, struct ctx_image_data *img_data) { diff --git a/src/webu_stream.hpp b/src/webu_stream.hpp index 875fe5ca..a2b42e9d 100644 --- a/src/webu_stream.hpp +++ b/src/webu_stream.hpp @@ -26,7 +26,6 @@ void webu_stream_deinit(struct ctx_cam *cam); void webu_stream_getimg(struct ctx_cam *cam, struct ctx_image_data *img_data); - mhdrslt webu_stream_mjpeg(struct webui_ctx *webui); - mhdrslt webu_stream_static(struct webui_ctx *webui); + mhdrslt webu_stream_main(struct webui_ctx *webui); #endif diff --git a/src/webu_text.cpp b/src/webu_text.cpp deleted file mode 100644 index 2dfd10c9..00000000 --- a/src/webu_text.cpp +++ /dev/null @@ -1,1235 +0,0 @@ -/* - * This file is part of MotionPlus. - * - * MotionPlus 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. - * - * MotionPlus 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 MotionPlus. If not, see . - * - * Copyright 2020 MotionMrDave@gmail.com -*/ - -/* - * This module processes the requests associated with the text inferface - * of the webcontrol. This interface is intended to be used by programs - * and does not have any user interface to navigate. The same actions - * are available as the HTML as well as a few more. - * Additional functions not directly available via HTML - * get: Returns the value of a parameter. - * stop: Stops the camera thread - * list: Lists all the configuration parameters and values - * status Whether the camera is in pause mode. - * connection Whether the camera connection is working - * - */ - -#include "motionplus.hpp" -#include "conf.hpp" -#include "logger.hpp" -#include "util.hpp" -#include "webu.hpp" -#include "webu_text.hpp" - -static void webu_text_seteol(struct webui_ctx *webui) -{ - /* Set the end of line character for text interface */ - if (webui->motapp->cam_list[0]->conf->webcontrol_interface == 2) { - snprintf(webui->text_eol, WEBUI_LEN_PARM,"%s","
"); - } else { - snprintf(webui->text_eol, WEBUI_LEN_PARM,"%s",""); - } - -} - -static void webu_text_camera_name(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - if (webui->motapp->cam_list[webui->thread_nbr]->conf->camera_name == ""){ - snprintf(response,sizeof(response), - "Camera %s %s\n" - ,webui->uri_camid,webui->text_eol - ); - } else { - snprintf(response,sizeof(response), - "Camera %s %s\n" - ,webui->motapp->cam_list[webui->thread_nbr]->conf->camera_name.c_str() - ,webui->text_eol - ); - } - webu_write(webui, response); - -} - -static void webu_text_back(struct webui_ctx *webui, const char *prevuri) -{ - char response[WEBUI_LEN_RESP]; - - if (webui->motapp->cam_list[0]->conf->webcontrol_interface == 2) { - snprintf(response,sizeof(response), - "<- back

\n" - ,webui->uri_camid, prevuri - ); - webu_write(webui, response); - } - -} - -static void webu_text_header(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - if (webui->motapp->cam_list[0]->conf->webcontrol_interface == 2) { - snprintf(response, sizeof (response),"%s", - "\n" - "\n" - "MotionPlus " VERSION " \n" - "\n" - "\n"); - webu_write(webui, response); - } -} - -static void webu_text_trailer(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - if (webui->motapp->cam_list[0]->conf->webcontrol_interface == 2) { - snprintf(response, sizeof (response),"%s", - "\n" - "\n"); - webu_write(webui, response); - } - -} - -void webu_text_badreq(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webu_text_header(webui); - snprintf(response, sizeof (response), - "Bad Request %s\n" - "The server did not understand your request. %s\n" - ,webui->text_eol, webui->text_eol - ); - webu_write(webui, response); - webu_text_trailer(webui); - - return; -} - -static void webu_text_page_raw(struct webui_ctx *webui) -{ - /* Write the main page text */ - char response[WEBUI_LEN_RESP]; - int indx; - - snprintf(response, sizeof (response), - "MotionPlus " VERSION " Running [%d] Camera%s \n" - ,webui->cam_count - ,(webui->cam_count > 1 ? "s" : "") - ); - webu_write(webui, response); - - if (webui->cam_threads > 1){ - for (indx = 1; indx < webui->cam_threads; indx++) { - snprintf(response, sizeof (response), - "%d \n" - ,webui->motapp->cam_list[indx]->camera_id - ); - webu_write(webui, response); - } - } - -} - -static void webu_text_page_basic(struct webui_ctx *webui) -{ - /* Write the main page text */ - char response[WEBUI_LEN_RESP]; - int indx; - - webu_text_header(webui); - snprintf(response, sizeof (response), - "MotionPlus " VERSION " Running [%d] Camera%s
\n" - "All
\n" - ,webui->cam_count, (webui->cam_count > 1 ? "s" : "") - ,webui->motapp->cam_list[0]->camera_id); - webu_write(webui, response); - - if (webui->cam_threads > 1){ - for (indx = 1; indx < webui->cam_threads; indx++) { - if (webui->motapp->cam_list[indx]->conf->camera_name == ""){ - snprintf(response, sizeof (response), - "Camera %d
\n" - , webui->motapp->cam_list[indx]->camera_id - , indx); - webu_write(webui, response); - } else { - snprintf(response, sizeof (response), - "Camera %s
\n" - , webui->motapp->cam_list[indx]->camera_id - ,webui->motapp->cam_list[indx]->conf->camera_name.c_str()); - webu_write(webui, response); - } - } - } - webu_text_trailer(webui); - -} - -static void webu_text_list_raw(struct webui_ctx *webui) -{ - /* Write out the options and values */ - char response[WEBUI_LEN_RESP]; - int indx_parm,retcd; - char val_parm[PATH_MAX]; - - indx_parm = 0; - while (config_parms[indx_parm].parm_name != ""){ - - if ((config_parms[indx_parm].webui_level > webui->motapp->cam_list[0]->conf->webcontrol_parms) || - (config_parms[indx_parm].webui_level == WEBUI_LEVEL_NEVER) || - ((webui->thread_nbr != 0) && (config_parms[indx_parm].main_thread != 0))){ - indx_parm++; - continue; - } - - conf_edit_get(webui->motapp->cam_list[webui->thread_nbr], config_parms[indx_parm].parm_name - , val_parm, config_parms[indx_parm].parm_cat); - if (val_parm == NULL){ - conf_edit_get(webui->motapp->cam_list[0], config_parms[indx_parm].parm_name - , val_parm, config_parms[indx_parm].parm_cat); - } - retcd = snprintf(response, sizeof (response), - " %s = %s \n" - ,config_parms[indx_parm].parm_name.c_str() - ,val_parm - ); - if (retcd <0) MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO, _("Error option")); - webu_write(webui, response); - - indx_parm++; - } - -} - -static void webu_text_list_basic(struct webui_ctx *webui) -{ - /* Write out the options and values */ - char response[WEBUI_LEN_RESP]; - int indx_parm,retcd; - char val_parm[PATH_MAX]; - - webu_text_header(webui); - - snprintf(response,sizeof(response), - "<- back

" - ,webui->uri_camid - ); - webu_write(webui, response); - - webu_text_camera_name(webui); - - snprintf(response,sizeof(response),"%s","
    \n"); - webu_write(webui, response); - - indx_parm = 0; - while (config_parms[indx_parm].parm_name != ""){ - - if ((config_parms[indx_parm].webui_level > webui->motapp->cam_list[0]->conf->webcontrol_parms) || - (config_parms[indx_parm].webui_level == WEBUI_LEVEL_NEVER) || - ((webui->thread_nbr != 0) && (config_parms[indx_parm].main_thread != 0))){ - indx_parm++; - continue; - } - - conf_edit_get(webui->motapp->cam_list[webui->thread_nbr], config_parms[indx_parm].parm_name - , val_parm, config_parms[indx_parm].parm_cat); - if (val_parm == NULL){ - conf_edit_get(webui->motapp->cam_list[0], config_parms[indx_parm].parm_name - , val_parm, config_parms[indx_parm].parm_cat); - } - retcd = snprintf(response, sizeof (response), - "
  • %s = %s
  • \n" - ,webui->uri_camid - ,config_parms[indx_parm].parm_name.c_str() - ,config_parms[indx_parm].parm_name.c_str() - ,val_parm); - if (retcd <0) MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO, _("Error option")); - webu_write(webui, response); - - indx_parm++; - } - - snprintf(response,sizeof(response),"%s","
\n"); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -static void webu_text_set_menu(struct webui_ctx *webui) -{ - - /* Write out the options and values to allow user to set them*/ - char response[WEBUI_LEN_RESP]; - int indx_parm; - char val_parm[PATH_MAX]; - - webu_text_header(webui); - - webu_text_back(webui,"/config"); - - webu_text_camera_name(webui); - - snprintf(response, sizeof (response),"%s", - "\n" - "
\n" - "\n" - "
\n" - "
\n" - "\n" - "\n" - "
\n" - ); - webu_write(webui, response); - - webu_text_trailer(webui); - - -} - -static void webu_text_set_query(struct webui_ctx *webui) -{ - - /* Write out the options and values to allow user to set them*/ - char response[WEBUI_LEN_RESP]; - int indx_parm,retcd; - char val_parm[PATH_MAX]; - - webu_text_header(webui); - - webu_text_back(webui,"/config/list"); - - webu_text_camera_name(webui); - - indx_parm = 0; - while (config_parms[indx_parm].parm_name != ""){ - - if ((config_parms[indx_parm].webui_level > webui->motapp->cam_list[0]->conf->webcontrol_parms) || - (config_parms[indx_parm].webui_level == WEBUI_LEVEL_NEVER) || - ((webui->thread_nbr != 0) && (config_parms[indx_parm].main_thread != 0)) || - (mystrne(webui->uri_parm1, config_parms[indx_parm].parm_name.c_str()))) { - indx_parm++; - continue; - } - - conf_edit_get(webui->motapp->cam_list[webui->thread_nbr], config_parms[indx_parm].parm_name - , val_parm, config_parms[indx_parm].parm_cat); - if (val_parm == NULL){ - conf_edit_get(webui->motapp->cam_list[0], config_parms[indx_parm].parm_name - , val_parm, config_parms[indx_parm].parm_cat); - } - retcd = snprintf(response, sizeof (response), - "
\n" - "%s \n" - "\n" - ,config_parms[indx_parm].parm_name.c_str() - ,config_parms[indx_parm].parm_name.c_str() - ,val_parm - ); - if (retcd <0) MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO, _("Error option")); - webu_write(webui, response); - - break; - - indx_parm++; - } - - webu_text_trailer(webui); - -} - -static void webu_text_set_assign(struct webui_ctx *webui) -{ - /* Set a particular configuration parameter to desired value */ - - char response[WEBUI_LEN_RESP]; - int retcd; - - retcd = webu_process_config(webui); - - if (retcd == 0){ - webu_text_header(webui); - - webu_text_back(webui,"/config"); - - snprintf(response,sizeof(response), - "%s = %s %s\n" - "Done %s\n" - ,webui->uri_parm1 - ,webui->uri_value1 - ,webui->text_eol, webui->text_eol - ); - webu_write(webui, response); - - webu_text_trailer(webui); - } else { - webu_text_badreq(webui); - } - -} - -static void webu_text_get_menu(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - int indx_parm; - - webu_text_header(webui); - - webu_text_back(webui,"/config"); - - webu_text_camera_name(webui); - - snprintf(response, sizeof (response),"%s", - "\n" - "\n" - "\n" - "
\n" - ); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -static void webu_text_action_stop(struct webui_ctx *webui) -{ - /* Shut down MotionPlus or the associated thread */ - char response[WEBUI_LEN_RESP]; - - webu_process_action(webui); - - webu_text_back(webui,"/action"); - - webu_text_header(webui); - snprintf(response,sizeof(response), - "Stopping camera ... bye %s\nDone %s\n" - ,webui->text_eol, webui->text_eol - ); - webu_write(webui, response); - webu_text_trailer(webui); - -} - -static void webu_text_action_makemovie(struct webui_ctx *webui) -{ - /* end the event. Legacy api name*/ - - char response[WEBUI_LEN_RESP]; - - webu_process_action(webui); - - webu_text_back(webui,"/action"); - - webu_text_header(webui); - - snprintf(response,sizeof(response) - ,"makemovie for camera %d %s\nDone%s\n" - ,webui->cam->camera_id - ,webui->text_eol,webui->text_eol - ); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -static void webu_text_action_eventstart(struct webui_ctx *webui) -{ - /* Start the event*/ - - char response[WEBUI_LEN_RESP]; - - webu_process_action(webui); - - webu_text_header(webui); - - webu_text_back(webui,"/action"); - - snprintf(response,sizeof(response) - ,"Start event for camera %d %s\nDone%s\n" - ,webui->cam->camera_id - ,webui->text_eol,webui->text_eol - ); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -static void webu_text_action_eventend(struct webui_ctx *webui) -{ - /* End any active event*/ - - char response[WEBUI_LEN_RESP]; - - webu_process_action(webui); - - webu_text_header(webui); - - webu_text_back(webui,"/action"); - - snprintf(response,sizeof(response) - ,"End event for camera %d %s\nDone %s\n" - ,webui->cam->camera_id - ,webui->text_eol,webui->text_eol - ); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -/* trigger a snapshot*/ -static void webu_text_action_snapshot(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webu_process_action(webui); - - webu_text_header(webui); - - webu_text_back(webui,"/action"); - - snprintf(response,sizeof(response) - ,"Snapshot for camera %d %s\nDone%s\n" - ,webui->cam->camera_id - ,webui->text_eol,webui->text_eol - ); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -/* Restart*/ -static void webu_text_action_restart(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webu_process_action(webui); - - webu_text_header(webui); - - webu_text_back(webui,"/action"); - - snprintf(response,sizeof(response) - ,"Restart in progress ...%s\nDone %s\n" - ,webui->text_eol,webui->text_eol - ); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -static void webu_text_action_add(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webu_process_action(webui); - - webu_text_header(webui); - - webu_text_back(webui,"/action"); - - snprintf(response,sizeof(response) - ,"Camera added %s\nDone%s\n" - ,webui->text_eol,webui->text_eol - ); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -static void webu_text_action_delete(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webu_process_action(webui); - - webu_text_header(webui); - - webu_text_back(webui,"/action"); - - snprintf(response,sizeof(response) - ,"Camera delete %s\nDone%s\n" - ,webui->text_eol,webui->text_eol - ); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -static void webu_text_action_resume(struct webui_ctx *webui) -{ - /* Resume detection on the camera*/ - - char response[WEBUI_LEN_RESP]; - - webu_process_action(webui); - - webu_text_header(webui); - - webu_text_back(webui,"/detection"); - - snprintf(response,sizeof(response) - ,"Camera %d Detection resumed%s\nDone %s\n" - ,webui->cam->camera_id - ,webui->text_eol,webui->text_eol - ); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -/* pause the motion detection on the camera*/ -static void webu_text_action_pause(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webu_process_action(webui); - - webu_text_header(webui); - - webu_text_back(webui,"/detection"); - - snprintf(response,sizeof(response) - ,"Camera %d Detection paused%s\nDone %s\n" - ,webui->cam->camera_id - ,webui->text_eol,webui->text_eol - ); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -/* write the parms to file*/ -static void webu_text_action_write(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webu_process_action(webui); - - webu_text_header(webui); - - webu_text_back(webui,"/config"); - - snprintf(response,sizeof(response) - ,"Camera %d write %s\nDone %s\n" - ,webui->cam->camera_id - ,webui->text_eol,webui->text_eol - ); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -static void webu_text_action(struct webui_ctx *webui) -{ - /* Call the action functions */ - - if (mystreq(webui->uri_cmd2,"makemovie")){ - webu_text_action_makemovie(webui); - - } else if (mystreq(webui->uri_cmd2,"eventstart")){ - webu_text_action_eventstart(webui); - - } else if (mystreq(webui->uri_cmd2,"eventend")){ - webu_text_action_eventend(webui); - - } else if (mystreq(webui->uri_cmd2,"snapshot")){ - webu_text_action_snapshot(webui); - - } else if (mystreq(webui->uri_cmd2,"restart")){ - webu_text_action_restart(webui); - - } else if (mystreq(webui->uri_cmd2,"resume")){ - webu_text_action_resume(webui); - - } else if (mystreq(webui->uri_cmd2,"pause")){ - webu_text_action_pause(webui); - - } else if ((mystreq(webui->uri_cmd2,"stop")) || - (mystreq(webui->uri_cmd2,"end"))){ - webu_text_action_stop(webui); - - } else if ((mystreq(webui->uri_cmd2,"write")) || - (mystreq(webui->uri_cmd2,"writeyes"))){ - webu_text_action_write(webui); - - } else if (mystreq(webui->uri_cmd2,"add")){ - webu_text_action_add(webui); - - } else if (mystreq(webui->uri_cmd2,"delete")){ - webu_text_action_delete(webui); - - } else { - webu_text_badreq(webui); - MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO, - _("Invalid action requested: >%s< >%s< >%s<") - ,webui->uri_camid, webui->uri_cmd1, webui->uri_cmd2); - return; - } - -} - -static void webu_text_track_pantilt(struct webui_ctx *webui) -{ - /* Call the track function */ - char response[WEBUI_LEN_RESP]; - - webu_text_header(webui); - - webu_text_back(webui,"/track"); - - webu_text_camera_name(webui); - - snprintf(response,sizeof(response),"%s", - "
\n" - "Pan\n" - "Tilt\n" - "\n" - "
\n" - "
\n" - "X\n" - "Y\n" - "\n" - "
\n" - ); - webu_write(webui, response); - webu_text_trailer(webui); - -} - -static void webu_text_track(struct webui_ctx *webui) -{ - /* Call the track function */ - char response[WEBUI_LEN_RESP]; - int retcd; - - retcd = webu_process_track(webui); - if (retcd == 0){ - webu_text_header(webui); - - webu_text_back(webui,"/track"); - - webu_text_camera_name(webui); - - snprintf(response,sizeof(response) - ,"Track %s %s\n" - "Done %s\n" - ,webui->uri_cmd2,webui->text_eol - ,webui->text_eol - ); - webu_write(webui, response); - - webu_text_trailer(webui); - } else { - webu_text_badreq(webui); - } - -} - -static void webu_text_menu(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webu_text_header(webui); - - snprintf(response,sizeof(response), - "<- back

" - ); - webu_write(webui, response); - - webu_text_camera_name(webui); - snprintf(response,sizeof(response), - "config
\n" - "action
\n" - "detection
\n" - "track
\n" - ,webui->uri_camid, webui->uri_camid - ,webui->uri_camid, webui->uri_camid - ); - webu_write(webui, response); - webu_text_trailer(webui); - -} - -static void webu_text_menu_config(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webu_text_header(webui); - - webu_text_back(webui,"/"); - - webu_text_camera_name(webui); - snprintf(response,sizeof(response), - "list
" - "write
" - "set
" - "get
" - ,webui->uri_camid, webui->uri_camid - ,webui->uri_camid, webui->uri_camid - ); - webu_write(webui, response); - webu_text_trailer(webui); - -} - -static void webu_text_menu_action(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webu_text_header(webui); - - webu_text_back(webui,"/"); - - webu_text_camera_name(webui); - snprintf(response,sizeof(response), - "eventstart
" - "eventend
" - "snapshot
" - "restart
" - "stop
" - "end
" - ,webui->uri_camid, webui->uri_camid, webui->uri_camid - ,webui->uri_camid, webui->uri_camid, webui->uri_camid - ); - webu_write(webui, response); - webu_text_trailer(webui); - -} - -static void webu_text_menu_detection(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webu_text_header(webui); - - webu_text_back(webui,"/"); - - webu_text_camera_name(webui); - - snprintf(response,sizeof(response), - "status
" - "resume
" - "pause
" - "connection
" - ,webui->uri_camid, webui->uri_camid - ,webui->uri_camid, webui->uri_camid - ); - webu_write(webui, response); - webu_text_trailer(webui); - -} - -static void webu_text_menu_track(struct webui_ctx *webui) -{ - char response[WEBUI_LEN_RESP]; - - webu_text_header(webui); - - webu_text_back(webui,"/"); - - webu_text_camera_name(webui); - - snprintf(response,sizeof(response), - "track set pan/tilt
" - "track center
" - ,webui->uri_camid, webui->uri_camid - ); - webu_write(webui, response); - - webu_text_trailer(webui); - -} - -static void webu_text_submenu(struct webui_ctx *webui) -{ - - if ((mystreq(webui->uri_cmd1,"config")) && - (strlen(webui->uri_cmd2) == 0)) { - webu_text_menu_config(webui); - - } else if ((mystreq(webui->uri_cmd1,"action")) && - (strlen(webui->uri_cmd2) == 0)) { - webu_text_menu_action(webui); - - } else if ((mystreq(webui->uri_cmd1,"detection")) && - (strlen(webui->uri_cmd2) == 0)) { - webu_text_menu_detection(webui); - - } else if ((mystreq(webui->uri_cmd1,"track")) && - (strlen(webui->uri_cmd2) == 0)) { - webu_text_menu_track(webui); - - } else { - MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO, - _("Invalid action requested: >%s< >%s< >%s<") - ,webui->uri_camid, webui->uri_cmd1, webui->uri_cmd2); - webu_text_badreq(webui); - } - -} - -void webu_text_get_query(struct webui_ctx *webui) -{ - /* Write out the option value for one parm */ - char response[WEBUI_LEN_RESP]; - int indx_parm, retcd; - char val_parm[PATH_MAX]; - char temp_name[WEBUI_LEN_PARM]; - - - /* Search through the depreciated parms and if applicable, - * get the new parameter name so we can check its webcontrol_parms level - */ - snprintf(temp_name, WEBUI_LEN_PARM, "%s", webui->uri_value1); - indx_parm=0; - while (config_parms_depr[indx_parm].parm_name != "") { - if (mystreq(config_parms_depr[indx_parm].parm_name.c_str(), webui->uri_value1)){ - snprintf(temp_name, WEBUI_LEN_PARM, "%s", config_parms_depr[indx_parm].newname.c_str()); - break; - } - indx_parm++; - } - - indx_parm = 0; - while (config_parms[indx_parm].parm_name != ""){ - - if ((config_parms[indx_parm].webui_level > webui->motapp->cam_list[0]->conf->webcontrol_parms) || - (config_parms[indx_parm].webui_level == WEBUI_LEVEL_NEVER) || - mystrne(webui->uri_parm1,"query") || - mystrne(temp_name, config_parms[indx_parm].parm_name.c_str())){ - indx_parm++; - continue; - } - - conf_edit_get(webui->motapp->cam_list[webui->thread_nbr], config_parms[indx_parm].parm_name - , val_parm, config_parms[indx_parm].parm_cat); - if (val_parm == NULL){ - conf_edit_get(webui->motapp->cam_list[0], config_parms[indx_parm].parm_name - , val_parm, config_parms[indx_parm].parm_cat); - } - if (mystrne(webui->uri_value1, config_parms[indx_parm].parm_name.c_str())){ - MOTION_LOG(NTC, TYPE_STREAM, NO_ERRNO - , _("'%s' option is depreciated. New option name is `%s'") - ,webui->uri_value1, config_parms[indx_parm].parm_name.c_str()); - } - - webu_text_header(webui); - - webu_text_back(webui,"/config"); - - webu_text_camera_name(webui); - - if (webui->motapp->cam_list[0]->conf->webcontrol_interface == 2) { - retcd = snprintf(response, sizeof (response), - "
    \n" - "
  • %s = %s
  • \n" - "
\n" - ,config_parms[indx_parm].parm_name.c_str() - ,val_parm - ); - if (retcd <0) MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO, _("Error option")); - } else { - retcd = snprintf(response, sizeof (response), - "%s = %s %s\n" - "Done %s\n" - ,config_parms[indx_parm].parm_name.c_str() - ,val_parm - ,webui->text_eol, webui->text_eol - ); - if (retcd <0) MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO, _("Error option")); - } - webu_write(webui, response); - webu_text_trailer(webui); - - break; - } - - if (config_parms[indx_parm].parm_name == ""){ - webu_text_badreq(webui); - } - -} - -void webu_text_status(struct webui_ctx *webui) -{ - /* Write out the pause/active status */ - - char response[WEBUI_LEN_RESP]; - int indx, indx_st; - - webu_text_header(webui); - - webu_text_back(webui,"/detection"); - - if (webui->thread_nbr == 0){ - indx_st = 1; - if (webui->cam_threads == 1) indx_st = 0; - - for (indx = indx_st; indx < webui->cam_threads; indx++) { - snprintf(response, sizeof(response), - "Camera %d Detection status %s %s\n" - ,webui->motapp->cam_list[indx]->camera_id - ,(!webui->motapp->cam_list[indx]->running_cam)? "NOT RUNNING": - (webui->motapp->cam_list[indx]->pause)? "PAUSE":"ACTIVE" - ,webui->text_eol - ); - webu_write(webui, response); - } - } else { - snprintf(response, sizeof(response), - "Camera %d Detection status %s %s\n" - ,webui->cam->camera_id - ,(!webui->cam->running_cam)? "NOT RUNNING": - (webui->cam->pause)? "PAUSE":"ACTIVE" - ,webui->text_eol - ); - webu_write(webui, response); - } - webu_text_trailer(webui); -} - -void webu_text_connection(struct webui_ctx *webui) -{ - /* Write out the connection status */ - char response[WEBUI_LEN_RESP]; - int indx, indx_st; - - webu_text_header(webui); - - webu_text_back(webui,"/detection"); - - webu_text_camera_name(webui); - - if (webui->thread_nbr == 0){ - indx_st = 1; - if (webui->cam_threads == 1) indx_st = 0; - - for (indx = indx_st; indx < webui->cam_threads; indx++) { - snprintf(response,sizeof(response) - , "Camera %d%s%s %s %s\n" - ,webui->motapp->cam_list[indx]->camera_id - ,webui->motapp->cam_list[indx]->conf->camera_name!="" ? " -- " : "" - ,webui->motapp->cam_list[indx]->conf->camera_name!="" ? webui->motapp->cam_list[indx]->conf->camera_name.c_str() : "" - ,(!webui->motapp->cam_list[indx]->running_cam)? "NOT RUNNING" : - (webui->motapp->cam_list[indx]->lost_connection)? "Lost connection": "Connection OK" - ,webui->text_eol - ); - webu_write(webui, response); - } - } else { - snprintf(response,sizeof(response) - , "Camera %d%s%s %s %s\n" - ,webui->cam->camera_id - ,webui->cam->conf->camera_name!="" ? " -- " : "" - ,webui->cam->conf->camera_name!="" ? webui->cam->conf->camera_name.c_str() : "" - ,(!webui->cam->running_cam)? "NOT RUNNING" : - (webui->cam->lost_connection)? "Lost connection": "Connection OK" - ,webui->text_eol - ); - webu_write(webui, response); - } - webu_text_trailer(webui); -} - -void webu_text_list(struct webui_ctx *webui) -{ - - if (webui->motapp->cam_list[0]->conf->webcontrol_interface == 2) { - webu_text_list_basic(webui); - } else { - webu_text_list_raw(webui); - } - -} - -void webu_text_main(struct webui_ctx *webui) -{ - - /* Main entry point for processing requests for the text interface */ - - webu_text_seteol(webui); - - pthread_mutex_lock(&webui->motapp->mutex_camlst); - - if (strlen(webui->uri_camid) == 0) { - if (webui->motapp->cam_list[0]->conf->webcontrol_interface == 2) { - webu_text_page_basic(webui); - } else { - webu_text_page_raw(webui); - } - - } else if (strlen(webui->uri_cmd1) == 0) { - webu_text_menu(webui); - - } else if (strlen(webui->uri_cmd2) == 0) { - webu_text_submenu(webui); - - } else if ((mystreq(webui->uri_cmd1,"config")) && - (mystreq(webui->uri_cmd2,"set")) && - (strlen(webui->uri_parm1) == 0)) { - webu_text_set_menu(webui); - - } else if ((mystreq(webui->uri_cmd1,"config")) && - (mystreq(webui->uri_cmd2,"set")) && - (strlen(webui->uri_parm1) > 0) && - (strlen(webui->uri_value1) == 0) ) { - webu_text_set_query(webui); - - } else if ((mystreq(webui->uri_cmd1,"config")) && - (mystreq(webui->uri_cmd2,"set"))) { - webu_text_set_assign(webui); - - } else if ((mystreq(webui->uri_cmd1,"config")) && - (mystreq(webui->uri_cmd2,"write"))) { - webu_text_action(webui); - - } else if ((mystreq(webui->uri_cmd1,"config")) && - (mystreq(webui->uri_cmd2,"list"))) { - webu_text_list(webui); - - } else if ((mystreq(webui->uri_cmd1,"config")) && - (mystreq(webui->uri_cmd2,"get")) && - (strlen(webui->uri_parm1) == 0)) { - webu_text_get_menu(webui); - - } else if ((mystreq(webui->uri_cmd1,"config")) && - (mystreq(webui->uri_cmd2,"get"))) { - webu_text_get_query(webui); - - } else if ((mystreq(webui->uri_cmd1,"detection")) && - (mystreq(webui->uri_cmd2,"status"))) { - webu_text_status(webui); - - } else if ((mystreq(webui->uri_cmd1,"detection")) && - (mystreq(webui->uri_cmd2,"connection"))) { - webu_text_connection(webui); - - } else if ((mystreq(webui->uri_cmd1,"detection")) && - (mystreq(webui->uri_cmd2,"resume"))) { - webu_text_action(webui); - - } else if ((mystreq(webui->uri_cmd1,"detection")) && - (mystreq(webui->uri_cmd2,"pause"))) { - webu_text_action(webui); - - } else if ((mystreq(webui->uri_cmd1,"action")) && - (mystreq(webui->uri_cmd2,"stop"))){ - webu_text_action(webui); - - } else if ((mystreq(webui->uri_cmd1,"action")) && - (mystreq(webui->uri_cmd2,"end"))){ - webu_text_action(webui); - - } else if (mystreq(webui->uri_cmd1,"action")) { - webu_text_action(webui); - - } else if ((mystreq(webui->uri_cmd1,"track")) && - (mystreq(webui->uri_cmd2,"set")) && - (strlen(webui->uri_parm1) == 0)) { - webu_text_track_pantilt(webui); - - } else if ((mystreq(webui->uri_cmd1,"track"))){ - webu_text_track(webui); - - } else{ - MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO, - _("Invalid action requested: >%s< >%s< >%s<") - ,webui->uri_camid, webui->uri_cmd1, webui->uri_cmd2); - webu_text_badreq(webui); - } - pthread_mutex_unlock(&webui->motapp->mutex_camlst); - - return; -}