"Fossies" - the Fresh Open Source Software Archive

Member "motion-Release-4.3.0/src/webu_html.c" (14 Jan 2020, 48821 Bytes) of package /linux/misc/motion-Release-4.3.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "webu_html.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  *    webu_html.c
    3  *
    4  *    Create the html for the webcontrol page
    5  *
    6  *    This software is distributed under the GNU Public License Version 2
    7  *    See also the file 'COPYING'.
    8  *
    9  *    Functional naming scheme
   10  *        webu_html* - Functions that create the display webcontrol page.
   11  *        webu_html_main        - Entry point from webu_ans_ctrl(in webu.c)
   12  *        webu_html_page        - Create the web page
   13  *          webu_html_head      - Header section of the page
   14  *            webu_html_style*  - The style section of the web page
   15  *          webu_html_body      - Calls all the functions to create the body
   16  *            webu_html_navbar* - The navbar section of the web page
   17  *            webu_html_config* - config parms of page
   18  *            webu_html_track*  - Tracking functions
   19  *            webu_html_script* - The javascripts of the web page
   20  *
   21  *    To debug, run code, open page, view source and make copy of html
   22  *    into a local file to revise changes then determine applicable section(s)
   23  *    in this code to modify to match modified version.
   24  *    Known HTML Issues:
   25  *      Single and double quotes are not consistently used.
   26  *      HTML ids do not follow any naming convention.
   27  *      After clicking restart, do something...Try to connect again?
   28  *
   29  *    Additional functionality considerations:
   30  *      Notification to user of items that require restart when changed.
   31  *      Notification to user that item successfully implemented (config change/tracking)
   32  *      List motion parms somewhere so they can be found by xgettext
   33  *
   34  */
   35 
   36 #include "motion.h"
   37 #include "webu.h"
   38 #include "webu_html.h"
   39 #include "translate.h"
   40 
   41 /* struct to save information regarding the links to include in html page */
   42 struct strminfo_ctx {
   43     struct context  **cntlst;
   44     char            lnk_ref[WEBUI_LEN_LNK];
   45     char            lnk_src[WEBUI_LEN_LNK];
   46     char            lnk_camid[WEBUI_LEN_LNK];
   47     char            proto[WEBUI_LEN_LNK];
   48     int             port;
   49     int             motion_images;
   50 };
   51 
   52 static void webu_html_style_navbar(struct webui_ctx *webui) {
   53     /* Write out the style section of the web page */
   54     char response[WEBUI_LEN_RESP];
   55 
   56     snprintf(response, sizeof (response),"%s",
   57         "    .navbar {\n"
   58         "      overflow: hidden;\n"
   59         "      background-color: #333;\n"
   60         "      font-family: Arial;\n"
   61         "    }\n"
   62         "    .navbar a {\n"
   63         "      float: left;\n"
   64         "      font-size: 16px;\n"
   65         "      color: white;\n"
   66         "      text-align: center;\n"
   67         "      padding: 14px 16px;\n"
   68         "      text-decoration: none;\n"
   69         "    }\n"
   70         "    .navbar a:hover, {\n"
   71         "      background-color: darkgray;\n"
   72         "    }\n");
   73     webu_write(webui, response);
   74 
   75 }
   76 
   77 static void webu_html_style_dropdown(struct webui_ctx *webui) {
   78     /* Write out the style section of the web page */
   79     char response[WEBUI_LEN_RESP];
   80 
   81     snprintf(response, sizeof (response),"%s",
   82         "    .dropdown {\n"
   83         "      float: left;\n"
   84         "      overflow: hidden;\n"
   85         "    }\n"
   86         "    .dropdown .dropbtn {\n"
   87         "      font-size: 16px;\n"
   88         "      border: none;\n"
   89         "      outline: none;\n"
   90         "      color: white;\n"
   91         "      padding: 14px 16px;\n"
   92         "      background-color: inherit;\n"
   93         "      font-family: inherit;\n"
   94         "      margin: 0;\n"
   95         "    }\n"
   96         "    .dropdown-content {\n"
   97         "      display: none;\n"
   98         "      position: absolute;\n"
   99         "      background-color: #f9f9f9;\n"
  100         "      min-width: 160px;\n"
  101         "      box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);\n"
  102         "      z-index: 1;\n"
  103         "    }\n"
  104         "    .dropdown-content a {\n"
  105         "      float: none;\n"
  106         "      color: black;\n"
  107         "      padding: 12px 16px;\n"
  108         "      text-decoration: none;\n"
  109         "      display: block;\n"
  110         "      text-align: left;\n"
  111         "    }\n"
  112         "    .dropdown-content a:hover {\n"
  113         "      background-color: lightgray;\n"
  114         "    }\n"
  115         "    .dropdown:hover .dropbtn {\n"
  116         "      background-color: darkgray;\n"
  117         "    }\n"
  118         "    .border {\n"
  119         "      border-width: 2px;\n"
  120         "      border-color: white;\n"
  121         "      border-style: solid;\n"
  122         "    }\n");
  123     webu_write(webui, response);
  124 }
  125 
  126 static void webu_html_style_input(struct webui_ctx *webui) {
  127     /* Write out the style section of the web page */
  128     char response[WEBUI_LEN_RESP];
  129 
  130     snprintf(response, sizeof (response),"%s",
  131         "    input , select  {\n"
  132         "      width: 25%;\n"
  133         "      padding: 5px;\n"
  134         "      margin: 0;\n"
  135         "      display: inline-block;\n"
  136         "      border: 1px solid #ccc;\n"
  137         "      border-radius: 4px;\n"
  138         "      box-sizing: border-box;\n"
  139         "      height: 50%;\n"
  140         "      font-size: 75%;\n"
  141         "      margin-bottom: 5px;\n"
  142         "    }\n"
  143         "    .frm-input{\n"
  144         "      text-align:center;\n"
  145         "    }\n");
  146     webu_write(webui, response);
  147 }
  148 
  149 static void webu_html_style_base(struct webui_ctx *webui) {
  150     /* Write out the style section of the web page */
  151     char response[WEBUI_LEN_RESP];
  152 
  153     snprintf(response, sizeof (response),"%s",
  154         "    * {margin: 0; padding: 0; }\n"
  155         "    body {\n"
  156         "      padding: 0;\n"
  157         "      margin: 0;\n"
  158         "      font-family: Arial, Helvetica, sans-serif;\n"
  159         "      font-size: 16px;\n"
  160         "      line-height: 1;\n"
  161         "      color: #606c71;\n"
  162         "      background-color: #159957;\n"
  163         "      background-image: linear-gradient(120deg, #155799, #159957);\n"
  164         "      margin-left:0.5% ;\n"
  165         "      margin-right:0.5% ;\n"
  166         "      width: device-width ;\n"
  167         "    }\n"
  168         "    img {\n"
  169         "      max-width: 100%;\n"
  170         "      max-height: 100%;\n"
  171         "      height: auto;\n"
  172         "    }\n"
  173         "    .page-header {\n"
  174         "      color: #fff;\n"
  175         "      text-align: center;\n"
  176         "      margin-top: 0rem;\n"
  177         "      margin-bottom: 0rem;\n"
  178         "      font-weight: normal;\n"
  179         "    }\n");
  180     webu_write(webui, response);
  181 
  182     snprintf(response, sizeof (response),"%s",
  183         "    .page-header h4 {\n"
  184         "      height: 2px;\n"
  185         "      padding: 0;\n"
  186         "      margin: 1rem 0;\n"
  187         "      border: 0;\n"
  188         "    }\n"
  189         "    .main-content {\n"
  190         "      background-color: #000000;\n"
  191         "      text-align: center;\n"
  192         "      margin-top: 0rem;\n"
  193         "      margin-bottom: 0rem;\n"
  194         "      font-weight: normal;\n"
  195         "      font-size: 0.90em;\n"
  196         "    }\n"
  197         "    .header-right{\n"
  198         "      float: right;\n"
  199         "      color: white;\n"
  200         "    }\n"
  201         "    .header-center {\n"
  202         "      text-align: center;\n"
  203         "      color: white;\n"
  204         "      margin-top: 10px;\n"
  205         "      margin-bottom: 10px;\n"
  206         "    }\n");
  207     webu_write(webui, response);
  208 }
  209 
  210 static void webu_html_style(struct webui_ctx *webui) {
  211     /* Write out the style section of the web page */
  212     char response[WEBUI_LEN_RESP];
  213 
  214     snprintf(response, sizeof (response),"%s", "  <style>\n");
  215     webu_write(webui, response);
  216 
  217     webu_html_style_base(webui);
  218 
  219     webu_html_style_navbar(webui);
  220 
  221     webu_html_style_input(webui);
  222 
  223     webu_html_style_dropdown(webui);
  224 
  225     snprintf(response, sizeof (response),"%s", "  </style>\n");
  226     webu_write(webui, response);
  227 
  228 }
  229 
  230 static void webu_html_head(struct webui_ctx *webui) {
  231     /* Write out the header section of the web page */
  232     char response[WEBUI_LEN_RESP];
  233 
  234     snprintf(response, sizeof (response),"%s","<head>\n"
  235         "  <meta charset=\"UTF-8\">\n"
  236         "  <title>Motion</title>\n"
  237         "  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n");
  238     webu_write(webui, response);
  239 
  240     webu_html_style(webui);
  241 
  242     snprintf(response, sizeof (response),"%s", "</head>\n");
  243     webu_write(webui, response);
  244 
  245 }
  246 
  247 static void webu_html_navbar_camera(struct webui_ctx *webui) {
  248     /*Write out the options included in the camera dropdown */
  249     char response[WEBUI_LEN_RESP];
  250     int indx;
  251 
  252     if (webui->cam_threads == 1){
  253         /* Only Motion.conf file */
  254         if (webui->cntlst[0]->conf.camera_name == NULL){
  255             snprintf(response, sizeof (response),
  256                 "    <div class=\"dropdown\">\n"
  257                 "      <button onclick='display_cameras()' id=\"cam_drop\" class=\"dropbtn\">%s</button>\n"
  258                 "      <div id='cam_btn' class=\"dropdown-content\">\n"
  259                 "        <a onclick=\"camera_click('cam_%05d');\">%s 1</a>\n"
  260                 ,_("Cameras")
  261                 ,webui->cntlst[0]->camera_id
  262                 ,_("Camera"));
  263             webu_write(webui, response);
  264         } else {
  265             snprintf(response, sizeof (response),
  266                 "    <div class=\"dropdown\">\n"
  267                 "      <button onclick='display_cameras()' id=\"cam_drop\" class=\"dropbtn\">%s</button>\n"
  268                 "      <div id='cam_btn' class=\"dropdown-content\">\n"
  269                 "        <a onclick=\"camera_click('cam_%05d');\">%s</a>\n"
  270                 ,_("Cameras")
  271                 ,webui->cntlst[0]->camera_id
  272                 ,webui->cntlst[0]->conf.camera_name);
  273             webu_write(webui, response);
  274         }
  275     } else if (webui->cam_threads > 1){
  276         /* Motion.conf + separate camera.conf file */
  277         snprintf(response, sizeof (response),
  278             "    <div class=\"dropdown\">\n"
  279             "      <button onclick='display_cameras()' id=\"cam_drop\" class=\"dropbtn\">%s</button>\n"
  280             "      <div id='cam_btn' class=\"dropdown-content\">\n"
  281             "        <a onclick=\"camera_click('cam_all00');\">%s</a>\n"
  282             ,_("Cameras")
  283             ,_("All"));
  284         webu_write(webui, response);
  285 
  286         for (indx=1;indx <= webui->cam_count;indx++){
  287             if (webui->cntlst[indx]->conf.camera_name == NULL){
  288                 snprintf(response, sizeof (response),
  289                     "        <a onclick=\"camera_click('cam_%05d');\">%s %d</a>\n"
  290                     ,webui->cntlst[indx]->camera_id
  291                     , _("Camera"), webui->cntlst[indx]->camera_id);
  292             } else {
  293                 snprintf(response, sizeof (response),
  294                     "        <a onclick=\"camera_click('cam_%05d');\">%s</a>\n"
  295                     ,webui->cntlst[indx]->camera_id
  296                     ,webui->cntlst[indx]->conf.camera_name
  297                 );
  298             }
  299             webu_write(webui, response);
  300         }
  301     }
  302 
  303     snprintf(response, sizeof (response),"%s",
  304         "      </div>\n"
  305         "    </div>\n");
  306     webu_write(webui, response);
  307 
  308 }
  309 
  310 static void webu_html_navbar_action(struct webui_ctx *webui) {
  311     /* Write out the options included in the actions dropdown*/
  312     char response[WEBUI_LEN_RESP];
  313 
  314     snprintf(response, sizeof (response),
  315         "    <div class=\"dropdown\">\n"
  316         "      <button onclick='display_actions()' id=\"act_drop\" class=\"dropbtn\">%s</button>\n"
  317         "      <div id='act_btn' class=\"dropdown-content\">\n"
  318         "        <a onclick=\"action_click('/action/eventstart');\">%s</a>\n"
  319         "        <a onclick=\"action_click('/action/eventend');\">%s</a>\n"
  320         "        <a onclick=\"action_click('/action/snapshot');\">%s</a>\n"
  321         "        <a onclick=\"action_click('config');\">%s</a>\n"
  322         "        <a onclick=\"action_click('/config/write');\">%s</a>\n"
  323         "        <a onclick=\"action_click('track');\">%s</a>\n"
  324         "        <a onclick=\"action_click('/detection/pause');\">%s</a>\n"
  325         "        <a onclick=\"action_click('/detection/start');\">%s</a>\n"
  326         "        <a onclick=\"action_click('/action/restart');\">%s</a>\n"
  327         "        <a onclick=\"action_click('/action/quit');\">%s</a>\n"
  328         "      </div>\n"
  329         "    </div>\n"
  330         ,_("Action")
  331         ,_("Start Event")
  332         ,_("End Event")
  333         ,_("Snapshot")
  334         ,_("Change Configuration")
  335         ,_("Write Configuration")
  336         ,_("Tracking")
  337         ,_("Pause")
  338         ,_("Start")
  339         ,_("Restart")
  340         ,_("Quit"));
  341     webu_write(webui, response);
  342 }
  343 
  344 static void webu_html_navbar(struct webui_ctx *webui) {
  345     /* Write the navbar section*/
  346     char response[WEBUI_LEN_RESP];
  347 
  348     snprintf(response, sizeof (response),"%s",
  349         "  <div class=\"navbar\">\n");
  350     webu_write(webui, response);
  351 
  352     webu_html_navbar_camera(webui);
  353 
  354     webu_html_navbar_action(webui);
  355 
  356     snprintf(response, sizeof (response),
  357         "    <a href=\"https://motion-project.github.io/motion_guide.html\" "
  358         " target=\"_blank\">%s</a>\n"
  359         "    <p class=\"header-right\">Motion "VERSION"</p>\n"
  360         "  </div>\n"
  361         ,_("Help"));
  362     webu_write(webui, response);
  363 
  364 }
  365 
  366 static void webu_html_config_notice(struct webui_ctx *webui) {
  367     /* Print out the header description of which parameters are included based upon the
  368      * webcontrol_parms that was specified
  369      */
  370     char response[WEBUI_LEN_RESP];
  371 
  372     if (webui->cntlst[0]->conf.webcontrol_parms == 0){
  373         snprintf(response, sizeof (response),
  374             "    <h4 id='h4_parm' class='header-center'>webcontrol_parms = 0 (%s)</h4>\n"
  375             ,_("No Configuration Options"));
  376     } else if (webui->cntlst[0]->conf.webcontrol_parms == 1){
  377         snprintf(response, sizeof (response),
  378             "    <h4 id='h4_parm' class='header-center'>webcontrol_parms = 1 (%s)</h4>\n"
  379             ,_("Limited Configuration Options"));
  380     } else if (webui->cntlst[0]->conf.webcontrol_parms == 2){
  381         snprintf(response, sizeof (response),
  382             "    <h4 id='h4_parm' class='header-center'>webcontrol_parms = 2 (%s)</h4>\n"
  383             ,_("Advanced Configuration Options"));
  384     } else{
  385         snprintf(response, sizeof (response),
  386             "    <h4 id='h4_parm' class='header-center'>webcontrol_parms = 3 (%s)</h4>\n"
  387             ,_("Restricted Configuration Options"));
  388     }
  389     webu_write(webui, response);
  390 }
  391 
  392 static void webu_html_h3desc(struct webui_ctx *webui) {
  393     /* Write out the status description for the camera */
  394     char response[WEBUI_LEN_RESP];
  395 
  396     if (webui->cam_threads == 1){
  397         snprintf(response, sizeof (response),
  398             "  <div id=\"id_header\">\n"
  399             "    <h3 id='h3_cam' data-cam=\"cam_all00\" class='header-center'>%s (%s)</h3>\n"
  400             "  </div>\n"
  401             ,_("All Cameras")
  402             ,(!webui->cntlst[0]->running)? _("Not running") :
  403                 (webui->cntlst[0]->lost_connection)? _("Lost connection"):
  404                 (webui->cntlst[0]->pause)? _("Paused"):_("Active")
  405             );
  406         webu_write(webui,response);
  407     } else {
  408         snprintf(response, sizeof (response),
  409             "  <div id=\"id_header\">\n"
  410             "    <h3 id='h3_cam' data-cam=\"cam_all00\" class='header-center'>%s</h3>\n"
  411             "  </div>\n"
  412             ,_("All Cameras"));
  413         webu_write(webui,response);
  414     }
  415 }
  416 
  417 static void webu_html_config(struct webui_ctx *webui) {
  418 
  419     /* Write out the options to put into the config dropdown
  420      * We use html data attributes to store the values for the options
  421      * We always set a cam_all00 attribute and if the value if different for
  422      * any of our cameras, then we also add a cam_xxxxx which has the config
  423      * value for camera xxxxx  The javascript then decodes these to display
  424      */
  425 
  426     char response[WEBUI_LEN_RESP];
  427     int indx_parm, indx, diff_vals;
  428     const char *val_main, *val_thread;
  429     char *val_temp;
  430 
  431 
  432     snprintf(response, sizeof (response),"%s",
  433         "  <div id='cfg_form' style=\"display:none\">\n");
  434     webu_write(webui, response);
  435 
  436     webu_html_config_notice(webui);
  437 
  438     snprintf(response, sizeof (response),
  439         "    <form class=\"frm-input\">\n"
  440         "      <select id='cfg_parms' name='onames' "
  441         " autocomplete='off' onchange='config_change();'>\n"
  442         "        <option value='default' data-cam_all00=\"\" >%s</option>\n"
  443         ,_("Select option"));
  444     webu_write(webui, response);
  445 
  446     /* The config_params[indx_parm].print reuses the buffer so create a
  447      * temporary variable for storing our parameter from main to compare
  448      * to the thread specific value
  449      */
  450     val_temp=malloc(PATH_MAX);
  451     indx_parm = 0;
  452     while (config_params[indx_parm].param_name != NULL){
  453 
  454         if ((config_params[indx_parm].webui_level > webui->cntlst[0]->conf.webcontrol_parms) ||
  455             (config_params[indx_parm].webui_level == WEBUI_LEVEL_NEVER)){
  456             indx_parm++;
  457             continue;
  458         }
  459 
  460         val_main = config_params[indx_parm].print(webui->cntlst, NULL, indx_parm, 0);
  461 
  462         snprintf(response, sizeof (response),
  463             "        <option value='%s' data-cam_all00=\""
  464             , config_params[indx_parm].param_name);
  465         webu_write(webui, response);
  466 
  467         memset(val_temp,'\0',PATH_MAX);
  468         if (val_main != NULL){
  469             snprintf(response, sizeof (response),"%s", val_main);
  470             webu_write(webui, response);
  471             snprintf(val_temp, PATH_MAX,"%s", val_main);
  472         }
  473 
  474         /* Loop through all the treads and see if any have a different value from motion.conf */
  475         if (webui->cam_threads > 1){
  476             for (indx=1;indx <= webui->cam_count;indx++){
  477                 val_thread=config_params[indx_parm].print(webui->cntlst, NULL, indx_parm, indx);
  478                 diff_vals = FALSE;
  479                 if (((strlen(val_temp) == 0) && (val_thread == NULL)) ||
  480                     ((strlen(val_temp) != 0) && (val_thread == NULL))) {
  481                     diff_vals = FALSE;
  482                 } else if (((strlen(val_temp) == 0) && (val_thread != NULL)) ) {
  483                     diff_vals = TRUE;
  484                 } else {
  485                     if (strcasecmp(val_temp, val_thread)) diff_vals = TRUE;
  486                 }
  487                 if (diff_vals){
  488                     snprintf(response, sizeof (response),"%s","\" \\ \n");
  489                     webu_write(webui, response);
  490 
  491                     snprintf(response, sizeof (response),
  492                         "           data-cam_%05d=\""
  493                         ,webui->cntlst[indx]->camera_id);
  494                     webu_write(webui, response);
  495                     if (val_thread != NULL){
  496                         snprintf(response, sizeof (response),"%s", val_thread);
  497                         webu_write(webui, response);
  498                     }
  499                 }
  500             }
  501         }
  502         /* Terminate the open quote and option.  For foreign language put hint in ()  */
  503         if (!strcasecmp(webui->lang,"en") ||
  504             !strcasecmp(config_params[indx_parm].param_name
  505                 ,_(config_params[indx_parm].param_name))){
  506             snprintf(response, sizeof (response),"\" >%s</option>\n",
  507                 config_params[indx_parm].param_name);
  508             webu_write(webui, response);
  509         } else {
  510             snprintf(response, sizeof (response),"\" >%s (%s)</option>\n",
  511                 config_params[indx_parm].param_name
  512                 ,_(config_params[indx_parm].param_name));
  513             webu_write(webui, response);
  514         }
  515 
  516         indx_parm++;
  517     }
  518 
  519     free(val_temp);
  520 
  521     snprintf(response, sizeof (response),
  522         "      </select>\n"
  523         "      <input type=\"text\"   id=\"cfg_value\" >\n"
  524         "      <input type='button' id='cfg_button' value='%s' onclick='config_click()'>\n"
  525         "    </form>\n"
  526         "  </div>\n"
  527         ,_("Save"));
  528     webu_write(webui, response);
  529 
  530 }
  531 
  532 static void webu_html_track(struct webui_ctx *webui) {
  533     /* Write the section for handling the tracking function */
  534     char response[WEBUI_LEN_RESP];
  535 
  536     snprintf(response, sizeof (response),
  537         "  <div id='trk_form' style='display:none'>\n"
  538         "    <form class='frm-input'>\n"
  539         "      <select id='trk_option' name='trkopt'  autocomplete='off' "
  540         " style='width:20%%' onchange='track_change();'>\n"
  541         "        <option value='pan/tilt' data-trk='pan' >%s</option>\n"
  542         "        <option value='absolute' data-trk='abs' >%s</option>\n"
  543         "        <option value='center' data-trk='ctr' >%s</option>\n"
  544         "      </select>\n"
  545         "      <label id='trk_lblpan' style='color:white; display:inline' >%s</label>\n"
  546         "      <label id='trk_lblx'   style='color:white; display:none' >X</label>\n"
  547         "      <input type='text'   id='trk_panx' style='width:10%%' >\n"
  548         "      <label id='trk_lbltilt' style='color:white; display:inline' >%s</label>\n"
  549         "      <label id='trk_lbly'   style='color:white; display:none' >Y</label>\n"
  550         "      <input type='text'   id='trk_tilty' style='width:10%%' >\n"
  551         "      <input type='button' id='trk_button' value='%s' "
  552         " style='width:10%%' onclick='track_click()'>\n"
  553         "    </form>\n"
  554         "  </div>\n"
  555         ,_("Pan/Tilt")
  556         ,_("Absolute Change")
  557         ,_("Center")
  558         ,_("Pan")
  559         ,_("Tilt")
  560         ,_("Save"));
  561     webu_write(webui, response);
  562 
  563 }
  564 
  565 static void webu_html_strminfo(struct strminfo_ctx *strm_info, int indx) {
  566     /* This determines all the items we need to know to specify links and
  567      * stream sources for the page.  The options are 0-3 as of this writing
  568      * where 0 = full streams, 1 = substreams, 2 = static images and 3 is
  569      * the legacy code for creating streams.  So we need to assign not only
  570      * what images are to be sent but also whether we have tls/ssl.
  571      * There are WAY too many options for this.
  572     */
  573     if (strm_info->cntlst[indx]->conf.stream_preview_method == 99){
  574         snprintf(strm_info->proto,WEBUI_LEN_LNK,"%s","http");
  575         snprintf(strm_info->lnk_ref,WEBUI_LEN_LNK,"%s","");
  576         snprintf(strm_info->lnk_src,WEBUI_LEN_LNK,"%s","");
  577         snprintf(strm_info->lnk_camid,WEBUI_LEN_LNK,"%s","");
  578         strm_info->port = strm_info->cntlst[indx]->conf.stream_port;
  579     } else {
  580         /* If using the main port,we need to insert a thread number into url*/
  581         if (strm_info->cntlst[0]->conf.stream_port != 0) {
  582             snprintf(strm_info->lnk_camid,WEBUI_LEN_LNK,"/%d"
  583                 ,strm_info->cntlst[indx]->camera_id);
  584             strm_info->port = strm_info->cntlst[0]->conf.stream_port;
  585             if (strm_info->cntlst[0]->conf.stream_tls) {
  586                 snprintf(strm_info->proto,WEBUI_LEN_LNK,"%s","https");
  587             } else {
  588                 snprintf(strm_info->proto,WEBUI_LEN_LNK,"%s","http");
  589             }
  590         } else {
  591             snprintf(strm_info->lnk_camid,WEBUI_LEN_LNK,"%s","");
  592             strm_info->port = strm_info->cntlst[indx]->conf.stream_port;
  593             if (strm_info->cntlst[indx]->conf.stream_tls) {
  594                 snprintf(strm_info->proto,WEBUI_LEN_LNK,"%s","https");
  595             } else {
  596                 snprintf(strm_info->proto,WEBUI_LEN_LNK,"%s","http");
  597             }
  598         }
  599         if (strm_info->motion_images){
  600             snprintf(strm_info->lnk_ref,WEBUI_LEN_LNK,"%s","/motion");
  601             snprintf(strm_info->lnk_src,WEBUI_LEN_LNK,"%s","/motion");
  602         } else {
  603             /* Assign what images and links we want */
  604             if (strm_info->cntlst[indx]->conf.stream_preview_method == 1){
  605                 /* Substream for preview */
  606                 snprintf(strm_info->lnk_ref,WEBUI_LEN_LNK,"%s","/stream");
  607                 snprintf(strm_info->lnk_src,WEBUI_LEN_LNK,"%s","/substream");
  608             } else if (strm_info->cntlst[indx]->conf.stream_preview_method == 2){
  609                 /* Static image for preview */
  610                 snprintf(strm_info->lnk_ref,WEBUI_LEN_LNK,"%s","/stream");
  611                 snprintf(strm_info->lnk_src,WEBUI_LEN_LNK,"%s","/current");
  612             } else if (strm_info->cntlst[indx]->conf.stream_preview_method == 4){
  613                 /* Source image for preview */
  614                 snprintf(strm_info->lnk_ref,WEBUI_LEN_LNK,"%s","/source");
  615                 snprintf(strm_info->lnk_src,WEBUI_LEN_LNK,"%s","/source");
  616             } else {
  617                 /* Full stream for preview (method 0 or 3)*/
  618                 snprintf(strm_info->lnk_ref,WEBUI_LEN_LNK,"%s","/stream");
  619                 snprintf(strm_info->lnk_src,WEBUI_LEN_LNK,"%s","/stream");
  620             }
  621         }
  622     }
  623 
  624 }
  625 
  626 static void webu_html_preview(struct webui_ctx *webui) {
  627 
  628     /* Write the initial version of the preview section.  The javascript
  629      * will change this section when user selects a different camera */
  630     char response[WEBUI_LEN_RESP];
  631     int indx, indx_st, preview_scale;
  632     struct strminfo_ctx strm_info;
  633 
  634     strm_info.cntlst = webui->cntlst;
  635 
  636     snprintf(response, sizeof (response),"%s",
  637         "  <div id=\"liveview\">\n"
  638         "    <section class=\"main-content\">\n"
  639         "      <br>\n"
  640         "      <p id=\"id_preview\">\n");
  641     webu_write(webui, response);
  642 
  643     indx_st = 1;
  644     if (webui->cam_threads == 1) indx_st = 0;
  645 
  646     for (indx = indx_st; indx<webui->cam_threads; indx++){
  647         if (webui->cntlst[indx]->conf.stream_preview_newline){
  648             snprintf(response, sizeof (response),"%s","      <br>\n");
  649             webu_write(webui, response);
  650         }
  651 
  652         if (webui->cntlst[indx]->conf.stream_preview_method == 3){
  653             preview_scale = 45;
  654         } else {
  655             preview_scale = webui->cntlst[indx]->conf.stream_preview_scale;
  656         }
  657 
  658         strm_info.motion_images = FALSE;
  659         webu_html_strminfo(&strm_info,indx);
  660         snprintf(response, sizeof (response),
  661             "      <a href=%s://%s:%d%s%s> "
  662             " <img src=%s://%s:%d%s%s border=0 width=%d%%></a>\n"
  663             ,strm_info.proto, webui->hostname, strm_info.port
  664             ,strm_info.lnk_camid, strm_info.lnk_ref
  665             ,strm_info.proto, webui->hostname, strm_info.port
  666             ,strm_info.lnk_camid, strm_info.lnk_src
  667             ,preview_scale);
  668         webu_write(webui, response);
  669 
  670         if (webui->cntlst[indx]->conf.stream_preview_method == 3){
  671             strm_info.motion_images = TRUE;
  672             webu_html_strminfo(&strm_info,indx);
  673             snprintf(response, sizeof (response),
  674                 "      <a href=%s://%s:%d%s%s> "
  675                 " <img src=%s://%s:%d%s%s class=border width=%d%%></a>\n"
  676                 ,strm_info.proto, webui->hostname, strm_info.port
  677                 ,strm_info.lnk_camid, strm_info.lnk_ref
  678                 ,strm_info.proto, webui->hostname, strm_info.port
  679                 ,strm_info.lnk_camid, strm_info.lnk_src
  680                 ,preview_scale);
  681             webu_write(webui, response);
  682         }
  683 
  684     }
  685 
  686     snprintf(response, sizeof (response),"%s",
  687         "      </p>\n"
  688         "      <br>\n"
  689         "    </section>\n"
  690         "  </div>\n");
  691     webu_write(webui, response);
  692 
  693 }
  694 
  695 static void webu_html_script_action(struct webui_ctx *webui) {
  696     /* Write the javascript action_click() function.
  697      * We do not have a good notification section on the page so the successful
  698      * submission and response is currently a empty if block for the future
  699      * enhancement to somehow notify the user everything worked */
  700     char response[WEBUI_LEN_RESP];
  701 
  702     snprintf(response, sizeof (response),"%s",
  703         "    function event_reloadpage() {\n"
  704         "      window.location.reload();\n"
  705         "    }\n\n"
  706     );
  707     webu_write(webui, response);
  708 
  709     snprintf(response, sizeof (response),"%s",
  710         "    function action_click(actval) {\n"
  711         "      if (actval == \"config\"){\n"
  712         "        document.getElementById('trk_form').style.display=\"none\";\n"
  713         "        document.getElementById('cfg_form').style.display=\"inline\";\n"
  714         "      } else if (actval == \"track\"){\n"
  715         "        document.getElementById('cfg_form').style.display=\"none\";\n"
  716         "        document.getElementById('trk_form').style.display=\"inline\";\n"
  717         "      } else {\n"
  718         "        document.getElementById('cfg_form').style.display=\"none\";\n"
  719         "        document.getElementById('trk_form').style.display=\"none\";\n"
  720         "        var camstr = document.getElementById('h3_cam').getAttribute('data-cam');\n"
  721         "        var camnbr = camstr.substring(4,9);\n"
  722         "        var http = new XMLHttpRequest();\n"
  723         "        if ((actval == \"/detection/pause\") || (actval == \"/detection/start\")) {\n"
  724         "          http.addEventListener('load', event_reloadpage); \n"
  725         "        }\n"
  726     );
  727     webu_write(webui, response);
  728 
  729     snprintf(response, sizeof (response),
  730         "        var url = \"%s://%s:%d/\"; \n"
  731         ,webui->hostproto, webui->hostname
  732         ,webui->cntlst[0]->conf.webcontrol_port);
  733     webu_write(webui, response);
  734 
  735     snprintf(response, sizeof (response),
  736         "        if (camnbr == \"all00\"){\n"
  737         "          url = url + \"%05d\";\n"
  738         "        } else {\n"
  739         "          url = url + camnbr;\n"
  740         "        }\n"
  741         "        url = url + actval;\n"
  742        ,webui->cntlst[0]->camera_id);
  743     webu_write(webui, response);
  744 
  745     snprintf(response, sizeof (response),"%s",
  746         "        http.open(\"GET\", url, true);\n"
  747         "        http.onreadystatechange = function() {\n"
  748         "          if(http.readyState == 4 && http.status == 200) {\n"
  749         "          }\n"
  750         "        }\n"
  751         "        http.send(null);\n"
  752         "      }\n"
  753         "      document.getElementById('act_btn').style.display=\"none\"; \n"
  754         "      document.getElementById('cfg_value').value = '';\n"
  755         "      document.getElementById('cfg_parms').value = 'default';\n"
  756         "    }\n\n");
  757     webu_write(webui, response);
  758 }
  759 
  760 static void webu_html_script_camera_thread(struct webui_ctx *webui) {
  761     /* Write the javascript thread IF conditions of camera_click() function */
  762     char response[WEBUI_LEN_RESP];
  763     int indx, indx_st, preview_scale;
  764     struct strminfo_ctx strm_info;
  765 
  766     indx_st = 1;
  767     if (webui->cam_threads == 1) indx_st = 0;
  768 
  769     strm_info.cntlst = webui->cntlst;
  770 
  771     for (indx = indx_st; indx<webui->cam_threads; indx++){
  772         snprintf(response, sizeof (response),
  773             "      if (camid == \"cam_%05d\"){\n"
  774             ,webui->cntlst[indx]->camera_id);
  775         webu_write(webui, response);
  776 
  777         if (webui->cntlst[indx]->conf.stream_preview_method == 3){
  778             preview_scale = 45;
  779         } else {
  780             preview_scale = 95;
  781         }
  782 
  783         strm_info.motion_images = FALSE;
  784         webu_html_strminfo(&strm_info, indx);
  785         snprintf(response, sizeof (response),
  786             "        preview=\"<a href=%s://%s:%d%s%s> "
  787             " <img src=%s://%s:%d%s%s/ border=0 width=%d%%></a>\"  \n"
  788             ,strm_info.proto, webui->hostname, strm_info.port
  789             ,strm_info.lnk_camid, strm_info.lnk_ref
  790             ,strm_info.proto, webui->hostname,strm_info.port
  791             ,strm_info.lnk_camid, strm_info.lnk_src, preview_scale);
  792         webu_write(webui, response);
  793 
  794         if (webui->cntlst[indx]->conf.stream_preview_method == 3){
  795             strm_info.motion_images = TRUE;
  796             webu_html_strminfo(&strm_info, indx);
  797             snprintf(response, sizeof (response),
  798                 "        preview=preview + \"<a href=%s://%s:%d%s%s> "
  799                 " <img src=%s://%s:%d%s%s/ class=border width=%d%%></a>\"  \n"
  800                 ,strm_info.proto, webui->hostname, strm_info.port
  801                 ,strm_info.lnk_camid, strm_info.lnk_ref
  802                 ,strm_info.proto, webui->hostname,strm_info.port
  803                 ,strm_info.lnk_camid, strm_info.lnk_src, preview_scale);
  804             webu_write(webui, response);
  805         }
  806 
  807         if (webui->cntlst[indx]->conf.camera_name == NULL){
  808             snprintf(response, sizeof (response),
  809                 "        header=\"<h3 id='h3_cam' data-cam='\" + camid + \"' "
  810                 " class='header-center' >%s %d (%s)</h3>\"\n"
  811                 ,_("Camera")
  812                 , webui->cntlst[indx]->camera_id
  813                 ,(!webui->cntlst[indx]->running)? _("Not running") :
  814                  (webui->cntlst[indx]->lost_connection)? _("Lost connection"):
  815                  (webui->cntlst[indx]->pause)? _("Paused"):_("Active")
  816              );
  817         } else {
  818             snprintf(response, sizeof (response),
  819                 "        header=\"<h3 id='h3_cam' data-cam='\" + camid + \"' "
  820                 " class='header-center' >%s (%s)</h3>\"\n"
  821                 , webui->cntlst[indx]->conf.camera_name
  822                 ,(!webui->cntlst[indx]->running)? _("Not running") :
  823                  (webui->cntlst[indx]->lost_connection)? _("Lost connection"):
  824                  (webui->cntlst[indx]->pause)? _("Paused"):_("Active")
  825                 );
  826         }
  827         webu_write(webui, response);
  828 
  829         snprintf(response, sizeof (response),"%s","      }\n");
  830         webu_write(webui, response);
  831     }
  832 
  833     return;
  834 }
  835 
  836 static void webu_html_script_camera_all(struct webui_ctx *webui) {
  837     /* Write the javascript "All" IF condition of camera_click() function */
  838     char response[WEBUI_LEN_RESP];
  839     int indx, indx_st, preview_scale;
  840     struct strminfo_ctx strm_info;
  841 
  842 
  843     indx_st = 1;
  844     if (webui->cam_threads == 1) indx_st = 0;
  845 
  846     strm_info.cntlst = webui->cntlst;
  847 
  848     snprintf(response, sizeof (response), "      if (camid == \"cam_all00\"){\n");
  849     webu_write(webui, response);
  850 
  851     for (indx = indx_st; indx<webui->cam_threads; indx++){
  852         if (indx == indx_st){
  853             snprintf(response, sizeof (response),"%s","        preview = \"\";\n");
  854             webu_write(webui, response);
  855         }
  856 
  857         if (webui->cntlst[indx]->conf.stream_preview_newline){
  858             snprintf(response, sizeof (response),"%s","        preview = preview + \"      <br>\";\n");
  859             webu_write(webui, response);
  860         }
  861 
  862         if (webui->cntlst[indx]->conf.stream_preview_method == 3){
  863             preview_scale = 45;
  864         } else {
  865             preview_scale = webui->cntlst[indx]->conf.stream_preview_scale;
  866         }
  867 
  868         strm_info.motion_images = FALSE;
  869         webu_html_strminfo(&strm_info, indx);
  870         snprintf(response, sizeof (response),
  871             "        preview = preview + \"<a href=%s://%s:%d%s%s> "
  872             " <img src=%s://%s:%d%s%s border=0 width=%d%%></a>\"; \n"
  873             ,strm_info.proto, webui->hostname, strm_info.port
  874             ,strm_info.lnk_camid, strm_info.lnk_ref
  875             ,strm_info.proto, webui->hostname, strm_info.port
  876             ,strm_info.lnk_camid, strm_info.lnk_src
  877             ,preview_scale);
  878         webu_write(webui, response);
  879 
  880         if (webui->cntlst[indx]->conf.stream_preview_method == 3){
  881             strm_info.motion_images = TRUE;
  882             webu_html_strminfo(&strm_info, indx);
  883             snprintf(response, sizeof (response),
  884                 "        preview = preview + \"<a href=%s://%s:%d%s%s> "
  885                 " <img src=%s://%s:%d%s%s class=border width=%d%%></a>\"; \n"
  886                 ,strm_info.proto, webui->hostname, strm_info.port
  887                 ,strm_info.lnk_camid, strm_info.lnk_ref
  888                 ,strm_info.proto, webui->hostname, strm_info.port
  889                 ,strm_info.lnk_camid, strm_info.lnk_src
  890                 ,preview_scale);
  891             webu_write(webui, response);
  892         }
  893     }
  894 
  895     snprintf(response, sizeof (response),
  896         "        header=\"<h3 id='h3_cam' data-cam='\" + camid + \"' "
  897         " class='header-center' >%s</h3>\"\n"
  898         "      }\n"
  899         ,_("All Cameras"));
  900     webu_write(webui, response);
  901 
  902     return;
  903 }
  904 
  905 static void webu_html_script_camera(struct webui_ctx *webui) {
  906     /* Write the javascript camera_click() function */
  907     char response[WEBUI_LEN_RESP];
  908 
  909     snprintf(response, sizeof (response),"%s",
  910         "    function camera_click(camid) {\n"
  911         "      var preview = \"\";\n"
  912         "      var header = \"\";\n");
  913     webu_write(webui, response);
  914 
  915     webu_html_script_camera_thread(webui);
  916 
  917     webu_html_script_camera_all(webui);
  918 
  919     snprintf(response, sizeof (response),"%s",
  920         "      document.getElementById(\"id_preview\").innerHTML = preview; \n"
  921         "      document.getElementById(\"id_header\").innerHTML = header; \n"
  922         "      document.getElementById('cfg_form').style.display=\"none\"; \n"
  923         "      document.getElementById('trk_form').style.display=\"none\"; \n"
  924         "      document.getElementById('cam_btn').style.display=\"none\"; \n"
  925         "      document.getElementById('cfg_value').value = '';\n"
  926         "      document.getElementById('cfg_parms').value = 'default';\n"
  927         "    }\n\n");
  928     webu_write(webui, response);
  929 
  930 }
  931 
  932 static void webu_html_script_menucam(struct webui_ctx *webui) {
  933     /* Write the javascript display_cameras() function */
  934     char response[WEBUI_LEN_RESP];
  935 
  936     snprintf(response, sizeof (response),"%s",
  937         "    function display_cameras() {\n"
  938         "      document.getElementById('act_btn').style.display = 'none';\n"
  939         "      if (document.getElementById('cam_btn').style.display == 'block'){\n"
  940         "        document.getElementById('cam_btn').style.display = 'none';\n"
  941         "      } else {\n"
  942         "        document.getElementById('cam_btn').style.display = 'block';\n"
  943         "      }\n"
  944         "    }\n\n");
  945     webu_write(webui, response);
  946 
  947 }
  948 
  949 static void webu_html_script_menuact(struct webui_ctx *webui) {
  950     /* Write the javascript display_actions() function */
  951     char response[WEBUI_LEN_RESP];
  952 
  953     snprintf(response, sizeof (response),"%s",
  954         "    function display_actions() {\n"
  955         "      document.getElementById('cam_btn').style.display = 'none';\n"
  956         "      if (document.getElementById('act_btn').style.display == 'block'){\n"
  957         "        document.getElementById('act_btn').style.display = 'none';\n"
  958         "      } else {\n"
  959         "        document.getElementById('act_btn').style.display = 'block';\n"
  960         "      }\n"
  961         "    }\n\n");
  962     webu_write(webui, response);
  963 
  964 }
  965 
  966 static void webu_html_script_evtclk(struct webui_ctx *webui) {
  967     /* Write the javascript 'click' EventListener */
  968     char response[WEBUI_LEN_RESP];
  969 
  970     snprintf(response, sizeof (response),"%s",
  971         "    document.addEventListener('click', function(event) {\n"
  972         "      const dropCam = document.getElementById('cam_drop');\n"
  973         "      const dropAct = document.getElementById('act_drop');\n"
  974         "      if (!dropCam.contains(event.target) && !dropAct.contains(event.target)) {\n"
  975         "        document.getElementById('cam_btn').style.display = 'none';\n"
  976         "        document.getElementById('act_btn').style.display = 'none';\n"
  977         "      }\n"
  978         "    });\n\n");
  979     webu_write(webui, response);
  980 
  981 }
  982 
  983 static void webu_html_script_cfgclk(struct webui_ctx *webui) {
  984     /* Write the javascript config_click function
  985      * We do not have a good notification section on the page so the successful
  986      * submission and response is currently a empty if block for the future
  987      * enhancement to somehow notify the user everything worked */
  988 
  989     char response[WEBUI_LEN_RESP];
  990 
  991     snprintf(response, sizeof (response),"%s",
  992         "    function config_click() {\n"
  993         "      var camstr = document.getElementById('h3_cam').getAttribute('data-cam');\n"
  994         "      var camnbr = camstr.substring(4,9);\n"
  995         "      var opts = document.getElementById('cfg_parms');\n"
  996         "      var optsel = opts.options[opts.selectedIndex].value;\n"
  997         "      var baseval = document.getElementById('cfg_value').value;\n"
  998         "      var http = new XMLHttpRequest();\n");
  999     webu_write(webui, response);
 1000 
 1001     snprintf(response, sizeof (response),
 1002         "      var url = \"%s://%s:%d/\"; \n"
 1003         ,webui->hostproto, webui->hostname
 1004         ,webui->cntlst[0]->conf.webcontrol_port);
 1005     webu_write(webui, response);
 1006 
 1007     snprintf(response, sizeof (response),
 1008         "      var optval=encodeURI(baseval);\n"
 1009         "      if (camnbr == \"all00\"){\n"
 1010         "        url = url + \"%05d\";\n"
 1011         "      } else {\n"
 1012         "        url = url + camnbr;\n"
 1013         "      }\n"
 1014         ,webui->cntlst[0]->camera_id);
 1015     webu_write(webui, response);
 1016 
 1017     snprintf(response, sizeof (response),"%s",
 1018         "      url = url + \"/config/set?\" + optsel + \"=\" + optval;\n"
 1019         "      http.open(\"GET\", url, true);\n"
 1020         "      http.onreadystatechange = function() {\n"
 1021         "        if(http.readyState == 4 && http.status == 200) {\n"
 1022         "        }\n"
 1023         "      }\n"
 1024         "      http.send(null);\n"
 1025         "      document.getElementById('cfg_value').value = \"\";\n"
 1026         "      opts.options[opts.selectedIndex].setAttribute('data-'+camstr,baseval);\n"
 1027         "      opts.value = 'default';\n"
 1028         "    }\n\n");
 1029     webu_write(webui, response);
 1030 
 1031 }
 1032 
 1033 static void webu_html_script_cfgchg(struct webui_ctx *webui) {
 1034     /* Write the javascript option_change function */
 1035     char response[WEBUI_LEN_RESP];
 1036 
 1037     snprintf(response, sizeof (response),"%s",
 1038         "    function config_change() {\n"
 1039         "      var camSel = 'data-'+ document.getElementById('h3_cam').getAttribute('data-cam');\n"
 1040         "      var opts = document.getElementById('cfg_parms');\n"
 1041         "      var optval = opts.options[opts.selectedIndex].getAttribute(camSel);\n"
 1042         "      if (optval == null){\n"
 1043         "        optval = opts.options[opts.selectedIndex].getAttribute('data-cam_all00');\n"
 1044         "      }\n"
 1045         "      document.getElementById('cfg_value').value = optval;\n"
 1046         "    }\n\n");
 1047     webu_write(webui, response);
 1048 }
 1049 
 1050 static void webu_html_script_trkchg(struct webui_ctx *webui) {
 1051     char response[WEBUI_LEN_RESP];
 1052 
 1053     snprintf(response, sizeof (response),"%s",
 1054         "    function track_change() {\n"
 1055         "      var opts = document.getElementById('trk_option');\n"
 1056         "      var optval = opts.options[opts.selectedIndex].getAttribute('data-trk');\n"
 1057         "      if (optval == 'pan'){\n"
 1058         "        document.getElementById('trk_panx').disabled=false;\n"
 1059         "        document.getElementById('trk_tilty').disabled = false;\n"
 1060         "        document.getElementById('trk_lblx').style.display='none';\n"
 1061         "        document.getElementById('trk_lbly').style.display='none';\n"
 1062         "        document.getElementById('trk_lblpan').style.display='inline';\n"
 1063         "        document.getElementById('trk_lbltilt').style.display='inline';\n");
 1064     webu_write(webui, response);
 1065 
 1066     snprintf(response, sizeof (response),"%s",
 1067         "      } else if (optval =='abs'){\n"
 1068         "        document.getElementById('trk_panx').disabled=false;\n"
 1069         "        document.getElementById('trk_tilty').disabled = false;\n"
 1070         "        document.getElementById('trk_lblx').value = 'X';\n"
 1071         "        document.getElementById('trk_lbly').value = 'Y';\n"
 1072         "        document.getElementById('trk_lblpan').style.display='none';\n"
 1073         "        document.getElementById('trk_lbltilt').style.display='none';\n"
 1074         "        document.getElementById('trk_lblx').style.display='inline';\n"
 1075         "        document.getElementById('trk_lbly').style.display='inline';\n");
 1076     webu_write(webui, response);
 1077 
 1078    snprintf(response, sizeof (response),"%s",
 1079         "      } else {\n"
 1080         "        document.getElementById('cfg_form').style.display='none';\n"
 1081         "        document.getElementById('trk_panx').disabled=true;\n"
 1082         "        document.getElementById('trk_tilty').disabled = true;\n"
 1083         "      }\n"
 1084         "    }\n\n");
 1085     webu_write(webui, response);
 1086 
 1087 }
 1088 
 1089 static void webu_html_script_trkclk(struct webui_ctx *webui) {
 1090     char response[WEBUI_LEN_RESP];
 1091     snprintf(response, sizeof (response),"%s",
 1092         "    function track_click() {\n"
 1093         "      var camstr = document.getElementById('h3_cam').getAttribute('data-cam');\n"
 1094         "      var camnbr = camstr.substring(4,9);\n"
 1095         "      var opts = document.getElementById('trk_option');\n"
 1096         "      var optsel = opts.options[opts.selectedIndex].getAttribute('data-trk');\n"
 1097         "      var optval1 = document.getElementById('trk_panx').value;\n"
 1098         "      var optval2 = document.getElementById('trk_tilty').value;\n"
 1099         "      var http = new XMLHttpRequest();\n");
 1100     webu_write(webui, response);
 1101 
 1102     snprintf(response, sizeof (response),
 1103         "      var url = \"%s://%s:%d/\"; \n"
 1104         ,webui->hostproto, webui->hostname
 1105         ,webui->cntlst[0]->conf.webcontrol_port);
 1106     webu_write(webui, response);
 1107 
 1108     snprintf(response, sizeof (response),
 1109         "      if (camnbr == \"all00\"){\n"
 1110         "        url = url + \"%05d\";\n"
 1111         "      } else {\n"
 1112         "        url = url + camnbr;\n"
 1113         "      }\n"
 1114         ,webui->cntlst[0]->camera_id);
 1115     webu_write(webui, response);
 1116 
 1117     snprintf(response, sizeof (response),"%s",
 1118 
 1119         "      if (optsel == 'pan'){\n"
 1120         "        url = url + '/track/set?pan=' + optval1 + '&tilt=' + optval2;\n"
 1121         "      } else if (optsel == 'abs') {\n"
 1122         "        url = url + '/track/set?x=' + optval1 + '&y=' + optval2;\n"
 1123         "      } else {\n"
 1124         "        url = url + '/track/center'\n"
 1125         "      }\n"
 1126         "      http.open(\"GET\", url, true);\n"
 1127         "      http.onreadystatechange = function() {\n"
 1128         "        if(http.readyState == 4 && http.status == 200) {\n"
 1129         "         }\n"
 1130         "      }\n"
 1131         "      http.send(null);\n"
 1132         "    }\n\n");
 1133     webu_write(webui, response);
 1134 
 1135 }
 1136 
 1137 static void webu_html_script(struct webui_ctx *webui) {
 1138     /* Write the javascripts */
 1139     char response[WEBUI_LEN_RESP];
 1140 
 1141     snprintf(response, sizeof (response),"%s", "  <script>\n");
 1142     webu_write(webui, response);
 1143 
 1144     webu_html_script_action(webui);
 1145 
 1146     webu_html_script_camera(webui);
 1147 
 1148     webu_html_script_cfgclk(webui);
 1149 
 1150     webu_html_script_cfgchg(webui);
 1151 
 1152     webu_html_script_trkclk(webui);
 1153 
 1154     webu_html_script_trkchg(webui);
 1155 
 1156     webu_html_script_menucam(webui);
 1157 
 1158     webu_html_script_menuact(webui);
 1159 
 1160     webu_html_script_evtclk(webui);
 1161 
 1162     snprintf(response, sizeof (response),"%s", "  </script>\n");
 1163     webu_write(webui, response);
 1164 
 1165 }
 1166 
 1167 static void webu_html_body(struct webui_ctx *webui) {
 1168     /* Write the body section of the form */
 1169     char response[WEBUI_LEN_RESP];
 1170 
 1171     snprintf(response, sizeof (response),"%s","<body class=\"body\">\n");
 1172     webu_write(webui, response);
 1173 
 1174     webu_html_navbar(webui);
 1175 
 1176     webu_html_h3desc(webui);
 1177 
 1178     webu_html_config(webui);
 1179 
 1180     webu_html_track(webui);
 1181 
 1182     webu_html_preview(webui);
 1183 
 1184     webu_html_script(webui);
 1185 
 1186     snprintf(response, sizeof (response),"%s", "</body>\n");
 1187     webu_write(webui, response);
 1188 
 1189 }
 1190 
 1191 static void webu_html_page(struct webui_ctx *webui) {
 1192     /* Write the main page html */
 1193     char response[WEBUI_LEN_RESP];
 1194 
 1195     snprintf(response, sizeof (response),
 1196         "<!DOCTYPE html>\n"
 1197         "<html lang=\"%s\">\n",webui->lang);
 1198     webu_write(webui, response);
 1199 
 1200     webu_html_head(webui);
 1201 
 1202     webu_html_body(webui);
 1203 
 1204     snprintf(response, sizeof (response),"%s", "</html>\n");
 1205     webu_write(webui, response);
 1206 
 1207 }
 1208 
 1209 void webu_html_badreq(struct webui_ctx *webui) {
 1210 
 1211     char response[WEBUI_LEN_RESP];
 1212 
 1213     snprintf(response, sizeof (response),"%s",
 1214         "<!DOCTYPE html>\n"
 1215         "<html>\n"
 1216         "<body>\n"
 1217         "<p>Bad Request</p>\n"
 1218         "<p>The server did not understand your request.</p>\n"
 1219         "</body>\n"
 1220         "</html>\n");
 1221     webu_write(webui, response);
 1222 
 1223     return;
 1224 
 1225 }
 1226 
 1227 void webu_html_main(struct webui_ctx *webui) {
 1228 
 1229     /* Note some detection and config requested actions call the
 1230      * action function.  This is because the legacy interface
 1231      * put these into those pages.  We put them together here
 1232      * based upon the structure of the new interface
 1233      */
 1234 
 1235     int retcd;
 1236 
 1237     retcd = 0;
 1238     if (strlen(webui->uri_camid) == 0){
 1239         webu_html_page(webui);
 1240 
 1241     } else if ((!strcmp(webui->uri_cmd1,"config")) &&
 1242                (!strcmp(webui->uri_cmd2,"write"))) {
 1243         webu_process_action(webui);
 1244 
 1245     } else if (!strcmp(webui->uri_cmd1,"config")) {
 1246         retcd = webu_process_config(webui);
 1247 
 1248     } else if (!strcmp(webui->uri_cmd1,"action")){
 1249         webu_process_action(webui);
 1250 
 1251     } else if (!strcmp(webui->uri_cmd1,"detection")){
 1252         webu_process_action(webui);
 1253 
 1254     } else if (!strcmp(webui->uri_cmd1,"track")){
 1255         retcd = webu_process_track(webui);
 1256 
 1257     } else{
 1258         MOTION_LOG(INF, TYPE_STREAM, NO_ERRNO,
 1259             _("Invalid action requested: >%s< >%s< >%s<")
 1260             ,webui->uri_camid, webui->uri_cmd1, webui->uri_cmd2);
 1261         retcd = -1;
 1262     }
 1263 
 1264     if (retcd < 0) webu_html_badreq(webui);
 1265 
 1266     return;
 1267 }