static void cmd_http_request( struct server_framework_state *state, struct client_state *p, size_t pkt_size, const struct new_server_prot_packet *pkt_gen) { enum { MAX_PARAM_NUM = 10000, MAX_PARAM_SIZE = 128 * 1024 * 1024, }; const struct new_server_prot_http_request *pkt; size_t in_size; const ej_size_t *arg_sizes, *env_sizes, *param_name_sizes, *param_sizes; unsigned long bptr; const unsigned char ** args; const unsigned char ** envs; const unsigned char ** param_names; const unsigned char ** params; size_t *my_param_sizes; int i; char *out_txt = 0; size_t out_size = 0; FILE *out_f = 0; struct http_request_info hr; unsigned char info_buf[1024]; unsigned char *pbuf = info_buf; memset(&hr, 0, sizeof(hr)); hr.id = p->id; hr.client_state = p; hr.fw_state = state; gettimeofday(&hr.timestamp1, 0); hr.current_time = hr.timestamp1.tv_sec; hr.locale_id = -1; if (pkt_size < sizeof(*pkt)) return nsf_err_packet_too_small(state, p, pkt_size, sizeof(*pkt)); pkt = (const struct new_server_prot_http_request *) pkt_gen; if (pkt->arg_num < 0 || pkt->arg_num > MAX_PARAM_NUM) return nsf_err_protocol_error(state, p); if (pkt->env_num < 0 || pkt->env_num > MAX_PARAM_NUM) return nsf_err_protocol_error(state, p); if (pkt->param_num < 0 || pkt->param_num > MAX_PARAM_NUM) return nsf_err_protocol_error(state, p); in_size = sizeof(*pkt); in_size += pkt->arg_num * sizeof(ej_size_t); in_size += pkt->env_num * sizeof(ej_size_t); in_size += pkt->param_num * 2 * sizeof(ej_size_t); if (pkt_size < in_size) return nsf_err_packet_too_small(state, p, pkt_size, in_size); XALLOCAZ(args, pkt->arg_num); XALLOCAZ(envs, pkt->env_num); XALLOCAZ(param_names, pkt->param_num); XALLOCAZ(params, pkt->param_num); XALLOCAZ(my_param_sizes, pkt->param_num); bptr = (unsigned long) pkt; bptr += sizeof(*pkt); arg_sizes = (const ej_size_t *) bptr; bptr += pkt->arg_num * sizeof(ej_size_t); env_sizes = (const ej_size_t *) bptr; bptr += pkt->env_num * sizeof(ej_size_t); param_name_sizes = (const ej_size_t *) bptr; bptr += pkt->param_num * sizeof(ej_size_t); param_sizes = (const ej_size_t *) bptr; bptr += pkt->param_num * sizeof(ej_size_t); for (i = 0; i < pkt->arg_num; i++) { if (arg_sizes[i] > MAX_PARAM_SIZE) return nsf_err_protocol_error(state, p); in_size += arg_sizes[i] + 1; } for (i = 0; i < pkt->env_num; i++) { if (env_sizes[i] > MAX_PARAM_SIZE) return nsf_err_protocol_error(state, p); in_size += env_sizes[i] + 1; } for (i = 0; i < pkt->param_num; i++) { if (param_name_sizes[i] > MAX_PARAM_SIZE) return nsf_err_protocol_error(state, p); if (param_sizes[i] > MAX_PARAM_SIZE) return nsf_err_protocol_error(state, p); in_size += param_name_sizes[i] + 1; in_size += param_sizes[i] + 1; } if (pkt_size != in_size) return nsf_err_bad_packet_length(state, p, pkt_size, in_size); for (i = 0; i < pkt->arg_num; i++) { args[i] = (const unsigned char*) bptr; bptr += arg_sizes[i] + 1; if (strlen(args[i]) != arg_sizes[i]) return nsf_err_protocol_error(state, p); } for (i = 0; i < pkt->env_num; i++) { envs[i] = (const unsigned char*) bptr; bptr += env_sizes[i] + 1; if (strlen(envs[i]) != env_sizes[i]) return nsf_err_protocol_error(state, p); } for (i = 0; i < pkt->param_num; i++) { param_names[i] = (const unsigned char*) bptr; bptr += param_name_sizes[i] + 1; if (strlen(param_names[i]) != param_name_sizes[i]) return nsf_err_protocol_error(state, p); params[i] = (const unsigned char *) bptr; my_param_sizes[i] = param_sizes[i]; bptr += param_sizes[i] + 1; } hr.arg_num = pkt->arg_num; hr.args = args; hr.env_num = pkt->env_num; hr.envs = envs; hr.param_num = pkt->param_num; hr.param_names = param_names; hr.param_sizes = my_param_sizes; hr.params = params; hr.config = ejudge_config; // ok, generate HTML out_f = open_memstream(&out_txt, &out_size); ns_handle_http_request(state, p, out_f, &hr); close_memstream(out_f); out_f = 0; *pbuf = 0; // report IP? if (hr.ssl_flag) { pbuf = stpcpy(pbuf, "HTTPS:"); } else { pbuf = stpcpy(pbuf, "HTTPS:"); } pbuf = stpcpy(pbuf, xml_unparse_ipv6(&hr.ip)); *pbuf++ = ':'; if (hr.role_name) { pbuf = stpcpy(pbuf, hr.role_name); } if (hr.action > 0 && hr.action < NEW_SRV_ACTION_LAST && ns_symbolic_action_table[hr.action]) { *pbuf++ = '/'; pbuf = stpcpy(pbuf, ns_symbolic_action_table[hr.action]); } if (hr.session_id) { *pbuf++ = '/'; *pbuf++ = 'S'; pbuf += sprintf(pbuf, "%016llx", hr.session_id); if (hr.client_key) { *pbuf++ = '-'; pbuf += sprintf(pbuf, "%016llx", hr.client_key); } } if (hr.user_id > 0) { *pbuf++ = '/'; *pbuf++ = 'U'; pbuf += sprintf(pbuf, "%d", hr.user_id); } if (hr.contest_id > 0) { *pbuf++ = '/'; *pbuf++ = 'C'; pbuf += sprintf(pbuf, "%d", hr.contest_id); } // no reply now if (hr.no_reply) goto cleanup; if (hr.protocol_reply) { xfree(out_txt); out_txt = 0; info("%d:%s -> %d", p->id, info_buf, hr.protocol_reply); nsf_close_client_fds(p); nsf_send_reply(state, p, hr.protocol_reply); goto cleanup; } // if (hr.content_type && hr.content_type[0]) { // generate header char *hdr_t = NULL; size_t hdr_z = 0; FILE *hdr_f = open_memstream(&hdr_t, &hdr_z); fprintf(hdr_f, "Content-Type: %s\n", hr.content_type); fprintf(hdr_f, "Cache-Control: no-cache\n"); fprintf(hdr_f, "Pragma: no-cache\n"); if (hr.client_key) { fprintf(hdr_f, "Set-Cookie: EJSID=%016llx; Path=/\n", hr.client_key); } putc('\n', hdr_f); if (out_size > 0) { fwrite(out_txt, 1, out_size, hdr_f); } fclose(hdr_f); hdr_f = NULL; free(out_txt); out_txt = hdr_t; out_size = hdr_z; } if (!out_txt || !*out_txt) { xfree(out_txt); out_txt = 0; if (hr.allow_empty_output) { info("%d:%s -> OK", p->id, info_buf); nsf_close_client_fds(p); nsf_send_reply(state, p, NEW_SRV_RPL_OK); goto cleanup; } out_f = open_memstream(&out_txt, &out_size); ns_html_err_internal_error(out_f, &hr, 0, "empty output generated"); close_memstream(out_f); out_f = 0; xfree(out_txt); out_txt = 0; } nsf_new_autoclose(state, p, out_txt, out_size); info("%d:%s -> OK, %zu", p->id, info_buf, out_size); nsf_send_reply(state, p, NEW_SRV_RPL_OK); cleanup: if (hr.log_f) fclose(hr.log_f); xfree(hr.log_t); xfree(hr.login); xfree(hr.name); xfree(hr.name_arm); xfree(hr.script_part); xfree(hr.body_attr); }
static void cmd_http_request(struct server_framework_state *state, struct client_state *p, size_t pkt_size, const struct new_server_prot_packet *pkt_gen) { enum { MAX_PARAM_NUM = 10000, MAX_PARAM_SIZE = 128 * 1024 * 1024, }; const struct new_server_prot_http_request *pkt; size_t in_size; const ej_size_t *arg_sizes, *env_sizes, *param_name_sizes, *param_sizes; unsigned long bptr; const unsigned char ** args; const unsigned char ** envs; const unsigned char ** param_names; const unsigned char ** params; size_t *my_param_sizes; int i; char *out_txt = 0; size_t out_size = 0; FILE *out_f = 0; struct http_request_info hr; memset(&hr, 0, sizeof(hr)); hr.id = p->id; hr.client_state = p; hr.fw_state = state; gettimeofday(&hr.timestamp1, 0); if (pkt_size < sizeof(*pkt)) return nsf_err_packet_too_small(state, p, pkt_size, sizeof(*pkt)); pkt = (const struct new_server_prot_http_request *) pkt_gen; if (pkt->arg_num < 0 || pkt->arg_num > MAX_PARAM_NUM) return nsf_err_protocol_error(state, p); if (pkt->env_num < 0 || pkt->env_num > MAX_PARAM_NUM) return nsf_err_protocol_error(state, p); if (pkt->param_num < 0 || pkt->param_num > MAX_PARAM_NUM) return nsf_err_protocol_error(state, p); in_size = sizeof(*pkt); in_size += pkt->arg_num * sizeof(ej_size_t); in_size += pkt->env_num * sizeof(ej_size_t); in_size += pkt->param_num * 2 * sizeof(ej_size_t); if (pkt_size < in_size) return nsf_err_packet_too_small(state, p, pkt_size, in_size); XALLOCAZ(args, pkt->arg_num); XALLOCAZ(envs, pkt->env_num); XALLOCAZ(param_names, pkt->param_num); XALLOCAZ(params, pkt->param_num); XALLOCAZ(my_param_sizes, pkt->param_num); bptr = (unsigned long) pkt; bptr += sizeof(*pkt); arg_sizes = (const ej_size_t *) bptr; bptr += pkt->arg_num * sizeof(ej_size_t); env_sizes = (const ej_size_t *) bptr; bptr += pkt->env_num * sizeof(ej_size_t); param_name_sizes = (const ej_size_t *) bptr; bptr += pkt->param_num * sizeof(ej_size_t); param_sizes = (const ej_size_t *) bptr; bptr += pkt->param_num * sizeof(ej_size_t); for (i = 0; i < pkt->arg_num; i++) { if (arg_sizes[i] > MAX_PARAM_SIZE) return nsf_err_protocol_error(state, p); in_size += arg_sizes[i] + 1; } for (i = 0; i < pkt->env_num; i++) { if (env_sizes[i] > MAX_PARAM_SIZE) return nsf_err_protocol_error(state, p); in_size += env_sizes[i] + 1; } for (i = 0; i < pkt->param_num; i++) { if (param_name_sizes[i] > MAX_PARAM_SIZE) return nsf_err_protocol_error(state, p); if (param_sizes[i] > MAX_PARAM_SIZE) return nsf_err_protocol_error(state, p); in_size += param_name_sizes[i] + 1; in_size += param_sizes[i] + 1; } if (pkt_size != in_size) return nsf_err_bad_packet_length(state, p, pkt_size, in_size); for (i = 0; i < pkt->arg_num; i++) { args[i] = (const unsigned char*) bptr; bptr += arg_sizes[i] + 1; if (strlen(args[i]) != arg_sizes[i]) return nsf_err_protocol_error(state, p); } for (i = 0; i < pkt->env_num; i++) { envs[i] = (const unsigned char*) bptr; bptr += env_sizes[i] + 1; if (strlen(envs[i]) != env_sizes[i]) return nsf_err_protocol_error(state, p); } for (i = 0; i < pkt->param_num; i++) { param_names[i] = (const unsigned char*) bptr; bptr += param_name_sizes[i] + 1; if (strlen(param_names[i]) != param_name_sizes[i]) return nsf_err_protocol_error(state, p); params[i] = (const unsigned char *) bptr; my_param_sizes[i] = param_sizes[i]; bptr += param_sizes[i] + 1; } hr.arg_num = pkt->arg_num; hr.args = args; hr.env_num = pkt->env_num; hr.envs = envs; hr.param_num = pkt->param_num; hr.param_names = param_names; hr.param_sizes = my_param_sizes; hr.params = params; // ok, generate HTML out_f = open_memstream(&out_txt, &out_size); ns_handle_http_request(state, p, out_f, &hr); close_memstream(out_f); out_f = 0; // no reply now if (hr.no_reply) goto cleanup; if (hr.protocol_reply) { xfree(out_txt); out_txt = 0; info("HTTP_REQUEST -> %d", hr.protocol_reply); nsf_close_client_fds(p); nsf_send_reply(state, p, hr.protocol_reply); goto cleanup; } if (!out_txt || !*out_txt) { xfree(out_txt); out_txt = 0; if (hr.allow_empty_output) { info("HTTP_REQUEST -> OK"); nsf_close_client_fds(p); nsf_send_reply(state, p, NEW_SRV_RPL_OK); goto cleanup; } out_f = open_memstream(&out_txt, &out_size); ns_html_err_internal_error(out_f, &hr, 0, "empty output generated"); close_memstream(out_f); out_f = 0; xfree(out_txt); out_txt = 0; } nsf_new_autoclose(state, p, out_txt, out_size); info("HTTP_REQUEST -> OK, %zu", out_size); nsf_send_reply(state, p, NEW_SRV_RPL_OK); cleanup: xfree(hr.login); xfree(hr.name); xfree(hr.name_arm); xfree(hr.script_part); xfree(hr.body_attr); }