File:  [Public] / libwww / Library / src / HTError.c
Revision 2.31: download - view: text, annotated - select for diffs
Wed Nov 8 23:47:43 1995 UTC (28 years, 6 months ago) by frystyk
Branches: MAIN
CVS tags: v4/0pre5, HEAD
Version 4.0pre5

/*								      HTError.c
**	ERROR REPORT MODULE
**
**	(c) COPYRIGHT MIT 1995.
**	Please first read the full copyright statement in the file COPYRIGH.
**
**	This is the implementaion of an error message reporting system that 
**	reports errors occured either in a stream module (structured streams
**	inclusive) or in a protocol module. A list of errors are put into the
**	a list which can be bound to a request object or a stream
**
** History:
**  	05 May 94	Written by Henrik Frystyk, frystyk@w3.org
**	   Nov 95	Made list as basic data structure
*/

/* Library include files */
#include "tcp.h"
#include "HTUtils.h"
#include "HTString.h"
#include "HTTCP.h"
#include "HTList.h"
#include "HTError.h"					 /* Implemented here */

PRIVATE unsigned int HTShowMask = HT_ERR_SHOW_DEFAULT;
PRIVATE char *HTErrorPrefix = NULL;

typedef struct _HTErrorMessage {
    int  	code;           	/* Error number */
    char *	msg;          		/* Short explanation */
    char *	url;			/* Explaning URL */
} HTErrorMessage;

struct _HTError {
    HTErrorElement 	element;        /* Index number into HTError */
    HTSeverity 		severity; 	/* A la VMS */
    BOOL               	ignore;         /* YES if msg should not go to user */
    void *  		par;          	/* Explanation, e.g. filename  */
    int 		length;   	/* For copying by generic routine */
    char *       	where;          /* Which function */
};

/* ------------------------------------------------------------------------- */

/*
** All errors that are not strictly HTTP errors but originates from, e.g., 
** the FTP protocol all have element numbers > HTERR_HTTP_CODES_END, i.e.,
** they should be placed after the blank line
*/
PRIVATE HTErrorMessage HTErrors[HTERR_ELEMENTS] = {
    { 200, "OK", 					"ok.multi" },
    { 201, "Created", 					"created.multi" },
    { 202, "Accepted", 					"accepted.multi" },
    { 203, "Provisional Information", 			"partial.multi" },
    { 204, "No Content",				"no_response.multi" },
    { 301, "Moved Permanently",				"moved.multi" },
    { 302, "Moved Temporarily", 			"moved.multi" },
    { 303, "Method", 					"method.multi" },
    { 304, "Not Modified",       			"not_modified.multi" },
    { 400, "Bad Request", 				"bad_request.multi" },
    { 401, "Unauthorized",				"unauthorized.multi" },
    { 402, "Payment Required", 				"payment.multi" },
    { 403, "Forbidden", 				"forbidden.multi" },
    { 404, "Not Found",		       			"not_found.multi" },
    { 405, "Method Not Allowed",	 		"method.multi" },
    { 406, "None Acceptable",		 		"none.multi" },
    { 407, "Proxy Authentication Required", 		"proxy.multi" },
    { 408, "Request Timeout",		 		"timeout.multi" },
    { 500, "Internal Server Error",			"internal.multi" },
    { 501, "Not Implemented", 				"not_made.multi" },
    { 502, "Bad Gateway", 				"bad_gate.multi" },
    { 503, "Service Unavailable",			"unavailable.multi" },
    { 504, "Gateway Timeout", 				"timeout.multi" },
    { 0,   "-------------------------", "----------------------------------" },
    { 0,   "Can't locate remote host", 			"host.multi" },
    { 0,   "No host name found", 			"host.multi" },
    { 0,   "FTP-server replies", 			"ftp.multi" },
    { 0,   "FTP-server doesn't reply", 			"no_server.multi" },
    { 0,   "Server timed out", 				"time_out.multi" },
    { 0,   "Gopher-server replies", 			"gopher.multi" },
    { 0,   "Data transfer interrupted", 		"interrupt.multi" },
    { 0,   "Connection establishment interrupted", 	"interrupt.multi" },
    { 0,   "CSO-server replies", 			"cso.multi" },
    { 0,   "This is probably a HTTP server 0.9 or less","http_version" },
    { 0,   "Bad, Incomplete, or Unknown Response",	"bad_reply.multi" },
    { 0,   "Unknown access authentication scheme",	"control.multi" },
    { 0,   "News-server replies",			"news.multi" },
    { 0,   "Trying `ftp://' instead of `file://'",	"ftpfile.multi" },
    { 0,   "Too many redirections",			"redirections.multi" },
    { 0,   "Premature End Of File",			"EOF.multi" },
    { 0,   "Response from WAIS Server too Large - Extra lines ignored",
	                                                "wais.multi" },
    { 0,   "WAIS-server doesn't return any data", 	"wais.multi" },
    { 0,   "Can't connect to WAIS-server",		"wais.multi" },
    { 0,   "System replies",				"system.multi" },
    { 0,   "Wrong Protocol Class",			"class.multi" }
};

/* ------------------------------------------------------------------------- */

