static int JK_METHOD service()

in native/common/jk_status.c [4752:5283]


static int JK_METHOD service(jk_endpoint_t *e,
                             jk_ws_service_t *s,
                             jk_log_context_t *l, int *is_error)
{
    int cmd;
    jk_uint32_t cmd_props;
    int mime;
    int refresh;
    int read_only = 0;
    const char *arg;
    char *err = NULL;
    status_endpoint_t *p;
    status_worker_t *w;
    int denied = 0;

    JK_TRACE_ENTER(l);

    if (!e || !e->endpoint_private || !s || !is_error) {
        JK_LOG_NULL_PARAMS(l);
        if (is_error)
            *is_error = JK_HTTP_SERVER_ERROR;
        JK_TRACE_EXIT(l);
        return JK_FALSE;
    }

    p = e->endpoint_private;
    w = p->worker;

    /* Set returned error to OK */
    *is_error = JK_HTTP_OK;

    if (w->num_of_users) {
        if (s->remote_user) {
            unsigned int i;
            denied = 1;
            for (i = 0; i < w->num_of_users; i++) {
                if (w->user_case_insensitive) {
                    if (!strcasecmp(s->remote_user, w->user_names[i])) {
                        denied = 0;
                        break;
                    }
                }
                else {
                    if (!strcmp(s->remote_user, w->user_names[i])) {
                        denied = 0;
                        break;
                    }
                }
            }
        }
        else {
            denied = 2;
        }
    }

    /* Step 0: Unescape request uri and make safe against XSS */
    if (status_unescape_uri(s, p, l) != JK_TRUE) {
        if (is_error)
            *is_error = JK_HTTP_SERVER_ERROR;
        JK_TRACE_EXIT(l);
        return JK_FALSE;
    }

    /* Step 1: Process GET params and update configuration */
    if (status_parse_uri(s, p, l) != JK_TRUE) {
        err = "Error during parsing of URI";
    }
    status_get_string(p, JK_STATUS_ARG_CMD, NULL, &arg, l);
    cmd = status_cmd_int(arg);
    cmd_props = status_cmd_props(cmd);
    status_get_string(p, JK_STATUS_ARG_MIME, NULL, &arg, l);
    mime = status_mime_int(arg);
    refresh = status_get_int(p, JK_STATUS_ARG_REFRESH, 0, l);
    if (w->read_only) {
        read_only = 1;
    }
    else {
        read_only = status_get_int(p, JK_STATUS_ARG_OPTIONS, 0, l) &
                    JK_STATUS_ARG_OPTION_READ_ONLY;
    }

    if (mime == JK_STATUS_MIME_HTML) {
        s->start_response(s, 200, "OK", headers_names, headers_vhtml, 3);
        jk_puts(s, JK_STATUS_HEAD);
    }
    else if (mime == JK_STATUS_MIME_XML) {
        s->start_response(s, 200, "OK", headers_names, headers_vxml, 3);
        jk_puts(s, JK_STATUS_XMLH);
        if (w->doctype) {
            jk_putv(s, w->doctype, "\n", NULL);
        }
        jk_print_xml_start_elt(s, l, w, 0, 0, "status");
        if (w->xmlns && strlen(w->xmlns))
            jk_putv(s, "  ", w->xmlns, NULL);
        jk_print_xml_stop_elt(s, l, 0, 0);
    }
    else {
        s->start_response(s, 200, "OK", headers_names, headers_vtxt, 3);
    }

    if (denied == 0) {
        if (JK_IS_DEBUG_LEVEL(l))
            jk_log(l, JK_LOG_DEBUG,
                   "Status worker '%s' service allowed for user '%s' [%s] from %s [%s]",
                   w->name,
                   s->remote_user ? s->remote_user : "(null)",
                   s->auth_type ? s->auth_type : "(null)",
                   s->remote_addr ? s->remote_addr : "(null)",
                   s->remote_host ? s->remote_host : "(null)");
    }
    else if (denied == 1) {
        err = "Access denied.";
        jk_log(l, JK_LOG_WARNING,
               "Status worker '%s' service denied for user '%s' [%s] from %s [%s]",
               w->name,
               s->remote_user ? s->remote_user : "(null)",
               s->auth_type ? s->auth_type : "(null)",
               s->remote_addr ? s->remote_addr : "(null)",
               s->remote_host ? s->remote_host : "(null)");
    }
    else if (denied == 2) {
        err = "Access denied.";
        jk_log(l, JK_LOG_WARNING,
               "Status worker '%s' service denied (no user) [%s] from %s [%s]",
               w->name,
               s->remote_user ? s->remote_user : "(null)",
               s->auth_type ? s->auth_type : "(null)",
               s->remote_addr ? s->remote_addr : "(null)",
               s->remote_host ? s->remote_host : "(null)");
    }
    else {
        err = "Access denied.";
        jk_log(l, JK_LOG_WARNING,
               "Status worker '%s' service denied (unknown reason) for user '%s' [%s] from %s [%s]",
               w->name,
               s->remote_user ? s->remote_user : "(null)",
               s->auth_type ? s->auth_type : "(null)",
               s->remote_addr ? s->remote_addr : "(null)",
               s->remote_host ? s->remote_host : "(null)");
    }

    if (!err) {
        if (read_only && !(cmd_props & JK_STATUS_CMD_PROP_READONLY)) {
            err = "This command is not allowed in read only mode.";
        }
    }

    if (!err) {
        if (cmd == JK_STATUS_CMD_UNKNOWN) {
            err = "Invalid command.";
        }
        else if (mime == JK_STATUS_MIME_UNKNOWN) {
            err = "Invalid mime type.";
        }
        else if (cmd_props & JK_STATUS_CMD_PROP_CHECK_WORKER &&
                 (check_worker(s, p, cmd_props & JK_STATUS_CMD_PROP_WILDCARD, l) != JK_TRUE)) {
            err = p->msg;
        }
    }

    if (!err) {
        char buf_time[JK_STATUS_TIME_BUF_SZ];
        char buf_tz[JK_STATUS_TIME_BUF_SZ];
        time_t clock = time(NULL);
        long unix_seconds = (long)clock;
        int rc_time = status_strftime(clock, mime, buf_time, buf_tz, l);
        if (cmd == JK_STATUS_CMD_UPDATE) {
            /* lock shared memory */
            jk_shm_lock();
            if (update_worker(s, p, l) == JK_FALSE) {
                if (strncmp("OK", p->msg, 3))
                    err = p->msg;
                else
                    err = "Update failed";
            }
            /* unlock the shared memory */
            jk_shm_unlock();
            if (mime == JK_STATUS_MIME_HTML) {
                write_html_refresh_response(s, p, err, l);
            }
        }
        else if (cmd == JK_STATUS_CMD_RESET) {
            /* lock shared memory */
            jk_shm_lock();
            if (reset_worker(s, p, l) == JK_FALSE) {
                err = "Reset failed";
            }
            /* unlock the shared memory */
            jk_shm_unlock();
            if (mime == JK_STATUS_MIME_HTML) {
                write_html_refresh_response(s, p, err, l);
            }
        }
        else if (cmd == JK_STATUS_CMD_RECOVER) {
            /* lock shared memory */
            jk_shm_lock();
            if (recover_worker(s, p, l) == JK_FALSE) {
                err = "Marking worker for recovery failed";
            }
            /* unlock the shared memory */
            jk_shm_unlock();
            if (mime == JK_STATUS_MIME_HTML) {
                write_html_refresh_response(s, p, err, l);
            }
        }
        else {
            if (mime == JK_STATUS_MIME_XML) {
                jk_print_xml_start_elt(s, l, w, 0, 0, "server");
                jk_print_xml_att_string(s, l, 2, "name", s->server_name);
                jk_print_xml_att_int(s, l, 2, "port", s->server_port);
                jk_print_xml_stop_elt(s, l, 0, 1);
                if (cmd_props & JK_STATUS_CMD_PROP_HEAD) {
                    if (rc_time > 0) {
                        jk_print_xml_start_elt(s, l, w, 0, 0, "time");
                        jk_print_xml_att_string(s, l, 2, "datetime", buf_time);
                        jk_print_xml_att_string(s, l, 2, "tz", buf_tz);
                        jk_print_xml_att_long(s, l, 2, "unix", unix_seconds);
                        jk_print_xml_stop_elt(s, l, 0, 1);
                    }
                    jk_print_xml_start_elt(s, l, w, 0, 0, "software");
                    jk_print_xml_att_string(s, l, 2, "web_server", s->server_software);
                    jk_print_xml_att_string(s, l, 2, "jk_version", JK_FULL_EXPOSED_VERSION);
                    jk_print_xml_stop_elt(s, l, 0, 1);
                }
                if (cmd == JK_STATUS_CMD_LIST) {
                    /* Step 2: Display configuration */
                    if (list_workers(s, p, l) != JK_TRUE) {
                        err = "Error in listing the workers.";
                    }
                }
                else if (cmd == JK_STATUS_CMD_SHOW) {
                    /* Step 2: Display detailed configuration */
                    if (show_worker(s, p, l) != JK_TRUE) {
                        err = "Error in showing this worker.";
                    }
                }
            }
            else if (mime == JK_STATUS_MIME_TXT) {
                jk_puts(s, "Server:");
                jk_printf(s, l, " name=%s", s->server_name);
                jk_printf(s, l, " port=%d", s->server_port);
                jk_puts(s, "\n");
                if (cmd_props & JK_STATUS_CMD_PROP_HEAD) {
                    if (rc_time > 0) {
                        jk_puts(s, "Time:");
                        jk_printf(s, l, " datetime=%s", buf_time);
                        jk_printf(s, l, " tz=%s", buf_tz);
                        jk_printf(s, l, " unix=%ld", unix_seconds);
                        jk_puts(s, "\n");
                    }
                    jk_puts(s, "Software:");
                    jk_printf(s, l, " web_server=\"%s\"", s->server_software);
                    jk_printf(s, l, " jk_version=%s", JK_FULL_EXPOSED_VERSION);
                    jk_puts(s, "\n");
                }
                if (cmd == JK_STATUS_CMD_LIST) {
                    /* Step 2: Display configuration */
                    if (list_workers(s, p, l) != JK_TRUE) {
                        err = "Error in listing the workers.";
                    }
                }
                else if (cmd == JK_STATUS_CMD_SHOW) {
                    /* Step 2: Display detailed configuration */
                    if (show_worker(s, p, l) != JK_TRUE) {
                        err = "Error in showing this worker.";
                    }
                }
            }
            else if (mime == JK_STATUS_MIME_PROP) {
                jk_print_prop_att_string(s, l, w, NULL, "server_name", s->server_name);
                jk_print_prop_att_int(s, l, w, NULL, "server_port", s->server_port);
                if (cmd_props & JK_STATUS_CMD_PROP_HEAD) {
                    if (rc_time > 0) {
                        jk_print_prop_att_string(s, l, w, NULL, "time_datetime", buf_time);
                        jk_print_prop_att_string(s, l, w, NULL, "time_tz", buf_tz);
                        jk_print_prop_att_long(s, l, w, NULL, "time_unix", unix_seconds);
                    }
                    jk_print_prop_att_string(s, l, w, NULL, "web_server", s->server_software);
                    jk_print_prop_att_string(s, l, w, NULL, "jk_version", JK_FULL_EXPOSED_VERSION);
                }
                if (cmd == JK_STATUS_CMD_LIST) {
                    /* Step 2: Display configuration */
                    if (list_workers(s, p, l) != JK_TRUE) {
                        err = "Error in listing the workers.";
                    }
                }
                else if (cmd == JK_STATUS_CMD_SHOW) {
                    /* Step 2: Display detailed configuration */
                    if (show_worker(s, p, l) != JK_TRUE) {
                        err = "Error in showing this worker.";
                    }
                }
            }
            else if (mime == JK_STATUS_MIME_HTML) {
                if (cmd_props & JK_STATUS_CMD_PROP_REFRESH &&
                    refresh > 0) {
                    jk_printf(s, l, "\n<meta http-equiv=\"Refresh\" content=\"%d;url=%s?%s\">",
                          refresh, p->req_uri, p->query_string);
                }
                if (w->css) {
                    jk_putv(s, "\n<link rel=\"stylesheet\" type=\"text/css\" href=\"",
                            w->css, "\" />\n", NULL);
                }
                jk_puts(s, JK_STATUS_HEND);
                jk_puts(s, "<h1>JK Status Manager for ");
                jk_puts(s, s->server_name);
                jk_printf(s, l, ":%d", s->server_port);
                if (read_only) {
                    jk_puts(s, " (read only)");
                }
                jk_puts(s, "</h1>\n\n");
                if (cmd_props & JK_STATUS_CMD_PROP_HEAD) {
                    jk_putv(s, "<table><tr><td>Server Version:</td><td>",
                            s->server_software, "</td><td>&nbsp;&nbsp;&nbsp;</td><td>", NULL);
                    if (rc_time > 0) {
                        jk_putv(s, "Server Time:</td><td>", buf_time, NULL);
                    }
                    jk_puts(s, "</td></tr>\n");
                    jk_putv(s, "<tr><td>JK Version:</td><td>",
                            JK_FULL_EXPOSED_VERSION, "</td><td></td><td>", NULL);
                    jk_printf(s, l, "Unix Seconds:</td><td>%d", unix_seconds);
                    jk_puts(s, "</td></tr></table>\n<hr/>\n");
                }
                jk_puts(s, "<table><tbody valign=\"baseline\"><tr>\n");
                if (cmd_props & JK_STATUS_CMD_PROP_REFRESH) {
                    jk_puts(s, "<td>");
                    if (refresh > 0) {
                        const char *str = p->query_string;
                        char *buf = jk_pool_alloc(s->pool, sizeof(char *) * (strlen(str)+1));
                        int result = 0;
                        size_t scan = 0;
                        size_t len = strlen(JK_STATUS_ARG_REFRESH);

                        while (str[scan] != '\0') {
                            if (strncmp(&str[scan], JK_STATUS_ARG_REFRESH, len) == 0 &&
                                str[scan+len] == '=') {
                                scan += len + 1;
                                while (str[scan] != '\0' && str[scan] != '&')
                                    scan++;
                                if (str[scan] == '&')
                                    scan++;
                            }
                            else {
                                if (result > 0 && str[scan] != '\0' && str[scan] != '&') {
                                    buf[result] = '&';
                                    result++;
                                }
                                while (str[scan] != '\0' && str[scan] != '&') {
                                    buf[result] = str[scan];
                                    result++;
                                    scan++;
                                }
                                if (str[scan] == '&')
                                    scan++;
                            }
                        }
                        buf[result] = '\0';

                        jk_putv(s, "[<a href=\"", p->req_uri, NULL);
                        if (buf && buf[0])
                            jk_putv(s, "?", buf, NULL);
                        jk_puts(s, "\">Stop auto refresh</a>]");
                    }
                    else {
                        status_start_form(s, p, "get", JK_STATUS_CMD_UNKNOWN, JK_STATUS_ARG_REFRESH, l);
                        jk_puts(s, "<input type=\"submit\" value=\"Start auto refresh\"/>\n");
                        jk_putv(s, "(every ",
                                "<input name=\"", JK_STATUS_ARG_REFRESH,
                                "\" type=\"text\" size=\"3\" value=\"",
                                JK_STATUS_REFRESH_DEF "\"/> ",
                                "seconds)", NULL);
                        jk_puts(s, "</form>\n");
                    }
                    jk_puts(s, "</td><td>&nbsp;&nbsp;|&nbsp;&nbsp;</td>\n");
                }
                if (cmd_props & JK_STATUS_CMD_PROP_FMT) {
                    jk_puts(s, "<td>\n");
                    status_start_form(s, p, "get", JK_STATUS_CMD_UNKNOWN, JK_STATUS_ARG_MIME, l);
                    jk_puts(s, "<input type=\"submit\" value=\"Change format\"/>\n");
                    jk_putv(s, "<select name=\"", JK_STATUS_ARG_MIME, "\" size=\"1\">", NULL);
                    jk_putv(s, "<option value=\"", JK_STATUS_MIME_TEXT_XML, "\">XML</option>", NULL);
                    jk_putv(s, "<option value=\"", JK_STATUS_MIME_TEXT_PROP, "\">Properties</option>", NULL);
                    jk_putv(s, "<option value=\"", JK_STATUS_MIME_TEXT_TXT, "\">Text</option>", NULL);
                    jk_puts(s, "</select></form>\n");
                    jk_puts(s, "</td>\n");
                }
                jk_puts(s, "</tr></tbody></table>\n");
                jk_puts(s, "<table><tbody valign=\"baseline\"><tr>\n");
                if (cmd_props & JK_STATUS_CMD_PROP_BACK_LINK) {
                    int from;
                    jk_puts(s, "<td>\n");
                    status_get_string(p, JK_STATUS_ARG_FROM, NULL, &arg, l);
                    from = status_cmd_int(arg);
                    jk_puts(s, "[");
                    if (cmd_props & JK_STATUS_CMD_PROP_BACK_LIST ||
                        from == JK_STATUS_CMD_LIST) {
                        status_write_uri(s, p, "Back to worker list", JK_STATUS_CMD_LIST, JK_STATUS_MIME_UNKNOWN,
                                         "", "", 0, 0, "", l);
                    }
                    else {
                        status_write_uri(s, p, "Back to worker view", JK_STATUS_CMD_SHOW, JK_STATUS_MIME_UNKNOWN,
                                         NULL, NULL, 0, 0, "", l);
                    }
                    jk_puts(s, "]&nbsp;&nbsp;");
                    jk_puts(s, "</td>\n");
                }
                if (cmd_props & JK_STATUS_CMD_PROP_SWITCH_RO) {
                    jk_puts(s, "<td>\n");
                    if (!w->read_only) {
                        jk_puts(s, "[");
                        if (read_only) {
                            status_write_uri(s, p, "Read/Write", 0, JK_STATUS_MIME_UNKNOWN,
                                             NULL, NULL, 0, JK_STATUS_ARG_OPTION_READ_ONLY, NULL, l);
                        }
                        else {
                            status_write_uri(s, p, "Read Only", 0, JK_STATUS_MIME_UNKNOWN,
                                             NULL, NULL, JK_STATUS_ARG_OPTION_READ_ONLY, 0, NULL, l);
                        }
                        jk_puts(s, "]&nbsp;&nbsp;\n");
                    }
                    jk_puts(s, "</td>\n");
                }
                if (cmd_props & JK_STATUS_CMD_PROP_DUMP_LINK) {
                    jk_puts(s, "<td>\n");
                    jk_puts(s, "[");
                    status_write_uri(s, p, "Dump", JK_STATUS_CMD_DUMP, JK_STATUS_MIME_UNKNOWN,
                                     NULL, NULL, 0, 0, NULL, l);
                    jk_puts(s, "]&nbsp;&nbsp;\n");
                    jk_puts(s, "</td>\n");
                }
                if (cmd_props & JK_STATUS_CMD_PROP_LINK_HELP &&
                    (cmd == JK_STATUS_CMD_LIST || !read_only)) {
                    jk_puts(s, "<td>\n");
                    jk_puts(s, "[");
                    if (cmd == JK_STATUS_CMD_LIST) {
                        jk_puts(s, "<b>S</b>=Show only this worker, ");
                    }
                    jk_puts(s, "<b>E</b>=Edit worker, <b>R</b>=Reset worker state, <b>T</b>=Try worker recovery");
                    jk_puts(s, "]<br/>\n");
                    jk_puts(s, "</td>\n");
                }
                jk_puts(s, "</tr></tbody></table>\n");
                if (cmd == JK_STATUS_CMD_LIST) {
                    /* Step 2: Display configuration */
                    if (list_workers(s, p, l) != JK_TRUE) {
                        err = "Error in listing the workers.";
                    }
                }
                else if (cmd == JK_STATUS_CMD_SHOW) {
                    /* Step 2: Display detailed configuration */
                    if (show_worker(s, p, l) != JK_TRUE) {
                        err = "Error in showing this worker.";
                    }
                }
                else if (cmd == JK_STATUS_CMD_EDIT) {
                    /* Step 2: Display edit form */
                    if (edit_worker(s, p, l) != JK_TRUE) {
                        err = "Error in generating this worker's configuration form.";
                    }
                }
            }
            if (cmd == JK_STATUS_CMD_DUMP) {
                if (dump_config(s, p, mime, l) == JK_FALSE) {
                    err = "Dumping configuration failed";
                }
            }
            if (cmd_props & JK_STATUS_CMD_PROP_LEGEND) {
                display_legend(s, p, l);
            }
        }
    }
    if (err) {
        jk_log(l, JK_LOG_WARNING, "Status worker '%s': %s", w->name, err);
        if (mime == JK_STATUS_MIME_HTML) {
            jk_putv(s, "<p><b>Result: ERROR - ", err, "</b><br/>", NULL);
            jk_putv(s, "<a href=\"", p->req_uri, "\">JK Status Manager Start Page</a></p>", NULL);
        }
        else if (mime == JK_STATUS_MIME_XML) {
            jk_print_xml_start_elt(s, l, w, 2, 0, "result");
            jk_print_xml_att_string(s, l, 4, "type", "ERROR");
            jk_print_xml_att_string(s, l, 4, "message", err);
            jk_print_xml_stop_elt(s, l, 2, 1);
        }
        else if (mime == JK_STATUS_MIME_TXT) {
            jk_puts(s, "Result:");
            jk_printf(s, l, " type=%s", "ERROR");
            jk_printf(s, l, " message=\"%s\"", err);
            jk_puts(s, "\n");
        }
        else {
            jk_print_prop_att_string(s, l, w, "result", "type", "ERROR");
            jk_print_prop_att_string(s, l, w, "result", "message", err);
        }
    }
    else {
        if (mime == JK_STATUS_MIME_HTML) {
            jk_putv(s, "<p><a href=\"", p->req_uri, "\">JK Status Manager Start Page</a></p>", NULL);
        }
        else if (mime == JK_STATUS_MIME_XML) {
            jk_print_xml_start_elt(s, l, w, 2, 0, "result");
            jk_print_xml_att_string(s, l, 4, "type", "OK");
            jk_print_xml_att_string(s, l, 4, "message", "Action finished");
            jk_print_xml_stop_elt(s, l, 2, 1);
        }
        else if (mime == JK_STATUS_MIME_TXT) {
            jk_puts(s, "Result:");
            jk_printf(s, l, " type=%s", "OK");
            jk_printf(s, l, " message=\"%s\"", "Action finished");
            jk_puts(s, "\n");
        }
        else {
            jk_print_prop_att_string(s, l, w, "result", "type", "OK");
            jk_print_prop_att_string(s, l, w, "result", "message", "Action finished");
        }
    }
    if (mime == JK_STATUS_MIME_HTML) {
        if (w->css) {
            jk_putv(s, "<hr/><div class=\"footer\">", JK_STATUS_COPYRIGHT,
                    "</div>\n", NULL);
        }
        else {
            jk_putv(s, "<hr/><p align=\"center\"><small>", JK_STATUS_COPYRIGHT,
                    "</small></p>\n", NULL);
        }
        jk_puts(s, JK_STATUS_BEND);
    }
    else if (mime == JK_STATUS_MIME_XML) {
        jk_print_xml_close_elt(s, l, w, 0, "status");
    }
    JK_TRACE_EXIT(l);
    return JK_TRUE;
}