/* * Send back a simple error page */ void http_response_send_error(struct http_response *resp, int code, const char *fmt, ...) { struct http_request *const req = resp->msg->conn->req; const char *ua; FILE *fp; int i; /* Check headers already sent */ if (resp->msg->hdrs_sent) return; /* Set response line info */ http_response_set_header(resp, 0, HDR_REPLY_STATUS, "%d", code); http_response_set_header(resp, 0, HDR_REPLY_REASON, "%s", http_response_status_msg(code)); /* Set additional headers */ http_response_set_header(resp, 0, HTTP_HEADER_CONTENT_TYPE, "text/html; charset=iso-8859-1"); /* Close connection for real errors */ if (code >= 400) { http_response_set_header(resp, 0, _http_message_connection_header(resp->msg), "close"); } /* Send error page body */ if ((fp = http_response_get_output(resp, 1)) == NULL) return; fprintf(fp, "<HTML>\n<HEAD>\n<TITLE>%d %s</TITLE></HEAD>\n", code, http_response_status_msg(code)); fprintf(fp, "<BODY BGCOLOR=\"#FFFFFF\">\n<H3>%d %s</H3>\n", code, http_response_status_msg(code)); if (fmt != NULL) { va_list args; fprintf(fp, "<B>"); va_start(args, fmt); vfprintf(fp, fmt, args); va_end(args); fprintf(fp, "</B>\n"); } #if 0 fprintf(fp, "<P></P>\n<HR>\n"); fprintf(fp, "<FONT SIZE=\"-1\"><EM>%s</EM></FONT>\n", serv->server_name); #endif /* Add fillter for IE */ if ((ua = http_request_get_header(req, HTTP_HEADER_USER_AGENT)) != NULL && strstr(ua, "IE") != NULL) { for (i = 0; i < 20; i++) { fprintf(fp, "<!-- FILLER TO MAKE INTERNET EXPLORER SHOW" " THIS PAGE INSTEAD OF ITS OWN PAGE -->\n"); } } fprintf(fp, "</BODY>\n</HTML>\n"); }
/* * Send an HTTP redirect. */ void http_response_send_redirect(struct http_response *resp, const char *url) { const char *name; const char *value; while (_http_head_get_by_index(resp->msg->head, 0, &name, &value) == 0) _http_head_remove(resp->msg->head, name); http_response_set_header(resp, 0, HDR_REPLY_STATUS, "%d", HTTP_STATUS_MOVED_PERMANENTLY); http_response_set_header(resp, 0, HDR_REPLY_REASON, "%s", http_response_status_msg(HTTP_STATUS_MOVED_PERMANENTLY)); http_response_set_header(resp, 0, "Location", "%s", url); }
/* * Send a copy of the message, wait for a reply, and return the reply. * * The "reply" should already be initialized. * * This properly handles the calling thread's being canceled. */ int http_xml_send(struct http_client *client, struct in_addr ip, u_int16_t port, int https, const char *urlpath, const char *username, const char *password, const char *ptag, const char *pattrs, const struct structs_type *ptype, const void *payload, int pflags, const char *rtag, char **rattrsp, const char *rattrs_mtype, const struct structs_type *rtype, void *reply, int rflags, structs_xmllog_t *rlogger) { struct http_client_connection *cc; struct http_request *req; struct http_response *resp; int ret = -1; u_int code; FILE *fp; /* Get HTTP connection */ if ((cc = http_client_connect(client, ip, port, https)) == NULL) { alogf(LOG_ERR, "can't %s for %s:%u: %m", "get HTTP client" _ inet_ntoa(ip) _ port); return -1; } /* Push cleanup hook */ pthread_cleanup_push(http_xml_send_cleanup, cc); /* Set up request */ req = http_client_get_request(cc); if (http_request_set_method(req, payload != NULL ? HTTP_METHOD_POST : HTTP_METHOD_GET) == -1) { alogf(LOG_ERR, "can't %s for %s:%u: %m", "set method" _ inet_ntoa(ip) _ port); goto fail; } if (http_request_set_path(req, urlpath) == -1) { alogf(LOG_ERR, "can't %s for %s:%u: %m", "set path" _ inet_ntoa(ip) _ port); goto fail; } if (http_request_set_header(req, 0, "Content-Type", "text/xml") == -1) { alogf(LOG_ERR, "can't %s for %s:%u: %m", "set content-type" _ inet_ntoa(ip) _ port); goto fail; } if (username != NULL && password != NULL) { char *auth; if ((auth = http_request_encode_basic_auth(TYPED_MEM_TEMP, username, password)) == NULL) { alogf(LOG_ERR, "can't %s for %s:%u: %m", "encode authorization" _ inet_ntoa(ip) _ port); goto fail; } if (http_request_set_header(req, 0, "Authorization", "Basic %s", auth) == -1) { alogf(LOG_ERR, "can't %s for %s:%u: %m", "set authorization header" _ inet_ntoa(ip) _ port); FREE(TYPED_MEM_TEMP, auth); goto fail; } FREE(TYPED_MEM_TEMP, auth); } /* Write XML data to HTTP client output stream */ if (payload != NULL) { if ((fp = http_request_get_output(req, 1)) == NULL) { alogf(LOG_ERR, "can't %s for %s:%u: %m", "get output" _ inet_ntoa(ip) _ port); goto fail; } if (structs_xml_output(ptype, ptag, pattrs, payload, fp, NULL, pflags) == -1) { alogf(LOG_ERR, "can't %s for %s:%u: %m", "write XML" _ inet_ntoa(ip) _ port); goto fail; } } /* Get response */ if ((resp = http_client_get_response(cc)) == NULL) { alogf(LOG_ERR, "can't %s for %s:%u: %m", "get response" _ inet_ntoa(ip) _ port); goto fail; } if ((code = http_response_get_code(resp)) != HTTP_STATUS_OK) { alogf(LOG_ERR, "rec'd HTTP error code %d from" "http%s://%s:%u%s: %s", code _ https ? "s" : "" _ inet_ntoa(ip) _ port _ urlpath _ http_response_status_msg(code)); goto fail; } /* Read XML reply from client input stream */ if ((fp = http_response_get_input(resp)) == NULL) { alogf(LOG_ERR, "can't %s for %s:%u: %m", "get input" _ inet_ntoa(ip) _ port); goto fail; } if (structs_xml_input(rtype, rtag, rattrsp, rattrs_mtype, fp, reply, rflags, rlogger) == -1) { alogf(LOG_ERR, "can't %s for %s:%u: %m", "read XML reply" _ inet_ntoa(ip) _ port); goto fail; } /* OK */ ret = 0; fail:; /* Done */ pthread_cleanup_pop(1); return (ret); }