This patch is generated from the xsitescript-20001104 branch of HEAD in squid Thu Sep 11 11:58:08 2003 GMT See http://devel.squid-cache.org/ Index: squid/include/util.h diff -u squid/include/util.h:1.3 squid/include/util.h:1.3.6.1 --- squid/include/util.h:1.3 Mon Oct 23 08:04:18 2000 +++ squid/include/util.h Sun Oct 29 14:59:56 2000 @@ -84,6 +84,9 @@ extern char *rfc1738_escape_part(const char *); extern void rfc1738_unescape(char *); +/* html.c */ +extern char *html_quote(const char *); + #if XMALLOC_STATISTICS extern void malloc_statistics(void (*)(int, int, int, void *), void *); #endif Index: squid/lib/Makefile.in diff -u squid/lib/Makefile.in:1.3 squid/lib/Makefile.in:1.3.6.1 --- squid/lib/Makefile.in:1.3 Mon Oct 23 08:04:19 2000 +++ squid/lib/Makefile.in Sun Oct 29 13:23:33 2000 @@ -39,6 +39,7 @@ Stack.o \ hash.o \ heap.o \ + html.o \ $(LIBOBJS) REGEXOBJS = GNUregex.o DLMALLOCOBJS = dlmalloc.o Index: squid/lib/html.c diff -u /dev/null squid/lib/html.c:1.1.2.4 --- /dev/null Thu Sep 11 04:58:10 2003 +++ squid/lib/html.c Sun Oct 29 14:59:32 2000 @@ -0,0 +1,122 @@ +/* + * $Id: squid-xsitescript-20001104-HEAD,v 1.1 2004/08/17 20:55:13 hno Exp $ + * + * DEBUG: + * AUTHOR: Robert Collins + * + * 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 + * the Regents of the University of California. 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. + * + */ + +#include "config.h" + +#if HAVE_STDIO_H +#include +#endif +#if HAVE_STRING_H +#include +#endif + +#include "util.h" +#include "snprintf.h" + +/* + * HTML defines these characters as special entities that should be quoted. + */ +static struct { + unsigned char code; + char *quote; +} htmlstandardentities[] = +{ + /* NOTE: The quoted form MUST not be larger than 6 character. + * see close to the MemPool commend below + */ + { '<', "<" }, + { '>', ">" }, + { '"', """ }, + { '&', "&" }, + { '\'', "'" }, + { 0, NULL } +}; + +/* + * html_do_quote - Returns a static buffer containing the quoted + * string. + */ +char * +html_quote(const char *string) +{ + static char *buf; + static size_t bufsize = 0; + const char *src; + char *dst; + int i; + + /* XXX This really should be implemented using a MemPool, but + * MemPools are not yet available in lib... + */ + if (buf == NULL || strlen(string) * 6 > bufsize) { + xfree(buf); + bufsize = strlen(string) * 6 + 1; + buf = xcalloc(bufsize, 1); + } + for (src = string, dst = buf; *src; src++) { + char *escape = NULL; + const unsigned char ch = *src; + + /* Walk thru the list of HTML Entities that must be quoted to + * display safely + */ + for (i = 0; htmlstandardentities[i].code; i++) { + if (ch == htmlstandardentities[i].code) { + escape = htmlstandardentities[i].quote; + break; + } + } + /* Encode control chars just to be on the safe side, and make + * sure all 8-bit characters are encoded to protect from buggy + * clients + */ + if ( !escape && (ch <= 0x1F || ch >= 0x7f) && ch != '\n' && ch != '\r' && ch != '\t' ) { + static char dec_encoded[7]; + snprintf(dec_encoded, sizeof dec_encoded, "&#%3d;", (int) ch); + escape = dec_encoded; + } + + if (escape) { + /* Ok, An escaped form was found above. Use it */ + strncpy(dst, escape, 6); + dst += strlen(escape); + } else { + /* Apparently there is no need to escape this character */ + *dst++ = ch; + } + } + /* Nullterminate and return the result */ + *dst = '\0'; + return (buf); +} Index: squid/src/errorpage.c diff -u squid/src/errorpage.c:1.3 squid/src/errorpage.c:1.3.6.2 --- squid/src/errorpage.c:1.3 Mon Oct 23 08:04:21 2000 +++ squid/src/errorpage.c Sun Oct 29 15:01:16 2000 @@ -423,6 +423,7 @@ request_t *r = err->request; static MemBuf mb = MemBufNULL; const char *p = NULL; /* takes priority over mb if set */ + int do_quote = 1; memBufReset(&mb); switch (token) { @@ -524,6 +525,7 @@ memBufPrintf(&mb, "%s", sign_mb.buf); memBufClean(&sign_mb); err->page_id = saved_id; + do_quote = 0; } else { /* wow, somebody put %S into ERR_SIGNATURE, stop recursion */ p = "[%S]"; @@ -561,6 +563,8 @@ p = mb.buf; /* do not use mb after this assignment! */ assert(p); debug(4, 3) ("errorConvert: %%%c --> '%s'\n", token, p); + if (do_quote) + p = html_quote(p); return p; } Index: squid/src/ftp.c diff -u squid/src/ftp.c:1.3 squid/src/ftp.c:1.3.6.1 --- squid/src/ftp.c:1.3 Mon Oct 23 08:04:21 2000 +++ squid/src/ftp.c Sun Oct 29 15:43:21 2000 @@ -354,22 +354,23 @@ wordlist *w; char *dirup; int i, j, k; + char *title; storeBuffer(e); storeAppendPrintf(e, "\n", version_string); storeAppendPrintf(e, "\n", mkrfc1123(squid_curtime)); storeAppendPrintf(e, "\n"); storeAppendPrintf(e, "FTP Directory: %s\n", - ftpState->title_url); + html_quote(ftpState->title_url)); storeAppendPrintf(e, "\n"); if (ftpState->flags.use_base) storeAppendPrintf(e, "\n", - ftpState->base_href); + html_quote(ftpState->base_href)); storeAppendPrintf(e, "\n"); if (ftpState->cwd_message) { storeAppendPrintf(e, "
\n");
 	for (w = ftpState->cwd_message; w; w = w->next)
