diff -urN squid-1.1.17/src/Makefile.in squid/src/Makefile.in
--- squid-1.1.17/src/Makefile.in Sat Aug 9 00:00:00 1997
+++ squid/src/Makefile.in Tue Jun 2 15:42:52 1998
@@ -17,11 +17,14 @@
USE_SPLAY_TREE = # -DUSE_SPLAY_TREE
USE_BIN_TREE = # -DUSE_BIN_TREE
RELOAD_INTO_IMS = # -DRELOAD_INTO_IMS
+# SmartFilter Define
+LOCAL_OPTS = -DSMARTFILTER
DEFINES = $(HOST_OPT) $(AUTH_OPT) $(LOG_HDRS_OPT) \
$(ICMP_OPT) $(DELAY_HACK) $(USERAGENT_OPT) \
$(KILL_PARENT_OPT) $(USE_POLL_OPT) \
$(USE_SPLAY_TREE) $(USE_BIN_TREE) \
+ $(LOCAL_OPTS) \
$(RELOAD_INTO_IMS)
prefix = @prefix@
@@ -67,7 +70,7 @@
INCLUDE = -I. -I../include -I$(srcdir)/../include
CFLAGS = $(AC_CFLAGS) $(INCLUDE) $(DEFINES)
-SQUID_LIBS = -L../lib $(CRYPTLIB) $(REGEXLIB) -lmiscutil $(XTRA_LIBS)
+SQUID_LIBS = -L../lib $(CRYPTLIB) $(REGEXLIB) -lmiscutil -lwebtrack $(XTRA_LIBS)
CLIENT_LIBS = -L../lib -lmiscutil $(XTRA_LIBS)
DNSSERVER_LIBS = -L../lib -lmiscutil $(XTRA_LIBS)
FTPGET_LIBS = -L../lib -lmiscutil $(XTRA_LIBS)
@@ -122,6 +125,7 @@
url.o \
useragent.o \
wais.o \
+ smartfilter_squid.o \
$(XTRA_OBJS)
DEFAULTS = \
@@ -253,6 +257,9 @@
echo "$(INSTALL_FILE) squid.conf $(sysconfdir)"; \
$(INSTALL_FILE) squid.conf $(sysconfdir); \
fi
+ $(INSTALL_FILE) smartfilter.conf $(sysconfdir)
+ $(INSTALL_FILE) smartfilter.site $(sysconfdir)
+ $(INSTALL_FILE) custom_error.html $(sysconfdir)
install-pinger:
@f=pinger; \
diff -urN squid-1.1.17/src/a squid/src/a
--- squid-1.1.17/src/a Thu Jan 1 08:00:00 1970
+++ squid/src/a Wed Jun 3 14:02:01 1998
@@ -0,0 +1,27 @@
+WT_CAT_SEX,sx
+WT_CAT_DRUGS,dr
+WT_CAT_HATESPEECH,hs
+WT_CAT_CRIME,cs
+WT_CAT_WORTHLESS,os
+WT_CAT_SALES,gb
+WT_CAT_GAMBLING,pp
+WT_CAT_PERSONAL,js
+WT_CAT_JOBS,sp
+WT_CAT_SPORTS,gm
+WT_CAT_GAMES,hm
+WT_CAT_HUMOR,aj
+WT_CAT_ALTJRNL,et
+WT_CAT_ENTERTAIN,ls
+WT_CAT_LIFESTYLE,ex
+WT_CAT_EXTREME,wt
+WT_CAT_CHAT,ch
+WT_CAT_INVESTMENTS,in
+WT_CAT_GNEWS,nw
+WT_CAT_OPINION,po
+WT_CAT_DATING,mm
+WT_CAT_ART,ac
+WT_CAT_CULT,na
+WT_CAT_NEWSSITE,oc
+WT_CAT_SELFHELP,sh
+WT_CAT_TRAVEL,tr
+WT_CAT_NONESSENTIAL,ne
diff -urN squid-1.1.17/src/cache_cf.c squid/src/cache_cf.c
--- squid-1.1.17/src/cache_cf.c Fri Aug 22 03:17:00 1997
+++ squid/src/cache_cf.c Tue Jun 2 17:28:53 1998
@@ -208,6 +208,10 @@
#define DefaultOptionsEnablePurge 0 /* default off */
#define DefaultOptionsClientDb 1 /* default on */
#define DefaultOptionsQueryIcmp 0 /* default off */
+#ifdef SMARTFILTER
+#define DefaultSmartFilterState 0 /* default off */
+#define DefaultSmartFilterConf "/etc/smartfilter.conf"
+#endif
int httpd_accel_mode = 0; /* for fast access */
@@ -864,6 +868,7 @@
GetInteger(i);
if (i < 0)
i = 0;
+
Config.Port.http = (u_short) i;
}
@@ -878,6 +883,32 @@
Config.Port.icp = (u_short) i;
}
+#ifdef SMARTFILTER
+static void
+parseSmartFilterStateLine(int *iptr) /* state is either off or on */
+{
+ char *token;
+ token = strtok(NULL, w_space);
+ if (token == NULL)
+ self_destruct();
+ if (!strcasecmp(token, "on"))
+ *iptr = 1;
+ else
+ *iptr = 0;
+}
+
+static void
+parseSmartFilterConfLine(void)
+{
+ char *token;
+ token = strtok(NULL, w_space);
+ if (token == NULL)
+ self_destruct();
+ safe_free(Config.SmartFilterConf);
+ Config.SmartFilterConf = xstrdup(token);
+}
+#endif
+
static void
parseVisibleHostnameLine(void)
{
@@ -1298,6 +1329,13 @@
else if (!strcmp(token, "outbound_address"))
parseAddressLine(&Config.Addrs.tcp_outgoing);
+#ifdef SMARTFILTER
+ else if (!strcmp(token, "smartfilter_state"))
+ parseSmartFilterStateLine(&Config.SmartFilterState);
+
+ else if (!strcmp(token, "smartfilter_config"))
+ parseSmartFilterConfLine();
+#endif
else if (!strcmp(token, "http_port") || !strcmp(token, "ascii_port"))
parseHttpPortLine();
@@ -1616,6 +1654,10 @@
#ifdef RELOAD_INTO_IMS
Config.Options.reload_into_ims = 0;
#endif /* RELOAD_INTO_IMS */
+#ifdef SMARTFILTER
+ Config.SmartFilterState = DefaultSmartFilterState;
+ Config.SmartFilterConf = safe_xstrdup(DefaultSmartFilterConf);
+#endif
}
static void
diff -urN squid-1.1.17/src/cache_cf.h squid/src/cache_cf.h
--- squid-1.1.17/src/cache_cf.h Fri Aug 8 00:00:00 1997
+++ squid/src/cache_cf.h Tue Jun 2 15:42:52 1998
@@ -161,6 +161,10 @@
int lifetimeShutdown;
int connectTimeout;
int cleanRate;
+#ifdef SMARTFILTER
+ int SmartFilterState;
+ char *SmartFilterConf;
+#endif
int maxRequestSize;
struct {
u_short http;
diff -urN squid-1.1.17/src/client_db.c squid/src/client_db.c
--- squid-1.1.17/src/client_db.c Wed Mar 26 00:00:00 1997
+++ squid/src/client_db.c Fri Jun 5 09:58:19 1998
@@ -31,14 +31,20 @@
#include "squid.h"
+struct _client_stats {
+ int result_hist[ERR_MAX];
+ int n_requests;
+ unsigned long v_requests;
+ unsigned long v_hist[ERR_MAX];
+};
+
typedef struct _client_info {
char *key;
struct client_info *next;
struct in_addr addr;
- struct {
- int result_hist[ERR_MAX];
- int n_requests;
- } Http, Icp;
+ struct _client_stats Http, Icp, HttpTotal, IcpTotal;
+ WT_TYPES WTcats;
+ char *login_name;
} ClientInfo;
int client_info_sz;
@@ -54,6 +60,9 @@
c = xcalloc(1, sizeof(ClientInfo));
c->key = xstrdup(inet_ntoa(addr));
c->addr = addr;
+ c->WTcats = WT_NULLPARM;
+ c->login_name = NULL;
+
hash_join(client_table, (hash_link *) c);
meta_data.client_info++;
return c;
@@ -92,6 +101,83 @@
}
}
+void
+clientdbUpdateVol(struct in_addr addr, log_type log_type, u_short port, long bytes)
+{
+ char *key;
+ ClientInfo *c;
+
+ if (!Config.Options.client_db)
+ return;
+ key=inet_ntoa(addr);
+ c=(ClientInfo *) hash_lookup(client_table,key);
+ if (c==NULL) c=clientdbAdd(addr);
+ if (c==NULL) debug_trap("clientdbUpdateVol: Failed to add entry");
+ if (port==Config.Port.http)
+ { c->Http.v_requests+=bytes;
+ c->Http.v_hist[log_type]+=bytes;
+ }
+ else if (port==Config.Port.icp)
+ { c->Icp.v_requests+=bytes;
+ c->Icp.v_hist[log_type]+=bytes;
+ }
+}
+
+WT_TYPES
+clientdbGetCats(struct in_addr addr)
+{
+ char *key;
+ ClientInfo *c;
+
+ if (!Config.Options.client_db)
+ return WT_NULLPARM;
+ key=inet_ntoa(addr);
+ c=(ClientInfo *) hash_lookup(client_table,key);
+ if (c==NULL) c=clientdbAdd(addr);
+ if (c==NULL) debug_trap("clientdbUpdateVol: Failed to add entry");
+ return c->WTcats;
+}
+
+void
+clientdbSetCatsC(ClientInfo *c, char *catlist)
+{
+ if (!c) return;
+ if (c->WTcats != WT_NULLPARM) WT_FreeTypes(c->WTcats);
+ if (catlist && strlen(catlist)) {
+ c->WTcats = WT_AllocateTypes();
+ if (c->WTcats != WT_NULLPARM) wtsetcats(c->WTcats, catlist);
+ }
+ else c->WTcats = WT_NULLPARM;
+ return;
+}
+
+void
+clientdbSetLogin(ClientInfo *c, char *login)
+{
+ if (c->login_name) free(c->login_name);
+ if (login && strlen(login)) {
+ c->login_name = xstrdup(login);
+ }
+ else c->login_name = NULL;
+ return;
+}
+
+void
+clientdbSetCats(struct in_addr addr, char *catlist)
+{
+ char *key;
+ ClientInfo *c;
+
+ if (!Config.Options.client_db)
+ return;
+ key=inet_ntoa(addr);
+ c=(ClientInfo *) hash_lookup(client_table,key);
+ if (c==NULL) c=clientdbAdd(addr);
+ if (c==NULL) debug_trap("clientdbUpdateVol: Failed to add entry");
+ clientdbSetCatsC(c,catlist);
+ return;
+}
+
int
clientdbDeniedPercent(struct in_addr addr)
{
@@ -110,39 +196,176 @@
}
void
-clientdbDump(StoreEntry * sentry)
+clientdbStatsDump(StoreEntry *sentry,
+ struct _client_stats *Now,
+ struct _client_stats *Last,
+ struct _client_stats *StatsNow,
+ struct _client_stats *StatsLast,
+ char *desc)
+{ unsigned long reqtot, errtot, vtot, cvtot;
+ log_type l;
+
+ reqtot = Now->n_requests + Last->n_requests;
+ cvtot = (Now->v_requests/1000) + Last->v_requests;
+
+ if (sentry) {
+ storeAppendPrintf(sentry, "{ %s Requests %9d %9d }\n",desc,
+ reqtot, Now->n_requests);
+ storeAppendPrintf(sentry, "{ %s Volume %9lu KB %9lu }\n",desc,
+ cvtot, Now->v_requests);
+ }
+ if (StatsNow) {
+ StatsNow->n_requests+=Now->n_requests;
+ StatsNow->v_requests+=Now->v_requests;
+ }
+ if (StatsLast) {
+ StatsLast->n_requests+=Last->n_requests;
+ StatsLast->v_requests+=Last->v_requests;
+ }
+
+ for (l = LOG_TAG_NONE; l < ERR_MAX; l++) {
+ if (Now->result_hist[l]==0 && Last->result_hist[l] == 0) continue;
+ errtot = Now->result_hist[l] + Last->result_hist[l];
+ vtot = (Now->v_hist[l]/1000) + Last->v_hist[l];
+ if (sentry) storeAppendPrintf(sentry,
+ "{ %-20.20s %8lu KB %3d%% %7d %3d%% %8lu %3d%% %7d %3d%%}\n",
+ log_tags[l],
+ vtot,
+ percent(vtot,cvtot),
+ errtot,
+ percent(errtot,reqtot),
+ Now->v_hist[l],
+ percent(Now->v_hist[l],Now->v_requests),
+ Now->result_hist[l],
+ percent(Now->result_hist[l], Now->n_requests));
+ if (StatsNow) {
+ StatsNow->v_hist[l] += Now->v_hist[l];
+ StatsNow->result_hist[l] += Now->result_hist[l];
+ }
+ if (StatsLast) {
+ StatsLast->v_hist[l] += Last->v_hist[l];
+ StatsLast->result_hist[l]+= Last->result_hist[l];
+ }
+ }
+}
+
+
+void
+addstats(struct _client_stats *tot,
+ struct _client_stats *cur)
+{ log_type l;
+ if (!tot || !cur) {
+ return;
+ }
+
+ for (l=LOG_TAG_NONE; l < ERR_MAX; l++)
+ { tot->v_hist[l] += cur->v_hist[l]/1000;
+ tot->result_hist[l] += cur->result_hist[l];
+ }
+ tot->n_requests += cur->n_requests;
+ tot->v_requests += cur->v_requests/1000;
+ memset(cur,0,sizeof(struct _client_stats));
+}
+
+
+void
+clientdbDump(StoreEntry * sentry, char *extrainfo)
{
- ClientInfo *c;
- log_type l;
+#define MASK_ONE_IP 0xFFFFFFFF
+
+ ClientInfo *c, stats;
+ int resetvol=0, count=0, match=0;
+ char *maskp=NULL, *commands=NULL, *cmdp=NULL, *cmdp2=NULL;
+ struct in_addr ip,mask;
+ char tempstr[100];
+
+ mask.s_addr=MASK_ONE_IP;
+ ip.s_addr =0;
+
+ /* extra info
+ format: ip_address/mask?command
+ command may be:
+ WTCAT=catlist : catlist = list of ban categories for this ip
+ WTCAT= : disable ban categories on this ip
+ LOGIN=name : login name of user on this ip
+ */
+ if (extrainfo) {
+ if (*extrainfo=='-') { extrainfo++; resetvol=1; }
+ commands=strchr(extrainfo,'?');
+ if (commands) *commands++='\0';
+ maskp=strchr(extrainfo,'/');
+ if (maskp) { *maskp++='\0'; mask.s_addr=inet_addr(maskp); }
+ ip.s_addr=inet_addr(extrainfo);
+ if (ip.s_addr==-1) ip.s_addr = 0;
+ else {
+ /* Guarantee that an entry will exist - that way any settings will
+ be applied to at least that address :-)
+ */
+ c=(ClientInfo *) hash_lookup(client_table,extrainfo);
+ if (c==NULL) c=clientdbAdd(ip);
+ if (c==NULL) debug_trap("clientdbUpdateVol: Failed to add entry");
+
+ ip.s_addr &= mask.s_addr;
+ }
+ }
+ memset(&stats,0,sizeof(stats));
+
storeAppendPrintf(sentry, "{Cache Clients:\n");
c = (ClientInfo *) hash_first(client_table);
while (c) {
- storeAppendPrintf(sentry, "{Address: %s}\n", c->key);
- storeAppendPrintf(sentry, "{Name: %s}\n", fqdnFromAddr(c->addr));
- storeAppendPrintf(sentry, "{ ICP Requests %d}\n",
- c->Icp.n_requests);
- for (l = LOG_TAG_NONE; l < ERR_MAX; l++) {
- if (c->Icp.result_hist[l] == 0)
- continue;
- storeAppendPrintf(sentry,
- "{ %-20.20s %7d %3d%%}\n",
- log_tags[l],
- c->Icp.result_hist[l],
- percent(c->Icp.result_hist[l], c->Icp.n_requests));
- }
- storeAppendPrintf(sentry, "{ HTTP Requests %d}\n",
- c->Http.n_requests);
- for (l = LOG_TAG_NONE; l < ERR_MAX; l++) {
- if (c->Http.result_hist[l] == 0)
- continue;
- storeAppendPrintf(sentry,
- "{ %-20.20s %7d %3d%%}\n",
- log_tags[l],
- c->Http.result_hist[l],
- percent(c->Http.result_hist[l], c->Http.n_requests));
- }
+ match=0;
+ if (ip.s_addr && (ip.s_addr==(inet_addr(c->key) & mask.s_addr))) match=1;
+ else if (c->login_name && extrainfo && strcmp(c->login_name,extrainfo)==0) match=1;
+ else if (extrainfo && !*extrainfo) match=1;
+ else if (!extrainfo) match=1;
+ if (match) {
+ if (mask.s_addr==MASK_ONE_IP) {
+ storeAppendPrintf(sentry, "{Address: %s}\n", c->key);
+ storeAppendPrintf(sentry, "{Name: %s}\n", fqdnFromAddr(c->addr));
+ storeAppendPrintf(sentry, "{Login: %s}\n", (c->login_name?c->login_name:""));
+ storeAppendPrintf(sentry, "{Filters: %s}\n", wtgetcats(c->WTcats, tempstr));
+
+ clientdbStatsDump(sentry, &c->Icp, &c->IcpTotal,
+ &stats.Icp, &stats.IcpTotal, " ICP");
+ clientdbStatsDump(sentry, &c->Http, &c->HttpTotal,
+ &stats.Http, &stats.HttpTotal, "HTTP");
+ storeAppendPrintf(sentry, "{}\n");
+ count++;
+ }
+ else { clientdbStatsDump(NULL, &c->Icp, &c->IcpTotal, &stats.Icp, &stats.IcpTotal, "");
+ clientdbStatsDump(NULL, &c->Http,&c->HttpTotal,&stats.Http,&stats.HttpTotal,"");
+ }
+
+ if (resetvol) {
+ addstats(&c->HttpTotal,&c->Http);
+ addstats(&c->IcpTotal, &c->Icp);
+ }
+ cmdp=commands;
+ while (cmdp) { /* handle multiple items cgi-style - xxx=yyy&aaa=b */
+ cmdp2=strchr(cmdp,'&');
+ if (cmdp2) *cmdp2++='\0';
+ if (strncasecmp(cmdp,"WTCAT=",6)==0) clientdbSetCatsC(c,cmdp+6);
+ else if (strncasecmp(cmdp,"LOGIN=",6)==0) clientdbSetLogin(c,cmdp+6);
+ else { /* should log unknown arg... */ }
+ cmdp=cmdp2;
+ }
+ }
+ c = (ClientInfo *) hash_next(client_table);
+ }
+ if (count>1) {
storeAppendPrintf(sentry, "{}\n");
- c = (ClientInfo *) hash_next(client_table);
- }
+ clientdbStatsDump(sentry, &stats.Icp, &stats.IcpTotal, NULL, NULL, " ICP Total");
+ clientdbStatsDump(sentry, &stats.Http, &stats.HttpTotal, NULL, NULL, "HTTP Total");
+ }
+ else if (mask.s_addr!=MASK_ONE_IP) {
+ storeAppendPrintf(sentry, "{Address: %s}\n", extrainfo);
+ storeAppendPrintf(sentry, "{Name: %s}\n", extrainfo);
+
+ clientdbStatsDump(sentry, &stats.Icp, &stats.IcpTotal, NULL, NULL, " ICP");
+ clientdbStatsDump(sentry, &stats.Http, &stats.HttpTotal, NULL, NULL, "HTTP");
+ storeAppendPrintf(sentry, "{}\n");
+ }
+
storeAppendPrintf(sentry, close_bracket);
}
+
diff -urN squid-1.1.17/src/client_db.h squid/src/client_db.h
--- squid-1.1.17/src/client_db.h Sat Dec 14 00:00:00 1996
+++ squid/src/client_db.h Tue Jun 2 19:27:07 1998
@@ -32,9 +32,12 @@
#define CLIENT_DB_H
void clientdbInit _PARAMS((void));
-void clientdbUpdate _PARAMS((struct in_addr, log_type, u_short port));
-int clientdbDeniedPercent _PARAMS((struct in_addr));
-void clientdbDump _PARAMS((StoreEntry *));
+void clientdbUpdate _PARAMS((struct in_addr, log_type, u_short));
+int clientdbDeniedPercent _PARAMS((struct in_addr));
+void clientdbDump _PARAMS((StoreEntry *,char *));
+void clientdbUpdateVol _PARAMS((struct in_addr, log_type, u_short, long));
+WT_TYPES clientdbGetCats _PARAMS((struct in_addr));
+void clientdbSetCats _PARAMS((struct in_addr, char *));
extern int client_info_sz;
#endif /* CLIENT_DB_H */
diff -urN squid-1.1.17/src/client_side.c squid/src/client_side.c
--- squid-1.1.17/src/client_side.c Tue Aug 26 00:34:00 1997
+++ squid/src/client_side.c Fri Apr 3 19:31:56 1998
@@ -152,7 +152,8 @@
}
if (icpState->aclChecklist == NULL) {
icpState->aclChecklist = xcalloc(1, sizeof(aclCheck_t));
- icpState->aclChecklist->src_addr = icpState->peer.sin_addr;
+ /* icpState->aclChecklist->src_addr = icpState->peer.sin_addr; */
+ icpState->aclChecklist->src_addr = icpState->acct_addr;
icpState->aclChecklist->request = requestLink(icpState->request);
browser = mime_get_header(icpState->request_hdr, "User-Agent");
if (browser != NULL) {
@@ -540,6 +541,10 @@
icpState->log_type = LOG_TCP_REFRESH_HIT;
hbuf = get_free_8k_page();
storeClientCopy(oldentry, 0, 8191, hbuf, &len, fd);
+ clientdbUpdateVol(icpState->peer.sin_addr,
+ icpState->log_type,
+ ntohs(icpState->me.sin_port),
+ len);
if (oldentry->mem_obj->request == NULL) {
oldentry->mem_obj->request = requestLink(mem->request);
unlink_request = 1;
diff -urN squid-1.1.17/src/comm.c squid/src/comm.c
--- squid-1.1.17/src/comm.c Fri Aug 22 03:33:00 1997
+++ squid/src/comm.c Wed Apr 8 21:41:21 1998
@@ -1413,7 +1413,7 @@
char *
fd_note(int fd, const char *s)
-{
+{
if (s == NULL)
return (fd_table[fd].ascii_note);
xstrncpy(fd_table[fd].ascii_note, s, FD_ASCII_NOTE_SZ);
diff -urN squid-1.1.17/src/custom_error.html squid/src/custom_error.html
--- squid-1.1.17/src/custom_error.html Thu Jan 1 08:00:00 1970
+++ squid/src/custom_error.html Fri Jun 5 19:08:27 1998
@@ -0,0 +1,29 @@
+
+SmartFilter: Access Denied
+
+
+
+Access Denied
+
+The content you have requested contains material either unsuitable
+or irrelevant for your use as configured in the filtering setup
+on your account.
+
+This site was blocked by the following categories:
+%REASON
+
+
The SmartFilter system is currently under trial by MNS, so
+some unexpected results may occur.
+
+You can set the categories filtered for your service through Client Services
+on the MNS Home Page.
+
+If you discover a site or URL has been restricted for which you
+have a business need, but do not want to enable the entire category,
+record the URL for which you need access,
+and request an exemption for that URL by E-mailing
+mns@mns.net.au.
+
+Generated by SmartFilter at proxy.mns.net.au
+
+
diff -urN squid-1.1.17/src/custom_error.html.old squid/src/custom_error.html.old
--- squid-1.1.17/src/custom_error.html.old Thu Jan 1 08:00:00 1970
+++ squid/src/custom_error.html.old Tue Jun 2 15:42:49 1998
@@ -0,0 +1,46 @@
+
+Internet and WWW Acceptable Use Policy
+
+
+
+Internet and WWW Acceptable Use Policy
+
+The Internet connection you are using was established for business use.
+Use of this connection for non-business purposes is deemed an
+unacceptable use under this policy.
+
+Access restricted to proxy
+
+All browser access to the Internet for World Wide Web,
+FTP (file transfer), and gopher is required by policy
+to pass through a "proxy" machine that has been installed for this purpose.
+
+Browsers not configured to use the proxy will not be allowed
+direct access to the Internet.
+
+Logs are maintained
+
+Policy requires that logs of browser access to the Internet
+be kept. These logs record when and where, and from what networked computer
+Internet access has been allowed (or denied). Supervisors and authorized
+network management personnel have access to these logs.
+
+Use of this proxy and its attached Internet connection indicates your
+consent to usage monitoring and logging.
+
+
Non-business sites restricted
+
+In addition to keeping logs, the proxy may also restrict access
+to certain sites that have been determined to have no valid business
+purpose, or have been determined to contain objectionable material.
+
+Attempts to access these sites will result in the display of an error
+message including the reason(s) a site has been restricted.
+
+Exceptions made based on business need
+
+If you discover a site or URL has been restricted for which you
+have a business need, record the URL for which to which you need access,
+and request an exemption for that URL.
+
+
diff -urN squid-1.1.17/src/http.c squid/src/http.c
--- squid-1.1.17/src/http.c Fri Aug 8 00:00:00 1997
+++ squid/src/http.c Tue Oct 21 14:04:00 1997
@@ -771,6 +771,8 @@
strcat(viabuf, s);
strcat(viabuf, ", ");
continue;
+ } else if (strncasecmp(xbuf, "X-Acct-To:", 10) == 0) {
+ continue;
} else if (strncasecmp(xbuf, "X-Forwarded-For:", 16) == 0) {
for (s = xbuf + 16; *s && isspace(*s); s++);
if (strlen(fwdbuf) + strlen(s) < 4000)
diff -urN squid-1.1.17/src/icp.c squid/src/icp.c
--- squid-1.1.17/src/icp.c Thu Oct 9 06:18:00 1997
+++ squid/src/icp.c Tue Jun 2 21:38:55 1998
@@ -283,7 +283,7 @@
HTTPCacheInfo->proto_count(HTTPCacheInfo,
icpState->request ? icpState->request->protocol : PROTO_NONE,
icpState->log_type);
- clientdbUpdate(icpState->peer.sin_addr,
+ clientdbUpdate(icpState->acct_addr,
icpState->log_type,
ntohs(icpState->me.sin_port));
}
@@ -363,6 +363,21 @@
BIT_SET(request->flags, REQ_NOCACHE);
BIT_SET(request->flags, REQ_RANGE);
}
+ if ((t = mime_get_header(request_hdr, "X-Acct-To"))) {
+ struct in_addr addr;
+ addr.s_addr=inet_addr(t);
+ if (addr.s_addr!=-1) { char buf[FD_ASCII_NOTE_SZ+25];
+ icpState->acct_addr = addr;
+ icpState->peer.sin_addr = addr;
+ /* icpState->acct_addr.s_addr &= Config.Addrs.client_netmask.s_addr; */
+
+ /* make note of this for file handle listings... */
+ strcpy(buf, inet_ntoa(icpState->acct_addr));
+ strcat(buf, ", ");
+ strcat(buf, fd_note(icpState->fd, NULL));
+ fd_note(icpState->fd, buf);
+ }
+ }
if (mime_get_header(request_hdr, "Authorization"))
BIT_SET(request->flags, REQ_AUTH);
if (request->login[0] != '\0')
@@ -510,6 +525,10 @@
icpSendERRORComplete,
(void *) icpState,
put_free_4k_page);
+ clientdbUpdateVol(icpState->acct_addr,
+ icpState->log_type,
+ ntohs(icpState->me.sin_port),
+ buf_len);
}
#if LOG_FULL_HEADERS
@@ -567,6 +586,10 @@
icp_maybe_remember_reply_hdr(icpState);
#endif /* LOG_FULL_HEADERS */
icpState->out_offset += len;
+ clientdbUpdateVol(icpState->acct_addr,
+ icpState->log_type,
+ ntohs(icpState->me.sin_port),
+ len);
if (icpState->request->method == METHOD_HEAD) {
if ((p = mime_headers_end(buf))) {
*p = '\0';
@@ -703,6 +726,10 @@
icpHandleIMSComplete,
icpState,
xfree);
+ clientdbUpdateVol(icpState->acct_addr,
+ icpState->log_type,
+ ntohs(icpState->me.sin_port),
+ strlen(reply));
return COMM_OK;
}
@@ -772,6 +799,10 @@
icpSendERRORComplete,
icpState,
xfree);
+ clientdbUpdateVol(icpState->acct_addr,
+ icpState->log_type,
+ ntohs(icpState->me.sin_port),
+ strlen(reply));
return;
}
/* yes, continue */
@@ -961,6 +992,9 @@
clientdbUpdate(queue->address.sin_addr,
queue->logcode,
Config.Port.icp);
+ clientdbUpdateVol(queue->address.sin_addr,
+ queue->logcode,
+ Config.Port.icp,queue->len);
if (!Config.Options.log_udp)
return;
HTTPCacheInfo->log_append(HTTPCacheInfo,
@@ -1535,6 +1569,7 @@
sock,
len,
inet_ntoa(from.sin_addr));
+ neighborUpdateVol(&from.sin_addr,1,len);
#ifdef ICP_PACKET_DUMP
icpPktDump(buf);
#endif
@@ -1753,6 +1788,22 @@
icpSendERROR(fd, ERR_INVALID_URL, wbuf, icpState, 400);
return;
}
+
+#ifdef SMARTFILTER
+ if (Config.SmartFilterState) {
+ if (smartfilter_check_url(fd, icpState) == URL_ALLOWED) {
+ debug(61, 2, "clientReadRequest: SmartFilter allowed the url\n");
+ }
+ else {
+ debug(61, 2, "clientReadRequest: SmartFilter blocked the url\n");
+ return;
+ }
+ }
+ else {
+ debug(61, 5, "clientReadRequest: SmartFilter disabled\n");
+ }
+#endif
+
safe_free(icpState->log_url);
icpState->log_url = xstrdup(urlCanonicalClean(request));
request->http_ver = icpState->http_ver;
@@ -1883,11 +1934,13 @@
icpState->peer = peer;
icpState->log_addr = peer.sin_addr;
icpState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr;
+ icpState->acct_addr = peer.sin_addr;
+ /* icpState->acct_addr.s_addr &= Config.Addrs.client_netmask.s_addr; */
icpState->me = me;
icpState->entry = NULL;
icpState->fd = fd;
icpState->ident.fd = -1;
- fd_note(fd, inet_ntoa(icpState->log_addr));
+ fd_note(fd, inet_ntoa(icpState->acct_addr));
meta_data.misc += ASCII_INBUF_BLOCKSIZE;
commSetSelect(fd,
COMM_SELECT_LIFETIME,
@@ -2092,10 +2145,12 @@
icpState->peer = peer;
icpState->log_addr = peer.sin_addr;
icpState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr;
+ icpState->acct_addr = peer.sin_addr;
+ /* icpState->acct_addr.s_addr &= Config.Addrs.client_netmask.s_addr; */
icpState->me = me;
icpState->entry = NULL;
icpState->fd = fd;
- fd_note(fd, inet_ntoa(icpState->log_addr));
+ fd_note(fd, inet_ntoa(icpState->acct_addr));
meta_data.misc += ASCII_INBUF_BLOCKSIZE;
comm_add_close_handler(fd,
icpStateFree,
diff -urN squid-1.1.17/src/icp.h squid/src/icp.h
--- squid-1.1.17/src/icp.h Fri Jul 11 00:00:00 1997
+++ squid/src/icp.h Tue Jun 2 15:42:52 1998
@@ -187,6 +187,7 @@
struct sockaddr_in peer;
struct sockaddr_in me;
struct in_addr log_addr;
+ struct in_addr acct_addr;
struct timeval start;
int accel;
int size; /* hack for CONNECT which doesnt use sentry */
diff -urN squid-1.1.17/src/main.c squid/src/main.c
--- squid-1.1.17/src/main.c Thu Oct 9 01:09:00 1997
+++ squid/src/main.c Tue Jun 2 15:42:52 1998
@@ -317,6 +317,9 @@
void
shut_down(int sig)
{
+#ifdef SMARTFILTER
+ smartfilter_free();
+#endif
shutdown_pending = sig == SIGINT ? -1 : 1;
debug(1, 1, "Preparing for shutdown after %d connections\n",
ntcpconn + nudpconn);
@@ -503,6 +506,9 @@
static void
mainReinitialize(void)
{
+#ifdef SMARTFILTER
+ smartfilter_free();
+#endif
debug(1, 0, "Restarting Squid Cache (version %s)...\n", version_string);
/* Already called serverConnectionsClose and ipcacheShutdownServers() */
neighborsDestroy();
@@ -516,6 +522,9 @@
ftpInitialize();
if (theOutIcpConnection >= 0 && (!httpd_accel_mode || Config.Accel.withProxy))
neighbors_open(theOutIcpConnection);
+#ifdef SMARTFILTER
+ smartfilter_init();
+#endif
debug(1, 0, "Ready to serve requests.\n");
}
@@ -618,6 +627,9 @@
eventAdd("ipcache_purgelru", (EVH) ipcache_purgelru, NULL, 10);
}
first_time = 0;
+#ifdef SMARTFILTER
+ smartfilter_init();
+#endif
}
int
diff -urN squid-1.1.17/src/neighbors.c squid/src/neighbors.c
--- squid-1.1.17/src/neighbors.c Fri Aug 22 03:17:00 1997
+++ squid/src/neighbors.c Tue Oct 21 14:04:00 1997
@@ -129,6 +129,8 @@
static u_short echo_port;
static int NLateReplies = 0;
+static unsigned long DirectVolume=0, ParentVolumeHttp=0, ParentVolumeIcp=0;
+static unsigned long LastDirectVol=0, LastParentVolHttp=0, LastParentVolIcp=0;
static struct {
int n;
@@ -193,6 +195,55 @@
}
}
return NULL;
+}
+
+void
+neighborUpdateVol(struct in_addr *addr, u_short port, long len)
+{ peer *p;
+ int j;
+
+ for (p=Peers.peers_head; p; p=p->next) {
+ for (j=0; jn_addresses; j++) {
+ if (addr->s_addr==p->addresses[j].s_addr)
+ {
+ debug(15,2,"neighborUpdateVol: %s:%d : %lu bytes\n",
+ inet_ntoa(p->addresses[0]),port,len);
+ if (!port) { p->stats.v_fetches+=len;
+ ParentVolumeHttp +=len;
+ }
+ else { p->stats.v_icp +=len;
+ ParentVolumeIcp +=len;
+ }
+ return;
+ }
+ }
+ }
+ DirectVolume+=len;
+}
+
+void GetIntakeVolume(unsigned long *direct,
+ unsigned long *http,
+ unsigned long *icp,
+ int reset)
+{ *direct= DirectVolume;
+ *http = ParentVolumeHttp;
+ *icp = ParentVolumeIcp;
+ if (reset) {
+ LastDirectVol+=DirectVolume/1000;
+ LastParentVolHttp+=ParentVolumeHttp/1000;
+ LastParentVolIcp+=ParentVolumeIcp/1000;
+ DirectVolume=0;
+ ParentVolumeHttp=0;
+ ParentVolumeIcp=0;
+ }
+}
+
+void GetLastIntakeVolume(unsigned long *direct,
+ unsigned long *http,
+ unsigned long *icp)
+{ *direct= LastDirectVol;
+ *http = LastParentVolHttp;
+ *icp = LastParentVolIcp;
}
void
diff -urN squid-1.1.17/src/neighbors.h squid/src/neighbors.h
--- squid-1.1.17/src/neighbors.h Fri Aug 22 03:17:00 1997
+++ squid/src/neighbors.h Tue Oct 21 14:04:00 1997
@@ -166,19 +166,24 @@
#define PEER_MAX_ADDRESSES 10
#define RTT_AV_FACTOR 1000
-struct _peer {
- char *host;
- neighbor_t type;
- struct sockaddr_in in_addr;
- struct {
+
+struct _peer_stats {
int pings_sent;
int pings_acked;
int ack_deficit;
int fetches;
+ unsigned long v_fetches;
+ unsigned long v_icp;
int rtt;
int counts[ICP_OP_END];
int ignored_replies;
- } stats;
+};
+
+struct _peer {
+ char *host;
+ neighbor_t type;
+ struct sockaddr_in in_addr;
+ struct _peer_stats stats, last_stats;
u_short icp_port;
u_short http_port;
int icp_version;
@@ -255,6 +260,9 @@
extern void peerDestroy _PARAMS((peer * e));
extern char *neighborTypeStr _PARAMS((const peer * e));
extern void peerCheckConnectStart _PARAMS((peer *));
+extern void neighborUpdateVol _PARAMS((struct in_addr *, u_short, long));
+extern void GetIntakeVolume _PARAMS((unsigned long *,unsigned long *,unsigned long *, int reset));
+extern void GetLastIntakeVolume _PARAMS((unsigned long *,unsigned long *,unsigned long *));
extern const char *hier_strings[];
diff -urN squid-1.1.17/src/objcache.c squid/src/objcache.c
--- squid-1.1.17/src/objcache.c Wed Mar 26 00:00:00 1997
+++ squid/src/objcache.c Wed Jun 3 18:11:46 1998
@@ -127,7 +127,7 @@
struct _cachemgr_passwd *next;
};
-static ObjectCacheData *objcache_url_parser _PARAMS((const char *url));
+static ObjectCacheData *objcache_url_parser _PARAMS((const char *url, char *extrainfo));
static int objcache_CheckPassword _PARAMS((ObjectCacheData *));
static char *objcachePasswdGet _PARAMS((cachemgr_passwd ** a, objcache_op op));
@@ -142,7 +142,7 @@
(1 << MGR_CONFIG_FILE);
static objcache_op
-objcacheParseRequest(const char *buf)
+objcacheParseRequest(const char *buf, char *extrainfo)
{
objcache_op op = MGR_NONE;
if (!strcmp(buf, "shutdown"))
@@ -183,8 +183,16 @@
op = MGR_LOG_VIEW;
else if (!strcmp(buf, "parameter"))
op = MGR_CONFIG;
+ else if (!strncmp(buf, "server_list/",12))
+ { op = MGR_SERVER_LIST_IP;
+ if (extrainfo) strncpy(extrainfo,buf+12,100);
+ }
else if (!strcmp(buf, "server_list"))
op = MGR_SERVER_LIST;
+ else if (!strncmp(buf, "client_list/",12))
+ { op = MGR_CLIENT_LIST_IP;
+ if (extrainfo) strncpy(extrainfo,buf+12,100);
+ }
else if (!strcmp(buf, "client_list"))
op = MGR_CLIENT_LIST;
else if (!strcmp(buf, "squid.conf"))
@@ -194,7 +202,7 @@
static ObjectCacheData *
-objcache_url_parser(const char *url)
+objcache_url_parser(const char *url, char *extrainfo)
{
int t;
LOCAL_ARRAY(char, host, MAX_URL);
@@ -208,7 +216,7 @@
}
obj = xcalloc(1, sizeof(ObjectCacheData));
strcpy(obj->passwd, t == 3 ? password : "nopassword");
- obj->op = objcacheParseRequest(request);
+ obj->op = objcacheParseRequest(request,extrainfo);
return obj;
}
@@ -233,9 +241,10 @@
static const char *const BADPassword = "Incorrect password, sorry.\n";
ObjectCacheData *data = NULL;
int complete_flag = 1;
+ char extrainfo[101]="";
debug(16, 3, "objectcacheStart: '%s'\n", url);
- if ((data = objcache_url_parser(url)) == NULL) {
+ if ((data = objcache_url_parser(url,extrainfo)) == NULL) {
storeAbort(entry, "Invalid objcache syntax.\n");
entry->expires = squid_curtime + STAT_TTL;
safe_free(data);
@@ -245,9 +254,10 @@
data->reply_fd = fd;
data->entry = entry;
entry->expires = squid_curtime + STAT_TTL;
- debug(16, 1, "CACHEMGR: %s requesting '%s'\n",
+ debug(16, 1, "CACHEMGR: %s requesting '%s' info: '%s'\n",
fd_table[fd].ipaddr,
- objcacheOpcodeStr[data->op]);
+ objcacheOpcodeStr[data->op],
+ extrainfo);
/* Check password */
if (objcache_CheckPassword(data) != 0) {
debug(16, 1, "WARNING: Incorrect Cachemgr Password!\n");
@@ -321,10 +331,16 @@
HTTPCacheInfo->parameter_get(HTTPCacheInfo, entry);
break;
case MGR_SERVER_LIST:
- HTTPCacheInfo->server_list(HTTPCacheInfo, entry);
+ HTTPCacheInfo->server_list(HTTPCacheInfo, entry, extrainfo);
+ break;
+ case MGR_SERVER_LIST_IP:
+ HTTPCacheInfo->server_list(HTTPCacheInfo, entry, extrainfo);
break;
case MGR_CLIENT_LIST:
- clientdbDump(entry);
+ clientdbDump(entry,extrainfo);
+ break;
+ case MGR_CLIENT_LIST_IP:
+ clientdbDump(entry,extrainfo);
break;
case MGR_CONFIG_FILE:
HTTPCacheInfo->squid_get_start(HTTPCacheInfo, entry);
@@ -369,7 +385,7 @@
q->actions = ~0;
continue;
}
- op = objcacheParseRequest(w->key);
+ op = objcacheParseRequest(w->key,NULL);
if (op <= MGR_NONE || op >= MGR_MAX) {
debug(16, 0, "objcachePasswdAdd: Invalid operation: '%s'\n", w->key);
continue;
diff -urN squid-1.1.17/src/objcache_opcodes.h squid/src/objcache_opcodes.h
--- squid-1.1.17/src/objcache_opcodes.h Sat Dec 14 00:00:00 1996
+++ squid/src/objcache_opcodes.h Wed Jun 3 18:23:10 1998
@@ -31,6 +31,7 @@
typedef enum {
MGR_NONE,
MGR_CLIENT_LIST,
+ MGR_CLIENT_LIST_IP,
MGR_CONFIG,
MGR_CONFIG_FILE,
MGR_DNSSERVERS,
@@ -51,6 +52,7 @@
MGR_REMOVE,
MGR_REPLY_HDRS,
MGR_SERVER_LIST,
+ MGR_SERVER_LIST_IP,
MGR_SHUTDOWN,
MGR_UTILIZATION,
MGR_VM_OBJECTS,
@@ -61,6 +63,7 @@
{
"NONE",
"client_list",
+ "client_list/ip",
"config",
"config_file",
"dnsservers",
@@ -81,6 +84,7 @@
"remove",
"reply_headers",
"server_list",
+ "server_list/ip",
"shutdown",
"utilization",
"vm_objects",
diff -urN squid-1.1.17/src/proto.c squid/src/proto.c
--- squid-1.1.17/src/proto.c Fri Aug 22 03:25:00 1997
+++ squid/src/proto.c Tue Oct 21 14:04:00 1997
@@ -584,6 +584,7 @@
#endif
if (e) {
e->stats.fetches++;
+ entry->mem_obj->source=e->in_addr.sin_addr;
return proxyhttpStart(url, request, entry, e);
} else if (request->protocol == PROTO_HTTP) {
return httpStart(url, request, request_hdr, request_hdr_sz, entry);
diff -urN squid-1.1.17/src/smartfilter.conf squid/src/smartfilter.conf
--- squid-1.1.17/src/smartfilter.conf Thu Jan 1 08:00:00 1970
+++ squid/src/smartfilter.conf Tue Jun 2 15:42:49 1998
@@ -0,0 +1,66 @@
+#
+# Smartfilter Configuration File
+#
+# Identify below the full path and name of the
+# Control List file
+#
+controlfile /etc/wtcontrol
+domainresolvedfile /etc/wtcntldr
+#
+# For Squid redirect function specify a url to be used to
+# redirect blocked requests
+#redirecturl http://put.site.here/error.html
+#
+#
+# Identify below the full path and name of the local, site-specific
+# file to augment the full Control List (optional)
+#
+sitefile /etc/smartfilter.site
+#
+# errorfile is used by SmartFilter for Squid patch to
+# present a custom error message on a rejected request
+#errorfile /etc/custom_error.html
+#
+# This optional parameter specifies the error message to be
+# displayed to the user.
+#
+# The %REASON keyword (also optional) will be replaced by
+# the category descriptions.
+#
+errortext categories: %REASON are restricted.
+#
+# The following "#restrict" lines control which Control List
+# categories are forbidden. The category description (in quotes)
+# at the end of each line specifies the category
+# description to be inserted, as appropriate, in the position
+# specified by the %REASON keyword in the errortext parameter
+#
+restrict sx "Sex" #1
+restrict dr "Illegal Drugs" #2
+restrict hs "Hate Speech" #3
+restrict cs "Criminal Skills" #4
+restrict wt "Worthless" #5
+restrict os "On-line Sales" #6
+restrict gb "Gambling" #7
+restrict pp "Personal Ads" #8
+restrict js "Job Search" #9
+restrict sp "Sports" #10
+restrict gm "Games and Fun" #11
+restrict hm "Humor" #12
+restrict aj "Alternative Journal" #13
+restrict et "Entertainment" #14
+restrict ls "Personal, Alternative Lifestyle" #15
+restrict ex "Extreme, Gross,Indecent Content" #16
+restrict ch "Chat Web" #17
+restrict in "Investments Information" #18
+restrict nw "General News" #19
+restrict po "Poltics, Opinion, Religion" #20
+restrict mm "Dating and Introduction Service" #21
+restrict ac "Art and Culture" #22
+restrict oc "Cult/Occult" #23
+restrict na "Usenet News Site" #24
+restrict sh "Self Help" #25
+restrict tr "Travel" #26
+restrict ne "Non-Essential" #27
+#
+# End of config file
diff -urN squid-1.1.17/src/smartfilter.site squid/src/smartfilter.site
--- squid-1.1.17/src/smartfilter.site Thu Jan 1 08:00:00 1970
+++ squid/src/smartfilter.site Tue Jun 2 15:42:49 1998
@@ -0,0 +1,97 @@
+#
+# Smartfilter Site Overrides/Excemptions File
+#
+# Local Additions/Exemptions to the SmartFilter Control List
+#
+# Entries in this file, which is loaded at startup, take
+# precedence over entries in the Smartfilter Control List.
+#
+# Sites, parts of sites (i.e. a directory path within a site), or
+# individual URLs canbe specified.
+#
+# To exempt follow the site, path or URL specification with the word
+# EXEMPT.
+#
+# To add a site, path, or URL to one or more categories that are
+# restricted, follow the site, path or URL specification with
+# A comma-delimited string of two-letter category codes, as shown
+# below.
+#
+# format of file is
+#
+# Column 1 - the URL (ex: http://www.test.com/ )
+# Column 2 - Blank
+# Column 3 - for restrict action a list of category
+# codes, comma seperated, NO spaces.
+# Category codes -
+# aj - alternative journal
+# ac - art/culture
+# ch - chat site/gateway
+# cs - criminal skills
+# dr - drugs
+# et - entertainment
+# ex - extreme
+# gb - gambling
+# gm - games & fun
+# hm - humor
+# hs - hate speech
+# in - investing
+# js - job search
+# ls - lifestyle
+# mm - dating/match making
+# na - usenet access
+# ne - non-essential
+# nw - general news
+# oc - cult/occult
+# os - online sales/merchandising
+# pp - personal pages
+# po - politics/opinion
+# sh - self help
+# sp - sports
+# sx - sex
+# tr - travel
+# wt - worthless
+
+#
+# for exemption action the word exempt
+#
+# Examples:
+# (Note: these fictitious examples assume all categories shown are restricted
+# in the WebTrack NP configuration file)
+#
+# Restricting an entire site:
+#
+http://sexstuff.com sx,os
+#
+# Restricting an entire site using a dotted decimal address:
+#
+http://123.456.78.9 sx,os
+#
+# Restricting part of a site (all URLs beginning with specified path):
+#
+http://www.university.edu/computerscience/~joecollege/PICS/Girls sx,pp
+#
+# Restricting part of a site using dotted decimal addressing (all URLs
+beginning with specified path):
+#
+http://123.456.78.9/computerscience/~joecollege/PICS/Girls sx,pp
+#
+# Restricting a single URL without blocking the rest of a site:
+#
+http://www.bigco.com/HR/jobs.html js
+#
+#
+# Exempting an entire site:
+#
+http://www.asexysite.com exempt
+#
+# Exempting a path without exempting the balance of the site:
+#
+http://www.sexmag.com/articles exempt
+#
+# Exempting an individual URL without exempting the balance of the site:
+#
+http://www.sexmag.com/HumanResources/jobs/photographer.htm exempt
+#
+#END Site File
+
diff -urN squid-1.1.17/src/smartfilter_squid.c squid/src/smartfilter_squid.c
--- squid-1.1.17/src/smartfilter_squid.c Thu Jan 1 08:00:00 1970
+++ squid/src/smartfilter_squid.c Fri Jun 5 09:36:20 1998
@@ -0,0 +1,711 @@
+
+/*
+ * smartfilter_squid.c - an interface between Squid and SmartFilter
+ *
+ *
+ */
+
+/*
+ * Copyright (c) 1998. Secure Computing Corp.
+ * All rights reserved.
+ */
+
+#include "squid.h"
+
+#define MAX_LINE 1024
+
+#define CATDESC struct cat_desc
+CATDESC {
+ CATDESC *CTnext; /* Adr of next */
+ int CTapidesc; /* API category code */
+ int CTcategory; /* Category code T or F */
+ char CTwtcat[4]; /* WebTrack 2 char category code */
+ char CTsitedesc[1]; /* Site description */
+};
+
+/*
+ CAT_MAP replaces those horrible long if ... then .... else
+ statements that were originally in here....
+*/
+struct CAT_MAP {
+ int CTapidesc;
+ char CTwtcat[4];
+};
+static struct CAT_MAP cat_map[]={
+ { WT_CAT_SEX, "sx"},
+ { WT_CAT_DRUGS, "dr"},
+ { WT_CAT_HATESPEECH, "hs"},
+ { WT_CAT_CRIME, "cs"},
+ { WT_CAT_WORTHLESS, "os"},
+ { WT_CAT_SALES, "gb"},
+ { WT_CAT_GAMBLING, "pp"},
+ { WT_CAT_PERSONAL, "js"},
+ { WT_CAT_JOBS, "sp"},
+ { WT_CAT_SPORTS, "gm"},
+ { WT_CAT_GAMES, "hm"},
+ { WT_CAT_HUMOR, "aj"},
+ { WT_CAT_ALTJRNL, "et"},
+ { WT_CAT_ENTERTAIN, "ls"},
+ { WT_CAT_LIFESTYLE, "ex"},
+ { WT_CAT_EXTREME, "wt"},
+ { WT_CAT_CHAT, "ch"},
+ { WT_CAT_INVESTMENTS, "in"},
+ { WT_CAT_GNEWS, "nw"},
+ { WT_CAT_OPINION, "po"},
+ { WT_CAT_DATING, "mm"},
+ { WT_CAT_ART, "ac"},
+ { WT_CAT_CULT, "na"},
+ { WT_CAT_NEWSSITE, "oc"},
+ { WT_CAT_SELFHELP, "sh"},
+ { WT_CAT_TRAVEL, "tr"},
+ { WT_CAT_NONESSENTIAL, "ne"},
+ { 0, "" }
+ };
+
+static char * default_error_msg (int code, int method, const char *url, const char *client,const char *reason);
+static char * load_custom_error_file (char *filepath);
+
+static WT_SERVICE WTserv = WT_NULLPARM;
+static WT_TYPES WTtype = WT_NULLPARM;
+static WT_TYPES WTcat = WT_NULLPARM;
+static WT_TYPES WTwork = WT_NULLPARM;
+static CATDESC *WTdesc = (CATDESC * ) WT_NULLPARM;
+static char *WTerrtext = NULL;
+static char *WTerrfile = NULL;
+static char *WTcustom_errtext = NULL; /* we read the custom error file into here */
+static char err_message[MAX_LINE];
+static int WTfailcnt = 0;
+static int WTexpired = FALSE;
+
+
+int wtcattonum(char *wtcat)
+{ struct CAT_MAP *c=cat_map;
+ while (c->CTapidesc && strcmp(c->CTwtcat,wtcat)) c++;
+ return c->CTapidesc;
+}
+
+char *wtnumtocat(int apidesc)
+{ struct CAT_MAP *c=cat_map;
+ while (c->CTapidesc && c->CTapidesc!=apidesc) c++;
+ return c->CTwtcat;
+}
+
+char *wtgetcats(WT_TYPES *WTtypes, char *buf)
+{ struct CAT_MAP *c=cat_map;
+ char *bufend;
+ *buf='\0';
+ if (WTtypes == WT_NULLPARM) return buf;
+
+ while (c->CTapidesc) {
+ if (WT_TestThisCategory(WTtypes, c->CTapidesc) == WTISSET) {
+ strcat(buf,c->CTwtcat);
+ strcat(buf,",");
+ }
+ c++;
+ }
+ bufend=buf+strlen(buf);
+ if (bufend>buf) bufend--;
+ if (*bufend==',') *bufend='\0';
+ return buf;
+}
+
+/* set category discriptions based on what is in the configuration file */
+static void wtsetcatdesc( char *wtcat, char *sitedesc, int apidesc, int catyn )
+{
+ CATDESC *workdesc;
+ int i;
+
+ for ( i = 1; i < strlen( sitedesc ); i++ )
+ {
+ if ( *(sitedesc + i ) == '"' )
+ {
+ break;
+ }
+ }
+ i--; /* Back up from last quote */
+ workdesc = calloc( 1, sizeof( CATDESC) + i );
+ if ( workdesc )
+ {
+ strncpy( workdesc->CTwtcat, wtcat, sizeof( workdesc->CTwtcat) -1 );
+ strncpy( workdesc->CTsitedesc, sitedesc+1, i );
+ workdesc->CTapidesc = apidesc;
+ workdesc->CTcategory = catyn;
+ workdesc->CTnext = WTdesc;
+ WTdesc = workdesc;
+ }
+
+}
+
+/* check and get description to cat onto the err_message */
+static void wtfindcat( int category, char *workarea, int catyn )
+{
+ CATDESC *workdesc;
+
+ for ( workdesc = WTdesc; workdesc; workdesc = workdesc->CTnext )
+ {
+ if ( ( workdesc->CTapidesc == category ) &&
+ ( workdesc->CTcategory == catyn ) )
+ {
+ strcat( workarea, workdesc->CTsitedesc );
+ strcat( workarea, "," );
+ return;
+ }
+ }
+}
+
+
+/* generate the errtext output string based on info in the configuration file */
+static char *wtmakeerr( int iscategory, WT_TYPES WTwork, char *errtext, char *workarea )
+{
+ char *workchar, *errreason;
+
+ if ( errtext == NULL )
+ return( NULL );
+ errreason = strstr( errtext, "%REASON" );
+ if ( errreason == NULL )
+ {
+ return( errtext );
+ }
+ errreason += 7;
+ strcpy( workarea, errtext );
+ workchar = strstr( workarea, "%REASON" );
+ *workchar = '\0';
+ strcat( workarea," ");
+ if ( iscategory )
+ { struct CAT_MAP *c=cat_map;
+ while (c->CTapidesc) {
+ if ( WT_TestThisCategory( WTwork, c->CTapidesc ) == WTISSET )
+ wtfindcat( c->CTapidesc, workarea, TRUE );
+ c++;
+ }
+ }
+ else
+ {
+ if ( WT_TestThisControl( WTwork, WT_CONTROL_DDD ) == WTISSET )
+ wtfindcat( WT_CONTROL_DDD, workarea, FALSE );
+ if ( WT_TestThisControl( WTwork, WT_CONTROL_UNCATPERSONAL ) == WTISSET )
+ wtfindcat( WT_CONTROL_UNCATPERSONAL, workarea, FALSE );
+
+ }
+ if ( workarea[strlen(workarea) - 1] == ',' )
+ workarea[strlen(workarea) - 1] = '\0';
+ strcat( workarea, errreason );
+ return( workarea );
+}
+
+
+
+/* set and return the first category matched */
+static int wtsetcat( WT_TYPES *WTtype, char *parm2 )
+{ struct CAT_MAP *c=cat_map;
+
+ while (c->CTapidesc && strstr(parm2, c->CTwtcat)==0) c++;
+ if (c->CTapidesc) WT_SetThisCategory( WTtype, c->CTapidesc);
+ return c->CTapidesc;
+}
+
+/* set all categories matched */
+// static
+void wtsetcats( WT_TYPES *WTtype, char *parm2 )
+{ struct CAT_MAP *c=cat_map;
+
+ while (c->CTapidesc) {
+ if (strstr( parm2, c->CTwtcat))
+ WT_SetThisCategory( WTtype, c->CTapidesc );
+ c++;
+ }
+}
+
+
+/******************************************
+ * Local Function to update local site file
+ *
+ * Input is name of local site file
+ *
+ * format of file is
+ * - the URL (ex: http://www.test.com/ )
+ * - Blank
+ * - for restrict action a list of category
+ * codes, comma seperated, NO spaces.
+ * Category codes - sx - sex
+ * dr - drugs
+ * hs - hate speech
+ * cs - criminal skills
+ * os - online sales/merchandising
+ * gb - gambling
+ * pp - personal pages
+ * js - job search
+ * sp - sports
+ * gm - games
+ * hm - humor
+ * aj - alternative journal
+ * et - entertainment
+ * ls - lifestyle
+ * ex - extreme
+ * wt - worthless
+ * ch - chat gateway
+ * in - investing
+ * nw - general news
+ * po - politics, opinion, religion
+ * mm - dating
+ * ac - art culture
+ * na - usenet news access
+ * oc - occult/cults
+ * sh - self help
+ * tr - travel
+ * ne - non-essential
+ * for exemption action the word exempt
+ *
+ * Returns - True for OK
+ * False for failure
+ ******************************************/
+
+/* load the site-specific exemptions and restrictions */
+static int wtloadsitelist( WT_SERVICE wthandle, char *localfile )
+{
+ int workint;
+ FILE *fhandle; /* File handle */
+ WT_TYPES WebTrackTypes; /* types */
+ char workbuf[1024]; /* Input buffer */
+ char url[1024]; /* Input url */
+ char categoryinfo[1024]; /* category info */
+
+ debug(61, 5, "SmartFilter wtloadsitelist: loading site list from %s\n", localfile);
+
+ WebTrackTypes = WT_AllocateTypes();
+ if ( WebTrackTypes == NULL )
+ {
+ return( FALSE );
+ }
+ fhandle = fopen( localfile, "r" );
+ if ( fhandle == NULL )
+ {
+ return( FALSE );
+ }
+
+ while ( fgets( workbuf, sizeof( workbuf ), fhandle ) )
+ {
+ /* Clear the Types object */
+ WT_ClearTypes( WebTrackTypes );
+ if ( workbuf[0] == '#' )
+ continue;
+
+ workint = sscanf( workbuf, "%s%s", url, categoryinfo);
+ if ( workint > 0 )
+ {
+ /* Set type of entry to path */
+ WT_SetThisControl( WebTrackTypes, WT_CONTROL_PATH );
+ /* Set categories */
+ if ( strcasecmp( categoryinfo, "exempt" ) == 0 )
+ {
+ WT_SetThisControl( WebTrackTypes, WT_CONTROL_EXEMPT );
+ }
+ else
+ {
+ WT_SetThisControl( WebTrackTypes, WT_CONTROL_RESTRICT );
+
+ /* Note: Colin changed this from wtsetcat() to wtsetcats() to
+ * allow one site to be in multiple categories in the site list
+ */
+ wtsetcats( WebTrackTypes, categoryinfo );
+ }
+ if ( WT_UpdateSiteList( wthandle, url, WebTrackTypes ) != 0 )
+ {
+ fclose( fhandle );
+ return( FALSE );
+ }
+ }
+ }
+ WT_FreeTypes( WebTrackTypes );
+ fclose( fhandle );
+ return( TRUE );
+}
+
+/* Used to free static array on restart */
+void smartfilter_free()
+{
+ CATDESC *workdesc;
+
+ debug(61, 0, "Disabling SmartFilter\n");
+ debug(61, 5, "SmartFilter: freeing up resources\n");
+ Config.SmartFilterState = 0;
+
+ while ( WTdesc )
+ {
+ workdesc = WTdesc->CTnext;
+ free( WTdesc );
+ WTdesc = workdesc;
+ }
+ if ( WTerrtext )
+ {
+ free( WTerrtext );
+ WTerrtext = NULL;
+ }
+ WT_FreeTypes( WTtype );
+ WT_FreeTypes( WTcat );
+ WT_FreeTypes( WTwork );
+ WT_FreeService( WTserv );
+ WTserv = WT_NULLPARM;
+ WTtype = WT_NULLPARM;
+ WTcat = WT_NULLPARM;
+ WTwork = WT_NULLPARM;
+ WTfailcnt = 0;
+ WTexpired = FALSE;
+}
+
+/* initialize SmartFilter and load settings from configuration file
+ * returns zero if all is well, -1 if problems found
+ */
+int smartfilter_init()
+{
+ /* Working variables */
+ FILE *f;
+ char *workchar;
+ char buf[MAX_LINE];
+ char parm1[MAX_LINE];
+ char parm2[MAX_LINE];
+ char parm3[MAX_LINE];
+ char sitef[MAX_LINE];
+ char cntlf[MAX_LINE];
+ char dnrfile[MAX_LINE];
+ int workint;
+
+ if (Config.SmartFilterState) {
+ debug(61, 5, "Initializing SmartFilter\n");
+ }
+ else {
+ debug(61, 5, "SmartFilter init: SmartFilter disabled\n");
+ return 0;
+ }
+
+ memset( sitef, 0, MAX_LINE );
+ memset( cntlf, 0, MAX_LINE );
+ memset( dnrfile, 0, MAX_LINE );
+
+ debug(61, 5, "SmartFilter init: config file is %s\n", Config.SmartFilterConf);
+
+ if(!Config.SmartFilterConf) {
+ debug(61, 0, "SmartFilter init: missing parameter to webtrack_init (need file)\n");
+ smartfilter_free();
+ return -1;
+ }
+ f = fopen(Config.SmartFilterConf, "r");
+
+ /* Did we open it? */
+ if(!f) {
+ debug(61, 0, "SmartFilter init: can't open config file, disabling SmartFilter\n");
+ smartfilter_free();
+ return -1;
+ }
+ WTserv = WT_Init();
+ if ( WTserv == WT_NULLPARM )
+ {
+ debug(61, 0, "SmartFilter init: can't Initialize, disabling SmartFilter\n");
+ fclose(f);
+ smartfilter_free();
+ return -1;
+ }
+ WTtype = WT_AllocateTypes();
+ if ( WTtype == WT_NULLPARM )
+ {
+ debug(61, 0, "SmartFilter init: can't Allocate WTtype\n");
+ fclose(f);
+ smartfilter_free();
+ return -1;
+ }
+ WTcat = WT_AllocateTypes();
+ if ( WTcat == WT_NULLPARM )
+ {
+ debug(61, 0, "SmartFilter init: can't Allocate WTcat\n");
+ fclose(f);
+ smartfilter_free();
+ return -1;
+ }
+ WTwork = WT_AllocateTypes();
+ if ( WTwork == WT_NULLPARM )
+ {
+ debug(61, 0, "SmartFilter init: can't Allocate WTwork\n");
+ fclose(f);
+ smartfilter_free();
+ return -1;
+ }
+ /* Process config file */
+ while(fgets(buf, MAX_LINE, f))
+ { /* Blast linefeed that stdio helpfully leaves on there */
+ buf[strlen(buf) - 1] = '\0';
+ sscanf(buf,"%s%s%s",parm1, parm2, parm3);
+ if ( strcmp( parm1, "controlfile") == 0 )
+ {
+ strcpy(cntlf, parm2 );
+ }
+ else if ( strcmp( parm1, "sitefile") == 0 )
+ {
+ strcpy(sitef, parm2 );
+ }
+ else if ( strcmp( parm1, "domainresolvedfile") == 0 )
+ {
+ strcpy(dnrfile, parm2 );
+ }
+ else if ( strcmp( parm1, "restrict") == 0 )
+ {
+ workint = wtsetcat( WTtype, parm2 );
+ if ( ( workchar = strchr( buf, '"' ) ) != NULL )
+ {
+ wtsetcatdesc( parm2, workchar, workint, TRUE );
+ }
+ }
+ else if ( strcmp( parm1, "describe") == 0 )
+ { workint=wtcattonum(parm2);
+ if (workint && (workchar=strchr(buf,'"') ) != NULL )
+ wtsetcatdesc( parm2, workchar, workint, TRUE );
+ }
+ else if ( strcmp( parm1, "dotteddecimal") == 0 )
+ {
+ if ( strcmp( parm2, "forbid" ) == 0 )
+ {
+ WT_SetThisControl( WTtype, WT_CONTROL_DDD );
+ if ( ( workchar = strchr( buf, '"' ) ) != NULL )
+ {
+ wtsetcatdesc( "ddd", workchar, WT_CONTROL_DDD, FALSE );
+ }
+ }
+ }
+ else if ( strcmp( parm1, "uncatpersonal") == 0 )
+ {
+ if ( strcmp( parm2, "forbid" ) == 0 )
+ {
+ WT_SetThisControl( WTtype, WT_CONTROL_UNCATPERSONAL );
+ if ( ( workchar = strchr( buf, '"' ) ) != NULL )
+ {
+ wtsetcatdesc( "ucp", workchar, WT_CONTROL_UNCATPERSONAL, FALSE );
+ }
+ }
+ }
+ else if ( strcmp( parm1, "errortext") == 0 )
+ {
+ workint = strlen( &buf[10] ) + 1; /* Len of line past errortext */
+ WTerrtext = calloc( 1, workint );
+ strcpy( WTerrtext, &buf[10] );
+ }
+ else if ( strcmp( parm1, "errorfile") == 0 )
+ {
+ workint = strlen( &buf[10] ) + 1; /* Len of line past errorfile */
+ WTerrfile = calloc( 1, workint );
+ strcpy( WTerrfile, &buf[10] );
+ }
+ else if ( strlen(buf) > 2 && buf[0] != '#' ) {
+ debug(61, 0, "SmartFilter init: unknown config: %s\n", buf);
+ }
+ }
+ fclose(f); /* finished reading configuration file */
+ if ( strlen( cntlf ) == 0 )
+ {
+ debug(61, 0, "SmartFilter init: Control List not specified\n");
+ smartfilter_free();
+ return -1;
+ }
+ debug(61, 5, "SmartFilter init: Control List is %s\n", cntlf);
+ if ( (workint = WT_LoadControlList( WTserv, WTtype, cntlf )) != 0 )
+ {
+ if ( workint == WTERROLD )
+ {
+ debug(61, 1, "SmartFilter init Warning: Control List is Old\n");
+ }
+ else
+ {
+ if ( workint == WTERREXPIRED )
+ {
+ debug(61, 0, "SmartFilter init: Control List Expired\n");
+ WTexpired = TRUE;
+ }
+ else
+ {
+ debug(61, 0, "SmartFilter init: Unable to load Control List\n");
+ }
+ smartfilter_free();
+ return -1;
+ }
+ }
+ debug(61, 5, "SmartFilter init: Control List loaded OK\n");
+
+ if ( strlen( dnrfile ) > 0 )
+ {
+ debug(61, 5, "SmartFilter init: Resolved List is %s\n", dnrfile);
+
+ /* If loading DNR file dont do dotted decimal stuff */
+ if ( (workint = WT_LoadDomainResolvedList( WTserv, WTtype, dnrfile )) != 0 )
+ {
+ if ( workint == WTERROLD )
+ {
+ debug(61, 1, "SmartFilter init Warning: Resolved List is Old\n");
+ WT_ClearThisControl( WTtype, WT_CONTROL_DDD );
+ }
+ else
+ {
+ if ( workint == WTERREXPIRED )
+ {
+ debug(61, 0, "SmartFilter init: Resolved List Expired\n");
+ }
+ else
+ {
+ debug(61, 0, "SmartFilter init: Unable to load Resolved List\n");
+ }
+ }
+ }
+ else
+ {
+ WT_ClearThisControl( WTtype, WT_CONTROL_DDD );
+ }
+ }
+ if ( strlen( sitef ) > 0 )
+ {
+ debug(61, 5, "SmartFilter init: Site List is %s\n", sitef);
+ if ( wtloadsitelist( WTserv, sitef ) != TRUE )
+ {
+ debug(61, 0, "SmartFilter init: Unable to load Site File\n");
+ smartfilter_free();
+ return -1;
+ }
+ }
+
+ if ( WTerrfile != NULL ) {
+ if ( (WTcustom_errtext = load_custom_error_file ( WTerrfile )) == NULL ) {
+ debug(61, 0, "SmartFilter init: unable to load error file %s\n", WTerrfile);
+ }
+ debug(61, 5, "SmartFilter init: loaded error file %s\n", WTerrfile);
+ }
+
+ debug(61, 0, "SmartFilter init: Initialized and enabled\n");
+ return 0;
+}
+
+#define SMARTFILTER_DENIAL_HEADER "\
+HTTP/1.0 %d ERROR: Access Denied by Site Administrator\r\nContent-type: text/html\r\n\r\n"
+
+char categorizedUrl[MAX_LINE];
+
+/* check the URL with SmartFilter, returns URL_ALLOWED or URL_DISALLOWED */
+int smartfilter_check_url( int fd, void * data)
+{
+ icpStateData *icpState = data;
+ char *wbuf = NULL;
+ char *errtext;
+ int retcode;
+ WT_TYPES WTtmp = WT_NULLPARM;
+
+ if ( WTexpired ) {
+ if ( ( WTfailcnt == 0 ) || ( (WTfailcnt % 1000 ) == 0 ) ) {
+ debug(61, 5, "SmartFilter: smartfilter_check_url: Control List has expired\n");
+ }
+ WTfailcnt++;
+ return URL_ALLOWED;
+ }
+
+ if(!WTserv) {
+ /* Init not done, let it go */
+ debug(61, 5, "SmartFilter: smartfilter_check_url: not initialized\n");
+ return URL_ALLOWED;
+ }
+
+ debug(61, 5, "SmartFilter: smartfilter_check_url: url is %s\n", icpState->url);
+
+ WTtmp = clientdbGetCats(icpState->acct_addr);
+ if (WTtmp == WT_NULLPARM) WTtmp = WTtype; /* start with the default policy */
+
+ if ( ( retcode = WT_CategorizeUrl (WTserv, icpState->url, WTcat,
+ categorizedUrl, MAX_LINE )) == WTFOUND ) {
+ /* URL Found in list */
+ if ( WT_TestThisControl(WTcat, WT_CONTROL_EXEMPT) == WTISSET ) {
+ /* Site is exempt */
+ debug(61, 5, "SmartFilter: smartfilter_check_url: exempted\n");
+ return URL_ALLOWED;
+ }
+ if ( WT_CategoryAndCategory( WTtmp, WTcat, WTwork ) != WTISSET ) {
+ debug(61, 5, "SmartFilter: smartfilter_check_url: not this category\n");
+ return URL_ALLOWED;
+ }
+ else {
+ /* We use code 403 for denials; not 400, and not 200. The RFC says:
+ * RFC 2068, Hypertext Transfer Protocol -- HTTP/1.1, January 1997
+ * 403 Forbidden
+ * The server understood the request, but is refusing to fulfill it.
+ * Authorization will not help and the request SHOULD NOT be repeated.
+ */
+ icpState->http_code = 403;
+
+ if (WTcustom_errtext != NULL) {
+ sprintf(tmp_error_buf,
+ SMARTFILTER_DENIAL_HEADER,
+ icpState->http_code);
+ errtext = tmp_error_buf + strlen(tmp_error_buf);
+ errtext = wtmakeerr (TRUE, WTwork, WTcustom_errtext, errtext);
+ wbuf = tmp_error_buf; /* send the custom error file */
+ }
+ else {
+ errtext = wtmakeerr (TRUE, WTwork, WTerrtext, err_message);
+ wbuf = default_error_msg(icpState->http_code, icpState->method,
+ icpState->url, fd_table[fd].ipaddr, errtext);
+ }
+ debug(61, 5, "SmartFilter: smartfilter_check_url: blocked due to %s\n", errtext);
+ icpSendERROR(fd, LOG_TCP_DENIED, wbuf, icpState, icpState->http_code);
+ return URL_DISALLOWED;
+ }
+ }
+ else {
+ if ( retcode == WTERREXPIRED ) {
+ WTexpired = TRUE;
+ debug(61, 5, "SmartFilter: smartfilter_check_url: Control List is Expired\n");
+ }
+ debug(61, 5, "SmartFilter: smartfilter_check_url: allowed\n");
+ return URL_ALLOWED;
+ }
+}
+
+/* stat the file to see how big it is, malloc a buffer that size, read file into buf */
+static char *load_custom_error_file (char *filepath)
+{
+ int fd;
+ char *buf;
+ struct stat filestats;
+
+ if (stat(filepath, &filestats) < 0) {
+ debug(61, 0, "SmartFilter: Unable to stat custom error file %s\n", filepath);
+ return NULL;
+ }
+ if ((fd = open ( filepath, O_RDONLY)) == -1) {
+ debug(61, 0, "SmartFilter: Unable to open custom error file %s\n", filepath);
+ return NULL;
+ }
+ debug(61, 5, "SmartFilter: load_custom_error_file: file is %s, size %d\n",
+ filepath, filestats.st_size);
+ if ((buf = (char*) malloc(filestats.st_size)) == NULL) {
+ debug(61, 0, "SmartFilter: failed to malloc %d bytes for error file\n", filestats.st_size);
+ return NULL;
+ }
+ if (read(fd, buf, filestats.st_size) != filestats.st_size) {
+ debug(61, 0, "SmartFilter: failed to read custom error file\n");
+ return NULL;
+ }
+ return buf;
+}
+
+/* generate an error screen based on the src ip and err_message */
+static char * default_error_msg(int code, int method, const char *url, const char *client,const char *reason)
+{
+ sprintf(tmp_error_buf,
+ SMARTFILTER_DENIAL_HEADER
+ "ERROR: Access Denied by Site Administrator\n"
+ "ERROR: Access Denied by Site Administrator
\n"
+ "Sorry, you are not currently allowed to request:\n"
+ "
%s
\n"
+ "From: %s\n"
+ "
Reason:
\n"
+ "
%s
\n"
+ "Please contact the administrator\n"
+ "if you believe this is incorrect.\n"
+ "%s\n"
+ "
\nGenerated by %s/%s@%s\n\n",
+ code, categorizedUrl, client, reason, Config.adminEmail, Config.errHtmlText,
+ appname, version_string, getMyHostname());
+ return tmp_error_buf;
+}
diff -urN squid-1.1.17/src/smartfilter_squid.h squid/src/smartfilter_squid.h
--- squid-1.1.17/src/smartfilter_squid.h Thu Jan 1 08:00:00 1970
+++ squid/src/smartfilter_squid.h Wed Jun 3 15:22:12 1998
@@ -0,0 +1,23 @@
+
+/*
+ * Smartfilter Plugin for Squid Proxy Server
+ *
+ *
+ * Copyright 1996-98 - Secure Computing Corp.
+ *
+ * This software is covered under terms of a
+ * non-disclosure agreement.
+ *
+ */
+
+#include "webtrack.h"
+
+#define URL_ALLOWED 1
+#define URL_DISALLOWED 2
+
+extern void smartfilter_free();
+extern int smartfilter_init();
+extern int smartfilter_check_url(int fd, void *data);
+extern void wtsetcats(WT_TYPES *WTtype, char *parm2);
+extern char *wtgetcats(WT_TYPES *WTtype, char *buf);
+
diff -urN squid-1.1.17/src/squid.conf.pre.in squid/src/squid.conf.pre.in
--- squid-1.1.17/src/squid.conf.pre.in Fri Aug 8 00:00:00 1997
+++ squid/src/squid.conf.pre.in Tue Jun 2 16:07:29 1998
@@ -2,6 +2,9 @@
#
# $Id: squid.conf.pre.in,v 1.93.2.13 1997/08/07 20:38:02 wessels Exp $
#
+#
+smartfilter_state on
+smartfilter_config /usr/local/squid/etc/smartfilter.conf
# TAG: http_port
# The port number where squid will listen for HTTP client
diff -urN squid-1.1.17/src/squid.h squid/src/squid.h
--- squid-1.1.17/src/squid.h Sun Jun 1 00:00:00 1997
+++ squid/src/squid.h Tue Jun 2 15:42:52 1998
@@ -64,6 +64,10 @@
#define FD_SETSIZE SQUID_MAXFD
#endif
+#ifdef SMARTFILTER
+#include "smartfilter_squid.h"
+#endif
+
#if HAVE_UNISTD_H
#include
#endif
diff -urN squid-1.1.17/src/stat.c squid/src/stat.c
--- squid-1.1.17/src/stat.c Fri Aug 22 03:29:00 1997
+++ squid/src/stat.c Tue Oct 21 14:04:00 1997
@@ -151,7 +151,7 @@
static void proto_newobject _PARAMS((cacheinfo *, protocol_t, int, int));
static void proto_purgeobject _PARAMS((cacheinfo *, protocol_t, int));
static void proto_touchobject _PARAMS((cacheinfo *, protocol_t, int));
-static void server_list _PARAMS((const cacheinfo *, StoreEntry *));
+static void server_list _PARAMS((const cacheinfo *, StoreEntry *, char *extrainfo));
static void squidReadEndHandler _PARAMS((int, int, squid_read_data_t *));
static void squid_get_start _PARAMS((const cacheinfo *, StoreEntry *));
static void statFiledescriptors _PARAMS((StoreEntry *));
@@ -548,11 +548,19 @@
}
static void
-server_list(const cacheinfo * obj, StoreEntry * sentry)
+server_list(const cacheinfo * obj, StoreEntry * sentry, char *extrainfo)
{
peer *e = NULL;
struct _domain_ping *d = NULL;
icp_opcode op;
+ unsigned long http_tot=0,icp_tot=0,
+ last_http_tot=0,last_icp_tot=0,
+ last_direct=0,direct=0,reset=0;
+
+ if (extrainfo && *extrainfo=='-') {
+ extrainfo++;
+ reset=1;
+ }
storeAppendPrintf(sentry, open_bracket);
@@ -561,6 +569,10 @@
for (e = getFirstPeer(); e; e = getNextPeer(e)) {
if (e->host == NULL)
fatal_dump("Found an peer without a hostname!");
+ http_tot+=e->stats.v_fetches;
+ icp_tot +=e->stats.v_icp;
+ last_http_tot+=e->last_stats.v_fetches;
+ last_icp_tot +=e->last_stats.v_icp;
storeAppendPrintf(sentry, "\n{%-11.11s: %s/%d/%d}\n",
neighborTypeStr(e),
e->host,
@@ -574,9 +586,16 @@
storeAppendPrintf(sentry, "{PINGS ACKED: %8d %3d%%}\n",
e->stats.pings_acked,
percent(e->stats.pings_acked, e->stats.pings_sent));
- storeAppendPrintf(sentry, "{FETCHES : %8d %3d%%}\n",
+ storeAppendPrintf(sentry, "{ICP Vol : %8lu Kb %8lu Kb}\n",
+ e->last_stats.v_icp + (e->stats.v_icp/1000),
+ e->stats.v_icp/1000);
+ storeAppendPrintf(sentry, "{FETCHES : %8d %8d %3d%%}\n",
+ e->last_stats.fetches + e->stats.fetches,
e->stats.fetches,
percent(e->stats.fetches, e->stats.pings_acked));
+ storeAppendPrintf(sentry, "{FETCH Vol : %8lu KB %8lu Kb}\n",
+ e->last_stats.v_fetches + (e->stats.v_fetches/1000),
+ e->stats.v_fetches/1000);
storeAppendPrintf(sentry, "{IGNORED : %8d %3d%%}\n",
e->stats.ignored_replies,
percent(e->stats.ignored_replies, e->stats.pings_acked));
@@ -601,7 +620,30 @@
storeAppendPrintf(sentry, "!%s ", d->domain);
}
storeAppendPrintf(sentry, close_bracket); /* } */
- }
+ if (reset) {
+ e->last_stats.v_icp +=e->stats.v_icp/1000;
+ e->last_stats.v_fetches+=e->stats.v_fetches/1000;
+ e->last_stats.fetches +=e->stats.fetches;
+ e->stats.v_icp=0;
+ e->stats.v_fetches=0;
+ e->stats.fetches=0;
+ }
+ }
+ GetLastIntakeVolume(&last_direct,&last_http_tot,&last_icp_tot);
+ GetIntakeVolume(&direct,&http_tot,&icp_tot,reset);
+ icp_tot/=1000;
+ http_tot/=1000;
+ direct/=1000;
+ storeAppendPrintf(sentry, "{}\n{}\n");
+ storeAppendPrintf(sentry, "{Total Parent volume: ICP: %10lu Kb %10lu Kb}\n",
+ last_icp_tot+icp_tot, icp_tot);
+ storeAppendPrintf(sentry, "{ :HTTP: %10lu Kb %10lu Kb}\n",
+ last_http_tot+http_tot, http_tot);
+ storeAppendPrintf(sentry, "{Direct Volume : %10lu Kb %10lu Kb}\n",
+ last_direct+direct, direct);
+ storeAppendPrintf(sentry, "{Total Cache Volume : %10lu Kb %10lu Kb}\n",
+ last_icp_tot+icp_tot + last_http_tot+http_tot + last_direct+direct,
+ icp_tot+http_tot+direct);
storeAppendPrintf(sentry, close_bracket);
}
diff -urN squid-1.1.17/src/stat.h squid/src/stat.h
--- squid-1.1.17/src/stat.h Fri Jun 6 00:00:00 1997
+++ squid/src/stat.h Tue Oct 21 14:04:00 1997
@@ -167,7 +167,7 @@
/* get a parameter object */
void (*parameter_get) (const struct _cacheinfo * c, StoreEntry * sentry);
- void (*server_list) (const struct _cacheinfo * c, StoreEntry * sentry);
+ void (*server_list) (const struct _cacheinfo * c, StoreEntry * sentry, char *extrainfo);
/* get a total bytes for object in cache */
diff -urN squid-1.1.17/src/store.c squid/src/store.c
--- squid-1.1.17/src/store.c Sat Oct 18 07:22:00 1997
+++ squid/src/store.c Tue Oct 21 20:57:00 1997
@@ -990,6 +990,7 @@
store_mem_size += len;
mem->data->mem_append(mem->data, data, len);
mem->e_current_len += len;
+ if (e->mem_status != SWAPPING_IN) neighborUpdateVol(&mem->source,0,len);
}
if (e->store_status != STORE_ABORTED && !BIT_TEST(e->flag, DELAY_SENDING))
InvokeHandlers(e);
@@ -1128,6 +1129,8 @@
storeSwapFullPath(e->swap_file_number, NULL));
debug(20, 0, " --> Only read %d bytes\n",
mem->e_current_len);
+ debug(20, 0, " Marking entry for release....\n");
+ BIT_SET(e->flag, RELEASE_REQUEST);
}
e->lock_count++; /* lock while calling handler */
InvokeHandlers(e); /* once more after mem_status state change */
diff -urN squid-1.1.17/src/store.h squid/src/store.h
--- squid-1.1.17/src/store.h Fri Aug 8 00:00:00 1997
+++ squid/src/store.h Tue Oct 21 14:04:00 1997
@@ -1,7 +1,4 @@
-
-
-
/*
* $Id: store.h,v 1.80.2.9 1997/08/07 22:48:57 wessels Exp $
*
@@ -187,6 +184,7 @@
int e_lowest_offset;
struct _store_client *clients;
int nclients;
+ struct in_addr source;
u_num32 swap_offset;
@@ -335,3 +333,4 @@
extern unsigned long store_mem_size;
#endif
+
diff -urN squid-1.1.17/src/tools.c squid/src/tools.c
--- squid-1.1.17/src/tools.c Fri Aug 22 03:33:00 1997
+++ squid/src/tools.c Tue Jun 2 17:23:27 1998
@@ -502,10 +502,16 @@
if (geteuid() != 0)
return;
/* Started as a root, check suid option */
- if (Config.effectiveUser == NULL)
+
+ if (Config.effectiveUser == NULL) {
+ debug(0,0, "Effective user not defined%s\n", "");
return;
- if ((pwd = getpwnam(Config.effectiveUser)) == NULL)
+ }
+ if ((pwd = getpwnam(Config.effectiveUser)) == NULL) {
+ debug(0,0, "Effective UID not valid!%s\n", "");
+ debug(0,0, "User %s not valid\n", Config.effectiveUser);
return;
+ }
if (Config.effectiveGroup && (grp = getgrnam(Config.effectiveGroup))) {
if (setgid(grp->gr_gid) < 0)
debug(50, 1, "leave_suid: setgid: %s\n", xstrerror());
diff -urN squid-1.1.17/src/url.c squid/src/url.c
--- squid-1.1.17/src/url.c Wed Jul 30 00:00:00 1997
+++ squid/src/url.c Tue Oct 21 21:42:00 1997
@@ -191,6 +191,17 @@
}
}
+/* ok, i THINK it's the trashed URLs in requets that are killing my squid... */
+/* watch out for em, and scrap em */
+
+int valid_url(char *url)
+{ unsigned char *p=url;
+ if (!p) return 0;
+ while (*p>31 && *p<0x7F) p++;
+ if (*p) return 0;
+ return 1;
+}
+
request_t *
urlParse(method_t method, char *url)
{
@@ -205,6 +216,11 @@
int l;
proto[0] = host[0] = urlpath[0] = login[0] = '\0';
+ if (!valid_url(url)) {
+ debug(23, 0, "urlParse: eek! toasted URL! %s\n",url);
+ return NULL;
+ }
+
if ((l = strlen(url)) + Config.appendDomainLen > (MAX_URL - 1)) {
/* terminate so it doesn't overflow other buffers */
*(url + (MAX_URL >> 1)) = '\0';
@@ -216,9 +232,16 @@
if (sscanf(url, "%[^:]:%d", host, &port) < 1)
return NULL;
} else {
- if (sscanf(url, "%[^:]://%[^/]%s", proto, host, urlpath) < 2)
- return NULL;
- protocol = urlParseProtocol(proto);
+ if (sscanf(url, "%[^:]://%[^/]%s", proto, host, urlpath) < 2)
+ { if (url[0]=='/') url++;
+ if (sscanf(url, "%[^/]%s", host, urlpath)<1)
+ return NULL;
+ if (strncasecmp(host,"www.",4)==0) strcpy(proto,"http");
+ else if (strncasecmp(host,"ftp.",4)==0) strcpy(proto,"ftp");
+ else if (strncasecmp(host,"gopher.",7)==0) strcpy(proto,"gopher");
+ else strcpy(proto,"http");
+ }
+ protocol = urlParseProtocol(proto);
port = urlDefaultPort(protocol);
/* Is there any login informaiton? */
if ((t = strrchr(host, '@'))) {
@@ -304,6 +327,8 @@
request->urlpath);
break;
}
+ if (!valid_url(buf))
+ debug(23, 0, "urlCanonical: eek! we toasted a URL!\n");
return buf;
}
diff -urN squid-1.1.17/src/webtrack.h squid/src/webtrack.h
--- squid-1.1.17/src/webtrack.h Thu Jan 1 08:00:00 1970
+++ squid/src/webtrack.h Tue Jun 2 15:42:49 1998
@@ -0,0 +1,338 @@
+
+ /***********************************************************************
+ * *
+ * WebTrack(tm) API Library *
+ * *
+ * Copyright 1996-97 - Webster Network Strategies, Inc. *
+ * *
+ * *
+ * *
+ ***********************************************************************/
+
+
+/* Define for exports */
+#if defined(WIN32) || defined(WNSNLM)
+#define WNS_PUBLIC __declspec(dllexport)
+#else
+#define WNS_PUBLIC extern
+#endif
+
+/* Linkage Definition */
+#ifdef WNSOS2
+#define WNS_LINKAGE _System
+#else
+#define WNS_LINKAGE
+#endif
+
+#define WTRESTRICT 1
+#define WTEXEMPT 2
+#define WTNORMAL 3
+#define WTDISABLE 4
+#define WTENABLE 5
+#define WTALLOW 6
+#define WTALLOWOFF 7
+#define WTDISALLOW 8
+#define WTRESOLVE 9
+#define WTISSET 10
+#define WTNOTSET 11
+#define WTFOUND 12
+#define WTFOUNDTRUNC 13
+#define WTNOTFOUND 14
+#define WTNORESTRICT 15
+
+/* ERROR CODES */
+#define WTERRBASE 1000
+#define WTERROK 0
+#define WTERRIO 1+WTERRBASE
+#define WTERRTRUNC 2+WTERRBASE
+#define WTERROPEN 3+WTERRBASE
+#define WTERRINVHANDLE 4+WTERRBASE
+#define WTERRNULL 5+WTERRBASE
+#define WTERRINVCATEGORY 6+WTERRBASE
+#define WTERRINVCNTL 7+WTERRBASE
+#define WTERRNOSTORE 8+WTERRBASE
+#define WTERRINVALID 9+WTERRBASE
+#define WTERRINVURL 10+WTERRBASE
+#define WTERRNOSITE 11+WTERRBASE
+#define WTERROLD 12+WTERRBASE
+#define WTERREXPIRED 13+WTERRBASE
+#define WTERRDNS 14+WTERRBASE
+
+/* DATA TYPES */
+typedef void *WT_TYPES;
+typedef void *WT_SERVICE;
+typedef unsigned char WT_TYPEAREA[32];
+#define WT_NULLPARM ( (void *) 0 )
+typedef unsigned char WT_BIZHOURS[7][24];
+typedef enum {
+ WT_CAT_SEX = 1,
+ WT_CAT_DRUGS,
+ WT_CAT_HATESPEECH,
+ WT_CAT_CRIME,
+ WT_CAT_WORTHLESS,
+ WT_CAT_SALES,
+ WT_CAT_GAMBLING,
+ WT_CAT_PERSONAL,
+ WT_CAT_JOBS,
+ WT_CAT_SPORTS,
+ WT_CAT_GAMES,
+ WT_CAT_HUMOR,
+ WT_CAT_ALTJRNL,
+ WT_CAT_ENTERTAIN,
+ WT_CAT_LIFESTYLE,
+ WT_CAT_EXTREME,
+ WT_CAT_CHAT, /* Chat Gateway */
+ WT_CAT_INVESTMENTS, /* Investing Information */
+ WT_CAT_GNEWS, /* General News */
+ WT_CAT_OPINION, /* Politics, Opinion, Religion */
+ WT_CAT_DATING, /* Dating and Introduction Service */
+ WT_CAT_ART, /* Art and Culture */
+ WT_CAT_CULT, /* Cult/Occult */
+ WT_CAT_NEWSSITE, /* UseNet News Site on Web */
+ WT_CAT_SELFHELP, /* Self Help */
+ WT_CAT_TRAVEL, /* Travel */
+ WT_CAT_NONESSENTIAL /* Site Defined */
+ } WT_CATEGORY_SPECIFIC;
+
+typedef enum {
+ WT_CONTROL_EXEMPT = 1,
+ WT_CONTROL_RESTRICT,
+ WT_CONTROL_DDD,
+ WT_CONTROL_UNCATPERSONAL,
+ WT_CONTROL_NEWSBACK,
+ WT_CONTROL_UNAPPROVED,
+ WT_CONTROL_RESTRICTEDWORD,
+ WT_CONTROL_RESTRICTEDSEARCH,
+ WT_CONTROL_LOCAL,
+ WT_CONTROL_SITE,
+ WT_CONTROL_PATH,
+ WT_CONTROL_URL,
+ WT_CONTROL_BIZHOURS,
+ WT_CONTROL_CGI,
+ WT_CONTROL_RESOLVE,
+ WT_CONTROL_RESTRICTEDFILE
+ } WT_CONTROL_SPECIFIC;
+
+/*
+ * Defines for WT_TypeToBit function
+ */
+#define WT_BIT_NONESSENTIAL 0x1
+#define WT_BIT_ALTJRNL 0x2
+#define WT_BIT_ART 0x4
+#define WT_BIT_CHAT 0x8
+#define WT_BIT_CRIME 0x10
+#define WT_BIT_CULT 0x20
+#define WT_BIT_DATING 0x40
+#define WT_BIT_ENTERTAIN 0x80
+#define WT_BIT_EXTREME 0x100
+#define WT_BIT_GAMES 0x200
+#define WT_BIT_GNEWS 0x400
+#define WT_BIT_HATESPEECH 0x800
+#define WT_BIT_HUMOR 0x1000
+#define WT_BIT_DRUGS 0x2000
+#define WT_BIT_INVESTMENTS 0x4000
+#define WT_BIT_JOBS 0x8000
+#define WT_BIT_WORTHLESS 0x10000
+#define WT_BIT_GAMBLING 0x20000
+#define WT_BIT_SALES 0x40000
+#define WT_BIT_LIFESTYLE 0x80000
+#define WT_BIT_PERSONAL 0x100000
+#define WT_BIT_OPINION 0x200000
+#define WT_BIT_SELFHELP 0x400000
+#define WT_BIT_SEX 0x800000
+#define WT_BIT_SPORTS 0x1000000
+#define WT_BIT_TRAVEL 0x2000000
+#define WT_BIT_NEWSSITE 0x4000000
+
+
+
+ /* Initialize environment */
+ WNS_PUBLIC WT_TYPES WNS_LINKAGE WT_Init();
+
+ /* Free environment */
+ WNS_PUBLIC int WNS_LINKAGE WT_FreeService( WT_SERVICE );
+
+ /* Set IP Address Option On */
+ WNS_PUBLIC int WNS_LINKAGE WT_SetIPOption( WT_SERVICE , int);
+
+ /* Set Notify Old List on caturl Option On */
+ WNS_PUBLIC int WNS_LINKAGE WT_SetOldOption( WT_SERVICE, int);
+
+ /* Init Category Flags Object storage */
+ WNS_PUBLIC void WNS_LINKAGE WT_InitTypeArea( void * );
+
+ /* Obtain Category Flags Object */
+ WNS_PUBLIC WT_TYPES WNS_LINKAGE WT_AllocateTypes( void );
+
+ /* Free Category Flags Object */
+ WNS_PUBLIC int WNS_LINKAGE WT_FreeTypes( WT_TYPES );
+
+ /* Clear The Category Flags Object */
+ WNS_PUBLIC int WNS_LINKAGE WT_ClearTypes( WT_TYPES );
+
+ /* Convert Category Flags Category info to bit string */
+ WNS_PUBLIC unsigned long WNS_LINKAGE WT_TypeToBit( WT_TYPES );
+
+ /* Clear A Specific Category Flags Indicator */
+ WNS_PUBLIC int WNS_LINKAGE WT_ClearThisCategory( WT_TYPES,
+ WT_CATEGORY_SPECIFIC );
+
+ /* Set All Category Flags Indicator */
+ WNS_PUBLIC int WNS_LINKAGE WT_SetAllCategory( WT_TYPES );
+
+ /* Set A Specific Category Flags Indicator */
+ WNS_PUBLIC int WNS_LINKAGE WT_SetThisCategory( WT_TYPES,
+ WT_CATEGORY_SPECIFIC );
+
+ /* Test A Specific Category Flags Indicator */
+ WNS_PUBLIC int WNS_LINKAGE WT_TestThisCategory( WT_TYPES,
+ WT_CATEGORY_SPECIFIC );
+
+ /* Test A Set of Specific Category Flags Indicators */
+ WNS_PUBLIC int WNS_LINKAGE WT_CategoryAndCategory( WT_TYPES,
+ WT_TYPES,
+ WT_TYPES );
+
+ /* Set All Control Flags Indicator */
+ WNS_PUBLIC int WNS_LINKAGE WT_SetAllControl( WT_TYPES );
+
+ /* Clear A Specific Control Flags Indicator */
+ WNS_PUBLIC int WNS_LINKAGE WT_ClearThisControl( WT_TYPES,
+ WT_CONTROL_SPECIFIC );
+
+ /* Set A Specific Control Flags Indicator */
+ WNS_PUBLIC int WNS_LINKAGE WT_SetThisControl( WT_TYPES,
+ WT_CONTROL_SPECIFIC );
+
+ /* Test A Specific Control Flags Indicator */
+ WNS_PUBLIC int WNS_LINKAGE WT_TestThisControl( WT_TYPES,
+ WT_CONTROL_SPECIFIC );
+
+ /* Test A Set of Specific Control Flags Indicators */
+ WNS_PUBLIC int WNS_LINKAGE WT_ControlAndControl( WT_TYPES,
+ WT_TYPES,
+ WT_TYPES );
+
+ /* Test A Set of Specific Control Flags Indicators */
+ WNS_PUBLIC int WNS_LINKAGE WT_ControlOrControl( WT_TYPES,
+ WT_TYPES,
+ WT_TYPES );
+
+ /* Check URL against WebTrack Control List */
+ WNS_PUBLIC int WNS_LINKAGE WT_CategorizeUrl( WT_SERVICE,
+ char *,
+ WT_TYPES,
+ char *,
+ int
+ );
+
+ /* Set Shared Memory Routine Addresses */
+ WNS_PUBLIC int WNS_LINKAGE WT_SharedMemRoutines( WT_SERVICE,
+ void *,
+ void *(*getroutine)( void *, char *, long),
+ void (*freeroutine)( void *, char *, void *)
+ );
+
+ /* Set Mapped File Routine Addresses */
+ WNS_PUBLIC int WNS_LINKAGE WT_MappedFileRoutines( WT_SERVICE,
+ void *,
+ void *(*maproutine)( void *, char *, char *),
+ void (*unmaproutine)( void *, char *, void *)
+ );
+
+ /* Load WebTrack Control List */
+ WNS_PUBLIC int WNS_LINKAGE WT_LoadControlList( WT_SERVICE,
+ WT_TYPES,
+ char *
+ );
+
+ /* Load Domain Resolved Control List */
+ WNS_PUBLIC int WNS_LINKAGE WT_LoadDomainResolvedList( WT_SERVICE,
+ WT_TYPES,
+ char *
+ );
+
+ /* Get WebTrack Control List Status*/
+ WNS_PUBLIC int WNS_LINKAGE WT_ControlListStatus( WT_SERVICE );
+
+ /* Get WebTrack Control List Age*/
+ WNS_PUBLIC int WNS_LINKAGE WT_ControlListAge( WT_SERVICE , long *);
+
+ /* Get WebTrack Resolved Control List Age*/
+ WNS_PUBLIC int WNS_LINKAGE WT_ResolvedListAge( WT_SERVICE , long *);
+
+ /* Get WebTrack Resolved Control List Status*/
+ WNS_PUBLIC int WNS_LINKAGE WT_ResolvedListStatus( WT_SERVICE );
+
+
+ /* Update WebTrack Site Specific Control List */
+ WNS_PUBLIC int WNS_LINKAGE WT_UpdateSiteList( WT_SERVICE,
+ char *,
+ WT_TYPES
+ );
+
+
+ /* WebTrack Environment Built-In Function Calls */
+
+ /* Check URL against WebTrack Environment */
+ WNS_PUBLIC int WNS_LINKAGE WT_Env_UrlCheck( WT_SERVICE,
+ char *,
+ char *,
+ WT_TYPES,
+ WT_TYPES,
+ WT_TYPES
+ );
+
+ /* Set WebTrack Business Hours Option */
+ WNS_PUBLIC int WNS_LINKAGE WT_Env_SetBusinessHours( WT_SERVICE,
+ WT_BIZHOURS *
+ );
+
+ /* Set WebTrack Category Restrictions */
+ WNS_PUBLIC int WNS_LINKAGE WT_Env_RegularRestrictions( WT_SERVICE,
+ WT_TYPES,
+ int
+ );
+
+ /* Set WebTrack Non-Business Hours Category Restrictions */
+ WNS_PUBLIC int WNS_LINKAGE WT_Env_NonBusinessRestrictions( WT_SERVICE,
+ WT_TYPES,
+ int
+ );
+
+ /* Set WebTrack News Back Door Processing Option */
+ WNS_PUBLIC int WNS_LINKAGE WT_Env_NewsBackDoor( WT_SERVICE,
+ char *,
+ char *,
+ int
+ );
+
+ /* Set WebTrack Search Site Processing Option */
+ WNS_PUBLIC int WNS_LINKAGE WT_Env_SearchSite( WT_SERVICE,
+ char *,
+ char *,
+ int
+ );
+
+ /* Set WebTrack Restricted Search Word Processing Option */
+ WNS_PUBLIC int WNS_LINKAGE WT_Env_RestrictedSearchWord( WT_SERVICE,
+ char *,
+ WT_TYPES,
+ int
+ );
+
+ /* Set WebTrack Exempted Domain Processing Option */
+ WNS_PUBLIC int WNS_LINKAGE WT_Env_ExemptedDomain( WT_SERVICE,
+ char *,
+ int
+ );
+
+ /* Set WebTrack Forbidden File Type Processing Option */
+ WNS_PUBLIC int WNS_LINKAGE WT_Env_ForbidFileType( WT_SERVICE,
+ char *,
+ int
+ );
+
+ /* Parse a URL */
+ WNS_PUBLIC int WNS_LINKAGE WT_ParseUrl( char *, char *);
+