/* allocates and initializes an error response */ HttpReply * errorBuildReply(ErrorState * err) { HttpReply *rep = httpReplyCreate(); const char *name = errorPageName(err->page_id); /* no LMT for error pages; error pages expire immediately */ if (strchr(name, ':')) { /* Redirection */ httpReplySetHeaders(rep, HTTP_MOVED_TEMPORARILY, NULL, "text/html", 0, -1, -1); if (err->request) { char *quoted_url = rfc1738_escape_part(urlCanonical(err->request)); httpHeaderPutStrf(&rep->header, HDR_LOCATION, name, quoted_url); } httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%d %s", err->http_status, "Access Denied"); } else { MemBuf content = errorBuildContent(err); httpReplySetHeaders(rep, err->http_status, NULL, "text/html", content.size, -1, -1); /* * include some information for downstream caches. Implicit * replaceable content. This isn't quite sufficient. xerrno is not * necessarily meaningful to another system, so we really should * expand it. Additionally, we should identify ourselves. Someone * might want to know. Someone _will_ want to know OTOH, the first * X-CACHE-MISS entry should tell us who. */ httpHeaderPutStrf(&rep->header, HDR_X_SQUID_ERROR, "%s %d", name, err->xerrno); httpBodySet(&rep->body, &content); /* do not memBufClean() the content, it was absorbed by httpBody */ } return rep; }
/* Borrow part of code from libwww2 came with Mosaic distribution */ static void gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) { char *pos = inbuf; char *lpos = NULL; char *tline = NULL; LOCAL_ARRAY(char, line, TEMP_BUF_SIZE); LOCAL_ARRAY(char, tmpbuf, TEMP_BUF_SIZE); String outbuf = StringNull; char *name = NULL; char *selector = NULL; char *host = NULL; char *port = NULL; char *escaped_selector = NULL; const char *icon_url = NULL; char gtype; StoreEntry *entry = NULL; memset(tmpbuf, '\0', TEMP_BUF_SIZE); memset(line, '\0', TEMP_BUF_SIZE); entry = gopherState->entry; if (gopherState->conversion == HTML_INDEX_PAGE) { char *html_url = html_quote(storeUrl(entry)); gopherHTMLHeader(entry, "Gopher Index %s", html_url); storeAppendPrintf(entry, "<p>This is a searchable Gopher index. Use the search\n" "function of your browser to enter search terms.\n" "<ISINDEX>\n"); gopherHTMLFooter(entry); /* now let start sending stuff to client */ storeBufferFlush(entry); gopherState->HTML_header_added = 1; return; } if (gopherState->conversion == HTML_CSO_PAGE) { char *html_url = html_quote(storeUrl(entry)); gopherHTMLHeader(entry, "CSO Search of %s", html_url); storeAppendPrintf(entry, "<P>A CSO database usually contains a phonebook or\n" "directory. Use the search function of your browser to enter\n" "search terms.</P><ISINDEX>\n"); gopherHTMLFooter(entry); /* now let start sending stuff to client */ storeBufferFlush(entry); gopherState->HTML_header_added = 1; return; } inbuf[len] = '\0'; if (!gopherState->HTML_header_added) { if (gopherState->conversion == HTML_CSO_RESULT) gopherHTMLHeader(entry, "CSO Search Result", NULL); else gopherHTMLHeader(entry, "Gopher Menu", NULL); strCat(outbuf, "<PRE>"); gopherState->HTML_header_added = 1; gopherState->HTML_pre = 1; } while ((pos != NULL) && (pos < inbuf + len)) { if (gopherState->len != 0) { /* there is something left from last tx. */ xstrncpy(line, gopherState->buf, gopherState->len + 1); if (gopherState->len + len > TEMP_BUF_SIZE) { debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n", storeUrl(entry)); len = TEMP_BUF_SIZE - gopherState->len; } lpos = (char *) memccpy(line + gopherState->len, inbuf, '\n', len); if (lpos) *lpos = '\0'; else { /* there is no complete line in inbuf */ /* copy it to temp buffer */ if (gopherState->len + len > TEMP_BUF_SIZE) { debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n", storeUrl(entry)); len = TEMP_BUF_SIZE - gopherState->len; } xmemcpy(gopherState->buf + gopherState->len, inbuf, len); gopherState->len += len; return; } /* skip one line */ pos = (char *) memchr(pos, '\n', len); if (pos) pos++; /* we're done with the remain from last tx. */ gopherState->len = 0; *(gopherState->buf) = '\0'; } else { lpos = (char *) memccpy(line, pos, '\n', len - (pos - inbuf)); if (lpos) *lpos = '\0'; else { /* there is no complete line in inbuf */ /* copy it to temp buffer */ if ((len - (pos - inbuf)) > TEMP_BUF_SIZE) { debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n", storeUrl(entry)); len = TEMP_BUF_SIZE; } if (len > (pos - inbuf)) { xmemcpy(gopherState->buf, pos, len - (pos - inbuf)); gopherState->len = len - (pos - inbuf); } break; } /* skip one line */ pos = (char *) memchr(pos, '\n', len); if (pos) pos++; } /* at this point. We should have one line in buffer to process */ if (*line == '.') { /* skip it */ memset(line, '\0', TEMP_BUF_SIZE); continue; } switch (gopherState->conversion) { case HTML_INDEX_RESULT: case HTML_DIR:{ tline = line; gtype = *tline++; name = tline; selector = strchr(tline, TAB); if (selector) { *selector++ = '\0'; host = strchr(selector, TAB); if (host) { *host++ = '\0'; port = strchr(host, TAB); if (port) { char *junk; port[0] = ':'; junk = strchr(host, TAB); if (junk) *junk++ = 0; /* Chop port */ else { junk = strchr(host, '\r'); if (junk) *junk++ = 0; /* Chop port */ else { junk = strchr(host, '\n'); if (junk) *junk++ = 0; /* Chop port */ } } if ((port[1] == '0') && (!port[2])) port[0] = 0; /* 0 means none */ } /* escape a selector here */ escaped_selector = xstrdup(rfc1738_escape_part(selector)); switch (gtype) { case GOPHER_DIRECTORY: icon_url = mimeGetIconURL("internal-menu"); break; case GOPHER_HTML: case GOPHER_FILE: icon_url = mimeGetIconURL("internal-text"); break; case GOPHER_INDEX: case GOPHER_CSO: icon_url = mimeGetIconURL("internal-index"); break; case GOPHER_IMAGE: case GOPHER_GIF: case GOPHER_PLUS_IMAGE: icon_url = mimeGetIconURL("internal-image"); break; case GOPHER_SOUND: case GOPHER_PLUS_SOUND: icon_url = mimeGetIconURL("internal-sound"); break; case GOPHER_PLUS_MOVIE: icon_url = mimeGetIconURL("internal-movie"); break; case GOPHER_TELNET: case GOPHER_3270: icon_url = mimeGetIconURL("internal-telnet"); break; case GOPHER_BIN: case GOPHER_MACBINHEX: case GOPHER_DOSBIN: case GOPHER_UUENCODED: icon_url = mimeGetIconURL("internal-binary"); break; case GOPHER_INFO: icon_url = NULL; break; default: icon_url = mimeGetIconURL("internal-unknown"); break; } memset(tmpbuf, '\0', TEMP_BUF_SIZE); if ((gtype == GOPHER_TELNET) || (gtype == GOPHER_3270)) { if (strlen(escaped_selector) != 0) snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"telnet://%s@%s%s%s/\">%s</A>\n", icon_url, escaped_selector, rfc1738_escape_part(host), *port ? ":" : "", port, html_quote(name)); else snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"telnet://%s%s%s/\">%s</A>\n", icon_url, rfc1738_escape_part(host), *port ? ":" : "", port, html_quote(name)); } else if (gtype == GOPHER_INFO) { snprintf(tmpbuf, TEMP_BUF_SIZE, "\t%s\n", html_quote(name)); } else { if (strncmp(selector, "GET /", 5) == 0) { /* WWW link */ snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"http://%s/%s\">%s</A>\n", icon_url, host, rfc1738_escape_unescaped(selector + 5), html_quote(name)); } else { /* Standard link */ snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG border=\"0\" SRC=\"%s\"> <A HREF=\"gopher://%s/%c%s\">%s</A>\n", icon_url, host, gtype, escaped_selector, html_quote(name)); } } safe_free(escaped_selector); strCat(outbuf, tmpbuf); } else { memset(line, '\0', TEMP_BUF_SIZE); continue; } } else { memset(line, '\0', TEMP_BUF_SIZE); continue; } break; } /* HTML_DIR, HTML_INDEX_RESULT */ case HTML_CSO_RESULT:{ if (line[0] == '-') { int code, recno; char *s_code, *s_recno, *result; s_code = strtok(line + 1, ":\n"); s_recno = strtok(NULL, ":\n"); result = strtok(NULL, "\n"); if (!result) break; code = atoi(s_code); recno = atoi(s_recno); if (code != 200) break; if (gopherState->cso_recno != recno) { snprintf(tmpbuf, TEMP_BUF_SIZE, "</PRE><HR noshade size=\"1px\"><H2>Record# %d<br><i>%s</i></H2>\n<PRE>", recno, html_quote(result)); gopherState->cso_recno = recno; } else { snprintf(tmpbuf, TEMP_BUF_SIZE, "%s\n", html_quote(result)); } strCat(outbuf, tmpbuf); break; } else { int code; char *s_code, *result; s_code = strtok(line, ":"); result = strtok(NULL, "\n"); if (!result) break; code = atoi(s_code); switch (code) { case 200:{ /* OK */ /* Do nothing here */ break; } case 102: /* Number of matches */ case 501: /* No Match */ case 502: /* Too Many Matches */ { /* Print the message the server returns */ snprintf(tmpbuf, TEMP_BUF_SIZE, "</PRE><HR noshade size=\"1px\"><H2>%s</H2>\n<PRE>", html_quote(result)); strCat(outbuf, tmpbuf); break; } } } } /* HTML_CSO_RESULT */ default: break; /* do nothing */ } /* switch */ } /* while loop */ if (strLen(outbuf) > 0) { storeAppend(entry, strBuf(outbuf), strLen(outbuf)); /* now let start sending stuff to client */ storeBufferFlush(entry); } stringClean(&outbuf); return; }
char * internalRedirectProcessURL(clientHttpRequest * req, rewritetoken * head) { char *dev = NULL; size_t len = 0; debug(85, 5) ("internalRedirectProcessURL: start\n"); for (; head != NULL; head = head->next) { const char *str = NULL; /* string to append */ size_t str_len = 0; int do_ulong = 0; unsigned long ulong = 0; const char *ulong_fmt = "%lu"; debug(85, 5) ("internalRedirectProcessURL: token=%s str=%s urlEncode=%s\n", tokenNames[head->type], head->str, head->urlEncode ? "true" : "false"); switch (head->type) { case RFT_STRING: str = head->str; str_len = head->str_len; break; case RFT_CLIENT_IPADDRESS: str = inet_ntoa(req->conn->peer.sin_addr); break; case RFT_LOCAL_IPADDRESS: str = inet_ntoa(req->conn->me.sin_addr); break; case RFT_LOCAL_PORT: ulong = ntohs(req->conn->me.sin_port); do_ulong = 1; break; case RFT_EPOCH_SECONDS: ulong = current_time.tv_sec; do_ulong = 1; break; case RFT_TIME_SUBSECONDS: ulong = current_time.tv_usec / 1000; do_ulong = 1; ulong_fmt = "%03lu"; break; case RFT_USERNAME: if (req->request->auth_user_request) str = authenticateUserUsername(req->request->auth_user_request->auth_user); if (!str || !*str) str = req->conn->rfc931; #ifdef USE_SSL if ((!str || !*str) && req->conn != NULL) str = sslGetUserEmail(fd_table[req->conn->fd].ssl); #endif if (!str || !*str) str = req->request->extacl_user; break; case RFT_USERLOGIN: str = req->request->login; break; case RFT_USERIDENT: str = req->conn->rfc931; break; case RFT_USERSSL: #ifdef USE_SSL if (req->conn != NULL) str = sslGetUserEmail(fd_table[req->conn->fd].ssl); #endif break; case RFT_EXTERNALACL_USER: str = req->request->extacl_user; break; case RFT_METHOD: str = req->request->method->string; break; case RFT_PROTOCOL: str = ProtocolStr[req->request->protocol]; break; case RFT_URL: str = req->uri; break; case RFT_URLPATH: str = req->request->urlpath.buf; break; case RFT_URLHOST: str = req->request->host; break; case RFT_HDRHOST: str = httpHeaderGetStr(&req->request->header, HDR_HOST); break; case RFT_EXTERNALACL_LOGSTR: str = req->request->extacl_log.buf; break; default: assert(0 && "Invalid rewrite token type"); break; } if (do_ulong) { char tmpstr[12]; int nbytes = snprintf(tmpstr, 12, ulong_fmt, ulong); assert(nbytes > 0); dev = xreacat(dev, &len, tmpstr, nbytes); } else { if ((str == NULL) || (*str == '\0')) str = "-"; if (str_len == 0) str_len = strlen(str); if (head->urlEncode) { str = rfc1738_escape_part(str); str_len = strlen(str); } dev = xreacat(dev, &len, str, str_len); } } debug(85, 5) ("internalRedirectProcessURL: done: %s\n", dev); return dev; }
/* Borrow part of code from libwww2 came with Mosaic distribution */ static void gopherToHTML(GopherStateData * gopherState, char *inbuf, int len) { char *pos = inbuf; char *lpos = NULL; char *tline = NULL; LOCAL_ARRAY(char, line, TEMP_BUF_SIZE); LOCAL_ARRAY(char, tmpbuf, TEMP_BUF_SIZE); LOCAL_ARRAY(char, outbuf, TEMP_BUF_SIZE << 4); char *name = NULL; char *selector = NULL; char *host = NULL; char *port = NULL; char *escaped_selector = NULL; const char *icon_url = NULL; char gtype; StoreEntry *entry = NULL; memset(outbuf, '\0', TEMP_BUF_SIZE << 4); memset(tmpbuf, '\0', TEMP_BUF_SIZE); memset(line, '\0', TEMP_BUF_SIZE); entry = gopherState->entry; if (gopherState->conversion == HTML_INDEX_PAGE) { storeAppendPrintf(entry, "<HTML><HEAD><TITLE>Gopher Index %s</TITLE></HEAD>\n" "<BODY><H1>%s<BR>Gopher Search</H1>\n" "<p>This is a searchable Gopher index. Use the search\n" "function of your browser to enter search terms.\n" "<ISINDEX></BODY></HTML>\n", storeUrl(entry), storeUrl(entry)); /* now let start sending stuff to client */ storeBufferFlush(entry); gopherState->data_in = 1; return; } if (gopherState->conversion == HTML_CSO_PAGE) { storeAppendPrintf(entry, "<HTML><HEAD><TITLE>CSO Search of %s</TITLE></HEAD>\n" "<BODY><H1>%s<BR>CSO Search</H1>\n" "<P>A CSO database usually contains a phonebook or\n" "directory. Use the search function of your browser to enter\n" "search terms.</P><ISINDEX></BODY></HTML>\n", storeUrl(entry), storeUrl(entry)); /* now let start sending stuff to client */ storeBufferFlush(entry); gopherState->data_in = 1; return; } inbuf[len] = '\0'; if (!gopherState->HTML_header_added) { if (gopherState->conversion == HTML_CSO_RESULT) strcat(outbuf, "<HTML><HEAD><TITLE>CSO Searchs Result</TITLE></HEAD>\n" "<BODY><H1>CSO Searchs Result</H1>\n<PRE>\n"); else strcat(outbuf, "<HTML><HEAD><TITLE>Gopher Menu</TITLE></HEAD>\n" "<BODY><H1>Gopher Menu</H1>\n<PRE>\n"); gopherState->HTML_header_added = 1; } while ((pos != NULL) && (pos < inbuf + len)) { if (gopherState->len != 0) { /* there is something left from last tx. */ xstrncpy(line, gopherState->buf, gopherState->len); lpos = (char *) memccpy(line + gopherState->len, inbuf, '\n', len); if (lpos) *lpos = '\0'; else { /* there is no complete line in inbuf */ /* copy it to temp buffer */ if (gopherState->len + len > TEMP_BUF_SIZE) { debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n", storeUrl(entry)); len = TEMP_BUF_SIZE - gopherState->len; } xmemcpy(gopherState->buf + gopherState->len, inbuf, len); gopherState->len += len; return; } /* skip one line */ pos = (char *) memchr(pos, '\n', len); if (pos) pos++; /* we're done with the remain from last tx. */ gopherState->len = 0; *(gopherState->buf) = '\0'; } else { lpos = (char *) memccpy(line, pos, '\n', len - (pos - inbuf)); if (lpos) *lpos = '\0'; else { /* there is no complete line in inbuf */ /* copy it to temp buffer */ if ((len - (pos - inbuf)) > TEMP_BUF_SIZE) { debug(10, 1) ("GopherHTML: Buffer overflow. Lost some data on URL: %s\n", storeUrl(entry)); len = TEMP_BUF_SIZE; } if (len > (pos - inbuf)) { xmemcpy(gopherState->buf, pos, len - (pos - inbuf)); gopherState->len = len - (pos - inbuf); } break; } /* skip one line */ pos = (char *) memchr(pos, '\n', len); if (pos) pos++; } /* at this point. We should have one line in buffer to process */ if (*line == '.') { /* skip it */ memset(line, '\0', TEMP_BUF_SIZE); continue; } switch (gopherState->conversion) { case HTML_INDEX_RESULT: case HTML_DIR:{ tline = line; gtype = *tline++; name = tline; selector = strchr(tline, TAB); if (selector) { *selector++ = '\0'; host = strchr(selector, TAB); if (host) { *host++ = '\0'; port = strchr(host, TAB); if (port) { char *junk; port[0] = ':'; junk = strchr(host, TAB); if (junk) *junk++ = 0; /* Chop port */ else { junk = strchr(host, '\r'); if (junk) *junk++ = 0; /* Chop port */ else { junk = strchr(host, '\n'); if (junk) *junk++ = 0; /* Chop port */ } } if ((port[1] == '0') && (!port[2])) port[0] = 0; /* 0 means none */ } /* escape a selector here */ escaped_selector = xstrdup(rfc1738_escape_part(selector)); switch (gtype) { case GOPHER_DIRECTORY: icon_url = mimeGetIconURL("internal-menu"); break; case GOPHER_FILE: icon_url = mimeGetIconURL("internal-text"); break; case GOPHER_INDEX: case GOPHER_CSO: icon_url = mimeGetIconURL("internal-index"); break; case GOPHER_IMAGE: case GOPHER_GIF: case GOPHER_PLUS_IMAGE: icon_url = mimeGetIconURL("internal-image"); break; case GOPHER_SOUND: case GOPHER_PLUS_SOUND: icon_url = mimeGetIconURL("internal-sound"); break; case GOPHER_PLUS_MOVIE: icon_url = mimeGetIconURL("internal-movie"); break; case GOPHER_TELNET: case GOPHER_3270: icon_url = mimeGetIconURL("internal-telnet"); break; case GOPHER_BIN: case GOPHER_MACBINHEX: case GOPHER_DOSBIN: case GOPHER_UUENCODED: icon_url = mimeGetIconURL("internal-binary"); break; default: icon_url = mimeGetIconURL("internal-unknown"); break; } memset(tmpbuf, '\0', TEMP_BUF_SIZE); if ((gtype == GOPHER_TELNET) || (gtype == GOPHER_3270)) { if (strlen(escaped_selector) != 0) snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG BORDER=0 SRC=\"%s\"> <A HREF=\"telnet://%s@%s/\">%s</A>\n", icon_url, escaped_selector, host, name); else snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG BORDER=0 SRC=\"%s\"> <A HREF=\"telnet://%s/\">%s</A>\n", icon_url, host, name); } else { snprintf(tmpbuf, TEMP_BUF_SIZE, "<IMG BORDER=0 SRC=\"%s\"> <A HREF=\"gopher://%s/%c%s\">%s</A>\n", icon_url, host, gtype, escaped_selector, name); } safe_free(escaped_selector); strcat(outbuf, tmpbuf); gopherState->data_in = 1; } else { memset(line, '\0', TEMP_BUF_SIZE); continue; } } else { memset(line, '\0', TEMP_BUF_SIZE); continue; } break; } /* HTML_DIR, HTML_INDEX_RESULT */ case HTML_CSO_RESULT:{ int t; int code; int recno; LOCAL_ARRAY(char, result, MAX_CSO_RESULT); tline = line; if (tline[0] == '-') { t = sscanf(tline, "-%d:%d:%[^\n]", &code, &recno, result); if (t < 3) break; if (code != 200) break; if (gopherState->cso_recno != recno) { snprintf(tmpbuf, TEMP_BUF_SIZE, "</PRE><HR><H2>Record# %d<br><i>%s</i></H2>\n<PRE>", recno, result); gopherState->cso_recno = recno; } else { snprintf(tmpbuf, TEMP_BUF_SIZE, "%s\n", result); } strcat(outbuf, tmpbuf); gopherState->data_in = 1; break; } else { /* handle some error codes */ t = sscanf(tline, "%d:%[^\n]", &code, result); if (t < 2) break; switch (code) { case 200:{ /* OK */ /* Do nothing here */ break; } case 102: /* Number of matches */ case 501: /* No Match */ case 502: /* Too Many Matches */ { /* Print the message the server returns */ snprintf(tmpbuf, TEMP_BUF_SIZE, "</PRE><HR><H2>%s</H2>\n<PRE>", result); strcat(outbuf, tmpbuf); gopherState->data_in = 1; break; } } } } /* HTML_CSO_RESULT */ default: break; /* do nothing */ } /* switch */ } /* while loop */ if ((int) strlen(outbuf) > 0) { storeAppend(entry, outbuf, strlen(outbuf)); /* now let start sending stuff to client */ storeBufferFlush(entry); } return; }