-	    storeAppendPrintf(e, "%s\n", w->key);
+	    storeAppendPrintf(e, "%s\n", html_quote(w->key));
 	storeAppendPrintf(e, "
\n"); storeAppendPrintf(e, "
\n"); wordlistDestroy(&ftpState->cwd_message); @@ -378,25 +379,26 @@ storeAppendPrintf(e, "FTP Directory: "); /* "ftp://" == 6 characters */ assert(strlen(ftpState->title_url) >= 6); - for (i = 6, j = 0; ftpState->title_url[i]; j = i) { + title = html_quote(ftpState->title_url); + for (i = 6, j = 0; title[i]; j = i) { storeAppendPrintf(e, "title_url[i], "/"); - if (ftpState->title_url[i] == '/') + i += strcspn(&title[i], "/"); + if (title[i] == '/') i++; for (k = 0; k < i; k++) - storeAppendPrintf(e, "%c", ftpState->title_url[k]); + storeAppendPrintf(e, "%c", title[k]); storeAppendPrintf(e, "\">"); for (k = j; k < i - 1; k++) - storeAppendPrintf(e, "%c", ftpState->title_url[k]); + storeAppendPrintf(e, "%c", title[k]); if (ftpState->title_url[k] != '/') - storeAppendPrintf(e, "%c", ftpState->title_url[k++]); + storeAppendPrintf(e, "%c", title[k++]); storeAppendPrintf(e, ""); if (k < i) - storeAppendPrintf(e, "%c", ftpState->title_url[k++]); + storeAppendPrintf(e, "%c", title[k++]); if (i == j) { /* Error guard, or "assert" */ storeAppendPrintf(e, "ERROR: Failed to parse URL: %s\n", - ftpState->title_url); + html_quote(ftpState->title_url)); debug(9, 0) ("Failed to parse URL: %s\n", ftpState->title_url); break; } @@ -648,7 +650,7 @@ return html; } /* Handle builtin */ - if (!strcmp(line, "")) { + if (strcmp(line, "") == 0) { /* {icon} {text} {link} */ snprintf(icon, 2048, "\"%-6s\"", mimeGetIconURL("internal-dirup"), @@ -717,10 +719,13 @@ mimeGetIconURL("internal-link"), "[LINK]"); /* sometimes there is an 'l' flag, but no "->" link */ - if (parts->link) + if (parts->link) { + char *link2 = xstrdup(html_quote(rfc1738_escape(parts->link))); snprintf(link, 2048, " -> %s", - rfc1738_escape(parts->link), - parts->link); + link2, + html_quote(parts->link)); + safe_free(link2); + } break; case '\0': snprintf(icon, 2048, "\"%-6s\"", @@ -728,7 +733,7 @@ "[UNKNOWN]"); snprintf(chdir, 2048, " ", - rfc1738_escape(parts->name), + rfc1738_escape_part(parts->name), mimeGetIconURL("internal-dir")); break; case '-': @@ -755,13 +760,13 @@ if (parts->type != '\0') { snprintf(html, 8192, "%s %s%s " "%s%8s%s%s%s%s\n", - href, icon, href, text, dots_fill(strlen(text)), + href, icon, href, html_quote(text), dots_fill(strlen(text)), parts->date, size, chdir, view, download, link); } else { /* Plain listing. {icon} {text} ... {chdir}{view}{download} */ snprintf(html, 8192, "%s %s%s " "%s%s%s%s\n", - href, icon, href, text, dots_fill(strlen(text)), + href, icon, href, html_quote(text), dots_fill(strlen(text)), chdir, view, download, link); } ftpListPartsFree(&parts); Index: squid/src/gopher.c diff -u squid/src/gopher.c:1.3 squid/src/gopher.c:1.3.6.1 --- squid/src/gopher.c:1.3 Mon Oct 23 08:04:21 2000 +++ squid/src/gopher.c Sun Oct 29 16:01:49 2000 @@ -469,19 +469,20 @@ break; } - memset(tmpbuf, '\0', TEMP_BUF_SIZE); if ((gtype == GOPHER_TELNET) || (gtype == GOPHER_3270)) { if (strlen(escaped_selector) != 0) - snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n", - icon_url, escaped_selector, host, name); + snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n", + icon_url, escaped_selector, rfc1738_escape_part(host), + *port ? ":" : "", port, html_quote(name)); else - snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n", - icon_url, host, name); + snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n", + icon_url, rfc1738_escape_part(host), *port ? ":" : "", + port, html_quote(name)); } else { snprintf(tmpbuf, TEMP_BUF_SIZE, " %s\n", - icon_url, host, gtype, escaped_selector, name); + icon_url, host, gtype, escaped_selector, html_quote(name)); } safe_free(escaped_selector); strcat(outbuf, tmpbuf); @@ -515,10 +516,10 @@ break; if (gopherState->cso_recno != recno) { - snprintf(tmpbuf, TEMP_BUF_SIZE, "

Record# %d
%s

\n
", recno, result);
+			snprintf(tmpbuf, TEMP_BUF_SIZE, "

Record# %d
%s

\n
", recno, html_quote(result));
 			gopherState->cso_recno = recno;
 		    } else {
-			snprintf(tmpbuf, TEMP_BUF_SIZE, "%s\n", result);
+			snprintf(tmpbuf, TEMP_BUF_SIZE, "%s\n", html_quote(result));
 		    }
 		    strcat(outbuf, tmpbuf);
 		    gopherState->data_in = 1;
@@ -543,7 +544,7 @@
 		    case 502:	/* Too Many Matches */
 			{
 			    /* Print the message the server returns */
-			    snprintf(tmpbuf, TEMP_BUF_SIZE, "

%s

\n
", result);
+			    snprintf(tmpbuf, TEMP_BUF_SIZE, "

%s

\n
", html_quote(result));
 			    strcat(outbuf, tmpbuf);
 			    gopherState->data_in = 1;
 			    break;
squid-xsitescript-20001104-HEAD.new squid-xsitescript-20001104-HEAD differ: char 80, line 2