📄 errorpage.c
字号:
/* * $Id: errorpage.c,v 1.148.2.2 1999/06/19 16:16:06 wessels Exp $ * * DEBUG: section 4 Error Generation * AUTHOR: Duane Wessels * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from the * Internet community. Development is led by Duane Wessels of the * National Laboratory for Applied Network Research and funded by the * National Science Foundation. Squid is Copyrighted (C) 1998 by * Duane Wessels and the University of California San Diego. Please * see the COPYRIGHT file for full details. Squid incorporates * software developed and/or copyrighted by other sources. Please see * the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * *//* * Abstract: These routines are used to generate error messages to be * sent to clients. The error type is used to select between * the various message formats. (formats are stored in the * Config.errorDirectory) */#include "squid.h"/* local types */typedef struct { int id; char *page_name;} ErrorDynamicPageInfo;/* local constant and vars */static const char *const proxy_auth_challenge_fmt = "Basic realm=\"%s\"";/* * note: hard coded error messages are not appended with %S automagically * to give you more control on the format */static const struct { int type; /* and page_id */ const char *text;} error_hard_text[] = { { ERR_SQUID_SIGNATURE, "\n<br clear=\"all\">\n" "<hr noshade size=1>\n" "Generated %T by %h (<a href=\"http://squid.nlanr.net/Squid/\">%s</a>)\n" "</BODY></HTML>\n" }};static Stack ErrorDynamicPages;/* local prototypes */static const int error_hard_text_count = sizeof(error_hard_text) / sizeof(*error_hard_text);static char **error_text = NULL;static int error_page_count = 0;static char *errorTryLoadText(const char *page_name, const char *dir);static char *errorLoadText(const char *page_name);static const char *errorFindHardText(err_type type);static ErrorDynamicPageInfo *errorDynamicPageInfoCreate(int id, const char *page_name);static void errorDynamicPageInfoDestroy(ErrorDynamicPageInfo * info);static MemBuf errorBuildContent(ErrorState * err);static const char *errorConvert(char token, ErrorState * err);static CWCB errorSendComplete;/* * Function: errorInitialize * * Abstract: This function finds the error messages formats, and stores * them in error_text[]; * * Global effects: * error_text[] - is modified */voiderrorInitialize(void){ err_type i; const char *text; error_page_count = ERR_MAX + ErrorDynamicPages.count; error_text = xcalloc(error_page_count, sizeof(char *)); for (i = ERR_NONE, i++; i < error_page_count; i++) { safe_free(error_text[i]); /* hard-coded ? */ if ((text = errorFindHardText(i))) error_text[i] = xstrdup(text); else if (i < ERR_MAX) { /* precompiled ? */ error_text[i] = errorLoadText(err_type_str[i]); } else { /* dynamic */ ErrorDynamicPageInfo *info = ErrorDynamicPages.items[i - ERR_MAX]; assert(info && info->id == i && info->page_name); error_text[i] = errorLoadText(info->page_name); } assert(error_text[i]); }}voiderrorClean(void){ if (error_text) { int i; for (i = ERR_NONE + 1; i < error_page_count; i++) safe_free(error_text[i]); safe_free(error_text); } while (ErrorDynamicPages.count) errorDynamicPageInfoDestroy(stackPop(&ErrorDynamicPages)); error_page_count = 0;}static const char *errorFindHardText(err_type type){ int i; for (i = 0; i < error_hard_text_count; i++) if (error_hard_text[i].type == type) return error_hard_text[i].text; return NULL;}static char *errorLoadText(const char *page_name){ /* test configured location */ char *text = errorTryLoadText(page_name, Config.errorDirectory); /* test default location if failed */ if (!text && strcmp(Config.errorDirectory, DEFAULT_SQUID_ERROR_DIR)) text = errorTryLoadText(page_name, DEFAULT_SQUID_ERROR_DIR); /* giving up if failed */ if (!text) fatal("failed to find or read error text file."); return text;}static char *errorTryLoadText(const char *page_name, const char *dir){ int fd; char path[MAXPATHLEN]; struct stat sb; char *text; snprintf(path, sizeof(path), "%s/%s", dir, page_name); fd = file_open(path, O_RDONLY, NULL, NULL, NULL); if (fd < 0 || fstat(fd, &sb) < 0) { debug(4, 0) ("errorTryLoadText: '%s': %s\n", path, xstrerror()); if (fd >= 0) file_close(fd); return NULL; } text = xcalloc(sb.st_size + 2 + 1, 1); /* 2 == space for %S */ if (read(fd, text, sb.st_size) != sb.st_size) { debug(4, 0) ("errorTryLoadText: failed to fully read: '%s': %s\n", path, xstrerror()); xfree(text); text = NULL; } file_close(fd); if (strstr(text, "%s") == NULL) strcat(text, "%S"); /* add signature */ return text;}static ErrorDynamicPageInfo *errorDynamicPageInfoCreate(int id, const char *page_name){ ErrorDynamicPageInfo *info = xcalloc(1, sizeof(ErrorDynamicPageInfo)); info->id = id; info->page_name = xstrdup(page_name); return info;}static voiderrorDynamicPageInfoDestroy(ErrorDynamicPageInfo * info){ assert(info); xfree(info->page_name); xfree(info);}interrorReservePageId(const char *page_name){ ErrorDynamicPageInfo *info = errorDynamicPageInfoCreate(ERR_MAX + ErrorDynamicPages.count, page_name); stackPush(&ErrorDynamicPages, info); return info->id;}static const char *errorPageName(int pageId){ if (pageId >= ERR_NONE && pageId < ERR_MAX) /* common case */ return err_type_str[pageId]; if (pageId >= ERR_MAX && pageId - ERR_MAX < ErrorDynamicPages.count) return ((ErrorDynamicPageInfo *) ErrorDynamicPages. items[pageId - ERR_MAX])->page_name; return "ERR_UNKNOWN"; /* should not happen */}/* * Function: errorCon * * Abstract: This function creates a ErrorState object. */ErrorState *errorCon(err_type type, http_status status){ ErrorState *err = memAllocate(MEM_ERRORSTATE); err->page_id = type; /* has to be reset manually if needed */ err->type = type; err->http_status = status; return err;}/* * Function: errorAppendEntry * * Arguments: err - This object is destroyed after use in this function. * * Abstract: This function generates a error page from the info contained * by 'err' and then stores the text in the specified store * entry. This function should only be called by ``server * side routines'' which need to communicate errors to the * client side. It should also be called from client_side.c * because we now support persistent connections, and * cannot assume that we can immediately write to the socket * for an error. */voiderrorAppendEntry(StoreEntry * entry, ErrorState * err){ HttpReply *rep; MemObject *mem = entry->mem_obj; assert(mem != NULL); assert(mem->inmem_hi == 0); if (entry->store_status != STORE_PENDING) { /* * If the entry is not STORE_PENDING, then no clients * care about it, and we don't need to generate an * error message */ assert(EBIT_TEST(entry->flags, ENTRY_ABORTED)); assert(mem->nclients == 0); errorStateFree(err); return; } storeLockObject(entry); storeBuffer(entry); rep = errorBuildReply(err); /* Add authentication header */ switch (err->http_status) { case HTTP_PROXY_AUTHENTICATION_REQUIRED: /* Proxy authorisation needed */ httpHeaderPutStrf(&rep->header, HDR_PROXY_AUTHENTICATE, proxy_auth_challenge_fmt, Config.proxyAuthRealm); break; case HTTP_UNAUTHORIZED: /* WWW Authorisation needed */ httpHeaderPutStrf(&rep->header, HDR_WWW_AUTHENTICATE, proxy_auth_challenge_fmt, Config.proxyAuthRealm); break; default: /* Keep GCC happy */ break; } httpReplySwapOut(rep, entry); httpReplyDestroy(rep); mem->reply->sline.status = err->http_status; mem->reply->content_length = -1; EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT); storeBufferFlush(entry); storeComplete(entry);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -