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> </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> | </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, "] ");
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, "] \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, "] \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;
}