# Steve Young's code to implement file based HTML error messages,
rather than the hard coded string.
This commit is contained in:
parent
d28d9fb195
commit
a830af5097
242
src/htmlerror.c
Normal file
242
src/htmlerror.c
Normal file
@ -0,0 +1,242 @@
|
||||
/* $Id: htmlerror.c,v 1.1 2003-03-13 21:25:06 rjkaes Exp $
|
||||
*
|
||||
* This file contains source code for the handling and display of
|
||||
* HTML error pages with variable substitution.
|
||||
*/
|
||||
#include "tinyproxy.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "buffer.h"
|
||||
#include "conns.h"
|
||||
#include "heap.h"
|
||||
#include "htmlerror.h"
|
||||
#include "network.h"
|
||||
#include "utils.h"
|
||||
|
||||
/* Add an error number -> filename mapping to the errorpages list. */
|
||||
int add_new_errorpage(char *filepath, unsigned int errornum) {
|
||||
static int errorpage_count = 1;
|
||||
|
||||
/* First, add space for another pointer to the errorpages array. */
|
||||
config.errorpages = saferealloc(config.errorpages, sizeof(struct error_pages_s *) * (errorpage_count + 1));
|
||||
if(!config.errorpages)
|
||||
return(-1);
|
||||
|
||||
/* Allocate space for an actual structure */
|
||||
config.errorpages[errorpage_count - 1] = safemalloc(sizeof(struct error_pages_s));
|
||||
if(!config.errorpages[errorpage_count - 1])
|
||||
return(-1);
|
||||
|
||||
/* Set values for errorpage structure. */
|
||||
config.errorpages[errorpage_count - 1]->errorpage_path = safestrdup(filepath);
|
||||
if(!config.errorpages[errorpage_count - 1]->errorpage_path)
|
||||
return(-1);
|
||||
|
||||
config.errorpages[errorpage_count - 1]->errorpage_errnum = errornum;
|
||||
|
||||
/* Set NULL to denote end of array */
|
||||
config.errorpages[errorpage_count] = NULL;
|
||||
|
||||
errorpage_count++;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Get the file appropriate for a given error. */
|
||||
char *get_html_file(int errornum) {
|
||||
int i;
|
||||
|
||||
if(!config.errorpages) return(config.errorpage_undef);
|
||||
|
||||
for(i = 0; config.errorpages[i]; i++) {
|
||||
if(config.errorpages[i]->errorpage_errnum == errornum)
|
||||
return(config.errorpages[i]->errorpage_path);
|
||||
}
|
||||
|
||||
return(config.errorpage_undef);
|
||||
}
|
||||
|
||||
/* Look up the value for a variable. */
|
||||
char *lookup_variable(struct conn_s *connptr, char *varname) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i<connptr->error_variable_count; i++) {
|
||||
if(!strcasecmp(connptr->error_variables[i]->error_key, varname))
|
||||
return(connptr->error_variables[i]->error_val);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#define HTML_BUFSIZE 4096
|
||||
|
||||
/* Send an already-opened file to the client with
|
||||
* variable substitution. */
|
||||
int send_html_file(FILE *infile, struct conn_s *connptr) {
|
||||
char inbuf[HTML_BUFSIZE], *varstart = NULL, *p;
|
||||
char *varval;
|
||||
int in_variable = 0, writeret;
|
||||
|
||||
while(fgets(inbuf, HTML_BUFSIZE, infile) != NULL) {
|
||||
for(p = inbuf; *p; p++) {
|
||||
switch(*p) {
|
||||
case '}':
|
||||
if(in_variable) {
|
||||
*p = '\0';
|
||||
if(!(varval = lookup_variable(connptr, varstart)))
|
||||
varval = "(unknown)";
|
||||
writeret = write_message(connptr->client_fd, "%s",
|
||||
varval);
|
||||
if(writeret) return(writeret);
|
||||
in_variable = 0;
|
||||
break;
|
||||
}
|
||||
/* If we are not in a variable, then
|
||||
* we fallthrough. the code for { will
|
||||
* not do anything if in_variable is set to
|
||||
* 0. it will end up in the default
|
||||
* handler which will send the }.
|
||||
*/
|
||||
case '{':
|
||||
/* a {{ will print a single {. If we are NOT
|
||||
* already in a { variable, then proceed with
|
||||
* setup. If we ARE already in a { variable,
|
||||
* this code will fallthrough to the code that
|
||||
* just dumps a character to the client fd.
|
||||
*/
|
||||
if(!in_variable) {
|
||||
varstart = p+1;
|
||||
in_variable++;
|
||||
}
|
||||
default:
|
||||
if(!in_variable) {
|
||||
writeret = write_message(connptr->client_fd, "%c",
|
||||
*p);
|
||||
if(writeret) return(writeret);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
in_variable = 0;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int send_http_headers(struct conn_s *connptr, int code, char *message) {
|
||||
char *headers = \
|
||||
"HTTP/1.0 %d %s\r\n" \
|
||||
"Server: %s/%s\r\n" \
|
||||
"Content-Type: text/html\r\n" \
|
||||
"Connection: close\r\n" \
|
||||
"\r\n";
|
||||
|
||||
return(write_message(connptr->client_fd, headers,
|
||||
code, message,
|
||||
PACKAGE, VERSION));
|
||||
}
|
||||
|
||||
/*
|
||||
* Display an error to the client.
|
||||
*/
|
||||
int
|
||||
send_http_error_message(struct conn_s *connptr)
|
||||
{
|
||||
char *error_file;
|
||||
FILE *infile;
|
||||
int ret;
|
||||
char *fallback_error = \
|
||||
"<html><head><title>%s</title></head>" \
|
||||
"<body><blockquote><i>%s %s</i><br>" \
|
||||
"The page you requested was unavailable. The error code is listed " \
|
||||
"below. In addition, the HTML file which has been configured as the " \
|
||||
"page to be displayed when an error of this type was unavailable, " \
|
||||
"with the error code %d (%s). Please contact your administrator." \
|
||||
"<center>%s</center>" \
|
||||
"</body></html>" \
|
||||
"\r\n";
|
||||
|
||||
send_http_headers(connptr, connptr->error_number, connptr->error_string);
|
||||
|
||||
error_file = get_html_file(connptr->error_number);
|
||||
if(!(infile = fopen(error_file, "r")))
|
||||
return(write_message(connptr->client_fd, fallback_error,
|
||||
connptr->error_string,
|
||||
PACKAGE, VERSION,
|
||||
errno, strerror(errno),
|
||||
connptr->error_string));
|
||||
|
||||
ret = send_html_file(infile, connptr);
|
||||
fclose(infile);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a key -> value mapping for HTML file substitution.
|
||||
*/
|
||||
int
|
||||
add_error_variable(struct conn_s *connptr, char *key, char *val)
|
||||
{
|
||||
connptr->error_variable_count++;
|
||||
|
||||
/* Add space for a new pointer to the error_variables structure. */
|
||||
connptr->error_variables = saferealloc(connptr->error_variables, sizeof(struct error_variable_s *) * connptr->error_variable_count);
|
||||
if(!connptr->error_variables)
|
||||
return(-1);
|
||||
|
||||
/* Allocate a new variable mapping structure. */
|
||||
connptr->error_variables[connptr->error_variable_count - 1] = safemalloc(sizeof(struct error_variable_s));
|
||||
if(!connptr->error_variables[connptr->error_variable_count - 1])
|
||||
return(-1);
|
||||
|
||||
/* Set values for variable mapping. */
|
||||
connptr->error_variables[connptr->error_variable_count - 1]->error_key = safestrdup(key);
|
||||
connptr->error_variables[connptr->error_variable_count - 1]->error_val = safestrdup(val);
|
||||
if((!connptr->error_variables[connptr->error_variable_count - 1]->error_key)
|
||||
|| (!connptr->error_variables[connptr->error_variable_count - 1]->error_val))
|
||||
return(-1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#define ADD_VAR_RET(x, y) if(y) { if(add_error_variable(connptr, x, y) == -1) return(-1); }
|
||||
|
||||
/* Set some standard variables used by all HTML pages */
|
||||
int add_standard_vars(struct conn_s *connptr) {
|
||||
char timebuf[30];
|
||||
time_t global_time = time(NULL);
|
||||
|
||||
strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT",
|
||||
gmtime(&global_time));
|
||||
|
||||
ADD_VAR_RET("request", connptr->request_line);
|
||||
ADD_VAR_RET("cause", connptr->error_string);
|
||||
ADD_VAR_RET("clientip", connptr->client_ip_addr);
|
||||
ADD_VAR_RET("clienthost", connptr->client_string_addr);
|
||||
ADD_VAR_RET("version", VERSION);
|
||||
ADD_VAR_RET("package", PACKAGE);
|
||||
ADD_VAR_RET("date", timebuf);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the error information to the conn structure.
|
||||
*/
|
||||
int
|
||||
indicate_http_error(struct conn_s* connptr, int number, char *message, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char *key, *val;
|
||||
|
||||
va_start(ap, message);
|
||||
|
||||
while((key = va_arg(ap, char *))) {
|
||||
val = va_arg(ap, char *);
|
||||
if(add_error_variable(connptr, key, val) == -1)
|
||||
return(-1);
|
||||
}
|
||||
|
||||
connptr->error_number = number;
|
||||
connptr->error_string = safestrdup(message);
|
||||
|
||||
return(add_standard_vars(connptr));
|
||||
}
|
||||
|
20
src/htmlerror.h
Normal file
20
src/htmlerror.h
Normal file
@ -0,0 +1,20 @@
|
||||
/* $Id: htmlerror.h,v 1.1 2003-03-13 21:25:04 rjkaes Exp $
|
||||
*
|
||||
* Contains header declarations for the HTML error functions in htmlerror.c
|
||||
*/
|
||||
|
||||
#ifndef TINYPROXY_HTMLERROR_H
|
||||
#define TINYPROXY_HTMLERROR_H
|
||||
|
||||
/* Forward declaration */
|
||||
struct conn_s;
|
||||
|
||||
extern int add_new_errorpage(char *filepath, unsigned int errornum);
|
||||
extern int send_http_error_message(struct conn_s *connptr);
|
||||
extern int indicate_http_error(struct conn_s *connptr, int number, char *message, ...);
|
||||
extern int add_error_variable(struct conn_s *connptr, char *key, char *val);
|
||||
extern int send_html_file(FILE *infile, struct conn_s *connptr);
|
||||
extern int send_http_headers(struct conn_s *connptr, int code, char *message);
|
||||
extern int add_standard_vars(struct conn_s *connptr);
|
||||
|
||||
#endif /* !TINYPROXY_HTMLERROR_H */
|
Loading…
Reference in New Issue
Block a user