/*	HTError_add
**	-----------
**	Add an error message to the error list. `par' and `where'
**	might be set to NULL. If par is a string, it is sufficient to let
**	length be unspecified, i.e., 0. If only a part of the string is
**	wanted then specify a length inferior to strlen((char *) par).
**	The string is '\0' terminated automaticly.
**	NOTE: See also HTError_addSystem for system errors
**	Return YES if OK, else NO
*/
PUBLIC BOOL HTError_add (HTList * 	list,
			 HTSeverity	severity,
			 BOOL		ignore,
			 int		element,
			 void *		par,
			 unsigned int	length,
			 char *		where)
{
    HTError *newError;
    if (!list) return NO;
    if ((newError = (HTError *) calloc(1, sizeof(HTError))) == NULL)
	outofmem(__FILE__, "HTError_add");
    newError->element = (HTErrorElement) element;
    newError->severity = severity;
    newError->ignore = ignore;
    if (par) {
	if (!length) length = (int) strlen((char *) par);
	if ((newError->par = malloc(length+1)) == NULL)
	    outofmem(__FILE__, "HTErrorError");
	memcpy(newError->par, par, length);
	*(((char *) newError->par)+length) = '\0';
	newError->length = length;
    }
    newError->where = where;
    if (WWWTRACE) {
	TTYPrint(TDEST, "Error Add... Code: %3d\tMessage: `%s\'\tSeverity: %d\tParameter: `%s\'\tWhere: `%s\'\n",
		HTErrors[newError->element].code,
		HTErrors[newError->element].msg,
		newError->severity,
		newError->par ? (char *) newError->par : "Unspecified",
		newError->where ? newError->where : "Unspecified");
    }
    return HTList_addObject(list, (void *) newError);
}


/*	HTError_addSystem
**	-----------------
**	Add a system error message to the error list. syscall
**	is the name of the system call, e.g. "close". The message put to the
**	list is that corresponds to the error number passed. 
**	Returns YES if OK, else NO
**	See also HTError_add.
*/
PUBLIC BOOL HTError_addSystem (HTList *		list,
			       HTSeverity	severity,
			       int		errornumber,
			       BOOL		ignore,
			       char *		syscall)
{
    BOOL status = NO;
    if (list && syscall) {
	char *errmsg = NULL;
	StrAllocCopy(errmsg, syscall);
	StrAllocCat(errmsg, ": ");
	StrAllocCat(errmsg, HTErrnoString(errornumber));
	status = HTError_add(list, severity, ignore, HTERR_SYSTEM,
			     errmsg, (int) strlen(errmsg), syscall);
	free(errmsg);
    }
    return status;
}

/*	HTError_deleteAll
**	-----------------
**	Remove all errors from the list
*/
PUBLIC BOOL HTError_deleteAll (HTList * list)
{
    if (list) {
	HTList *cur = list;
	HTError *pres;
	while ((pres = (HTError *) HTList_nextObject(cur))) {
	    FREE(pres->par);
	    free(pres);
	}
	HTList_delete(list);
	return YES;
    }
    return NO;
}

/*	HTError_deleteLast
**	------------------
**	Deletes the last error entry added to the list
**	Return YES if OK, else NO
*/
PUBLIC BOOL HTError_deleteLast (HTList * list)
{
    if (list) {
	HTError *old = HTList_removeLastObject(list);
	if (old) {
	    if (WWWTRACE) TTYPrint(TDEST, "Error.Delete %p\n", old);
	    FREE(old->par);
	    free(old);
	    return YES;
	}
    }
    return NO;
}

/*	HTError_ignoreLast
**	------------------
**	Turns on the `ignore' flag for the most recent error entered the
**	error list. Returns YES if OK else NO
*/
PUBLIC BOOL HTError_ignoreLast (HTList * list)
{
    if (list) {
	HTError *last = HTList_lastObject(list);
	if (last) {
	    if (WWWTRACE) TTYPrint(TDEST, "Error.Ignore %p\n", last);
	    last->ignore = YES;
	    return YES;
	}
    }
    return NO;
}

/*	HTError_setIgnore
**	-----------------
*/
PUBLIC BOOL HTError_setIgnore (HTError * info)
{
    if (info) {
	info->ignore = YES;
	return YES;
    }
    return NO;
}

/*
**	Get show preferences
*/
PUBLIC HTErrorShow HTError_show (void)
{
    return HTShowMask;
}

PUBLIC BOOL HTError_setShow (HTErrorShow mask)
{
    HTShowMask = mask;
    return YES;
}

/*
**	Should we show this error entry?
*/
PUBLIC BOOL HTError_doShow (HTError *info)
{
    return (info && ((HTShowMask & info->severity) &&
		     (!info->ignore || HTShowMask & HT_ERR_SHOW_IGNORE)));
}

/*
**	Various Fields in the HTError structure
*/
PUBLIC HTSeverity HTError_severity (HTError *info)
{
    return info ? info->severity : 0;
}

PUBLIC int HTError_code (HTError * info)
{
    return info ? HTErrors[info->element].code : -1;
}

PUBLIC CONST char * HTError_message (HTError * info)
{
    return info ? HTErrors[info->element].msg : NULL;
}

PUBLIC void * HTError_parameter (HTError * info, int * length)
{
    if (info) {
	*length = info->length;
	return info->par;
    }
    return NULL;
}

PUBLIC CONST char * HTError_location (HTError * info)
{
    return info ? info->where : NULL;
}

/*	Error URLs
**	----------
**	Each error message can point to a URL with extended description of
**	what went wrong. This can for example also be used by a server in
**	order to send back a error URL to the client. The file names of the
**	URLs are given in the error message table but the prefix where to find
**	them can be handled with the following functions
*/
PUBLIC void HTError_setPrefix (CONST char * path)
{
    if (path && *path) StrAllocCopy(HTErrorPrefix, path);
}

PUBLIC CONST char *HTError_prefix (void)
{
    return HTErrorPrefix;
}

PUBLIC void HTError_freePrefix (void)
{
    FREE(HTErrorPrefix);
}

Webmaster