diff -r -d -u -N squid-1.1.22/README.MIME_INTERCEPT squid-1.1.22-mint/README.MIME_INTERCEPT
--- squid-1.1.22/README.MIME_INTERCEPT	Thu Jan  1 01:00:00 1970
+++ squid-1.1.22-mint/README.MIME_INTERCEPT	Sun Aug  2 13:00:50 1998
@@ -0,0 +1,67 @@
+If you have a fast internet connection, users tend to abuse it -
+for loading large pictures, listening to real audio streams and other
+bandwidth- and money-wasting activities. Denying special user agents like
+"RealPlayer" helps only until the next player appears, disabling images
+makes many sites unusable.
+
+The solution is filtering and bandwidth limiting on mime type after the
+connection has been established. The mime intercept patch adds this feature
+to the squid cache. After installing, you get a new configuration keyword:
+
+mime_intercept regex free_bytes bytes_sec
+
+regex allows you to specify a regular expression that is matched on the mime
+type, free_bytes is the number of bytes that will be transferred without
+delay, bytes_sec contains the number of bytes that will be transferred per
+second after free_bytes is exhausted. Multiple mime_intercept lines will
+be interpreted bottom to top, so put the most exact expression at the end.
+An unknown mime type will be transferred without delay.
+
+Example:
+
+mime_intercept ^audio/.*$ 8192 512
+mime_intercept ^image/.*$ 32768 4096
+mime_intercept ^image/jpeg$ 16384 1024
+
+All images will be limited to 4K/sec after 32K has been transferred except
+JPEGs. Here you get 1K/sec after 16K. Audio files will almost get stuck
+within the cable at 512 Bytes/sec. Everything else is left alone.
+
+
+Caveats and TODOs:
+
+-This is *ALPHA* stuff! The code comes without any warranties, so use at
+ your own risk. Look at the GNU public license for further information.
+
+-Allow aborting a transfer by setting bytes_sec to zero. I don't know if
+ it is safe to call comm_close within icpSendMoreData, I have to try.
+
+-Better integration into squid.
+
+-Squid starts delaying the connected server after the client is about 300K
+ back. So the cache won't be a nice internet citizen if users insist on
+ downloading large files with a low bytes_sec. Anyway, those people
+ penetrating the net with real audio shit deserve it. ;-)
+
+-Squid cannot determine the mime type of very small files, so my patch cannot
+ kick in here. This shouldn't be an issue.
+
+-Don't set bytes_sec too low. Squid cannot realize that a client has
+ aborted when it does not send data.
+
+-You might need more filedescriptors as connections stay active for a longer
+ period.
+
+-Don't trust me. Try to understand what I coded.
+
+The primary site of this patch is http://techwww.telemation.de/bofh/. You
+can reach me via email at srompf@telemation.de. Hope this software is
+useful for somebody.
+
+Stefan
+
+
+
+
+
+
diff -r -d -u -N squid-1.1.22/src/Makefile.in squid-1.1.22-mint/src/Makefile.in
--- squid-1.1.22/src/Makefile.in	Thu Jun 25 19:15:29 1998
+++ squid-1.1.22-mint/src/Makefile.in	Sat Aug  1 16:46:38 1998
@@ -20,13 +20,14 @@
 UNDERSCORES_OPT = # -DALLOW_HOSTNAME_UNDERSCORES
 RETRY_PATCH	= -DRETRY_PATCH
 NO_CACHE_ACL	= # -DNO_CACHE_ACL=1
+MIME_INTERCEPT	= -DMIME_INTERCEPT
 
 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) \
 		  $(RELOAD_INTO_IMS) $(UNDERSCORES_OPT) \
-		  $(RETRY_PATCH) $(NO_CACHE_ACL)
+		  $(RETRY_PATCH) $(NO_CACHE_ACL) $(MIME_INTERCEPT)
 
 prefix		= @prefix@
 exec_prefix	= @exec_prefix@
diff -r -d -u -N squid-1.1.22/src/cache_cf.c squid-1.1.22-mint/src/cache_cf.c
--- squid-1.1.22/src/cache_cf.c	Sat May  2 01:20:58 1998
+++ squid-1.1.22-mint/src/cache_cf.c	Sun Aug  2 11:14:17 1998
@@ -1031,6 +1031,39 @@
 	*iptr = ANONYMIZER_STANDARD;
 }
 
+#if MIME_INTERCEPT
+static void
+parseMimeIntercept(void) {
+    mime_intlist *nml;
+    char *token;
+    int i;
+
+    nml = xcalloc(1,sizeof(mime_intlist));
+    token = strtok(NULL, w_space);
+    if (token == NULL)
+        self_destruct();
+    if (regcomp(&nml->rex,token,0)) /* Compile token */
+        self_destruct();
+    GetInteger(i);
+    nml->sendok = i;
+    GetInteger(i);
+    nml->bsek = i;
+    nml->next = Config.mime_int; /* Put into list */
+    Config.mime_int = nml;
+}
+
+static void mime_int_destroy(void) {
+    mime_intlist *ml;
+
+    while (Config.mime_int) {
+        ml = Config.mime_int;
+        Config.mime_int = ml->next;
+        regfree(&ml->rex);
+        safe_free(ml);
+    }
+}
+#endif
+
 int
 parseConfigFile(const char *file_name)
 {
@@ -1419,7 +1452,10 @@
 	else if (!strcmp(token, "maximum_single_addr_tries"))
 	    parseIntegerValue(&Config.Retry.max_single_addr);
 #endif /* RETRY_PATCH */
-
+#if MIME_INTERCEPT
+        else if (!strcmp(token, "mime_intercept"))
+            parseMimeIntercept();
+#endif
 	/* If unknown, treat as a comment line */
 	else {
 	    debug(3, 0, "parseConfigFile: line %d unrecognized: '%s'\n",
@@ -1563,6 +1599,9 @@
     ip_acl_destroy(&Config.local_ip_list);
     ip_acl_destroy(&Config.firewall_ip_list);
     objcachePasswdDestroy(&Config.passwd_list);
+#if MIME_INTERCEPT
+    mime_int_destroy();
+#endif
     refreshFreeMemory();
 }
 
diff -r -d -u -N squid-1.1.22/src/cache_cf.h squid-1.1.22-mint/src/cache_cf.h
--- squid-1.1.22/src/cache_cf.h	Thu Apr  9 06:58:14 1998
+++ squid-1.1.22-mint/src/cache_cf.h	Sat Aug  1 19:42:49 1998
@@ -137,6 +137,15 @@
     struct _ip_acl *next;
 } ip_acl;
 
+#if MIME_INTERCEPT
+typedef struct _mime_intlist {
+    regex_t rex;
+    int sendok;
+    int bsek;
+    struct _mime_intlist *next;
+} mime_intlist;
+#endif
+
 struct SquidConfig {
     struct {
 	int maxSize;
@@ -290,6 +299,9 @@
 	int max_single_addr;
     } Retry;
 #endif /* RETRY_PATCH */
+#if MIME_INTERCEPT
+    mime_intlist *mime_int;
+#endif
 };
 
 extern struct SquidConfig Config;
@@ -314,3 +326,5 @@
 
 
 #endif /* ndef  _CACHE_CONFIG_H_ */
+
+
diff -r -d -u -N squid-1.1.22/src/comm.c squid-1.1.22-mint/src/comm.c
--- squid-1.1.22/src/comm.c	Thu Apr  9 06:58:15 1998
+++ squid-1.1.22-mint/src/comm.c	Sat Aug  1 16:55:31 1998
@@ -840,6 +840,15 @@
     fd_table[fd].stall_until = squid_curtime + delta;
 }
 
+#ifdef MIME_INTERCEPT
+void
+comm_set_wstall(int fd, int delta)
+{
+  if (fd < 0)
+    return;
+  fd_table[fd].wstall_until = squid_curtime + delta;
+}
+#endif
 
 #ifdef USE_POLL
 
@@ -1012,6 +1021,9 @@
 	    if (fd_table[i].read_handler && fd_table[i].stall_until <= squid_curtime)
 		events |= POLLRDNORM;
 	    if (fd_table[i].write_handler)
+#ifdef MIME_INTERCEPT
+	      if (fd_table[i].wstall_until <= squid_curtime)
+#endif
 		events |= POLLWRNORM;
 	    if (events) {
 		if (i == theHttpConnection)
@@ -1202,8 +1214,14 @@
 		}
 	    }
 	    if (fd_table[i].write_handler) {
+#ifdef MIME_INTERCEPT
+	      if (fd_table[i].wstall_until <= squid_curtime) {
+#endif
 		nfds++;
 		FD_SET(i, &writefds);
+#ifdef MIME_INTERCEPT
+	      }
+#endif
 	    }
 	}
 	if (!fdstat_are_n_free_fd(RESERVED_FD) && theHttpConnection >= 0) {
diff -r -d -u -N squid-1.1.22/src/comm.h squid-1.1.22-mint/src/comm.h
--- squid-1.1.22/src/comm.h	Thu Apr  9 06:58:16 1998
+++ squid-1.1.22-mint/src/comm.h	Sat Aug  1 17:09:17 1998
@@ -181,6 +181,9 @@
     char ascii_note[FD_ASCII_NOTE_SZ];
     unsigned int comm_type;
     time_t stall_until;		/* don't select for read until this time reached */
+#if MIME_INTERCEPT
+    time_t wstall_until;        /* don't select for write */
+#endif
     RWStateData *rwstate;	/* State data for comm_write */
 } FD_ENTRY;
 
@@ -209,6 +212,9 @@
 extern int comm_udp_sendto _PARAMS((int fd, const struct sockaddr_in *, int size, const char *buf, int len));
 extern int fd_of_first_client _PARAMS((StoreEntry *));
 extern void comm_set_stall _PARAMS((int, int));
+#if MIME_INTERCEPT
+extern void comm_set_wstall _PARAMS((int, int));
+#endif
 extern void comm_write _PARAMS((int fd,
 	char *buf,
 	int size,
diff -r -d -u -N squid-1.1.22/src/icp.c squid-1.1.22-mint/src/icp.c
--- squid-1.1.22/src/icp.c	Sat May  2 01:21:00 1998
+++ squid-1.1.22-mint/src/icp.c	Sun Aug  2 11:49:03 1998
@@ -570,6 +570,33 @@
 }
 
 #endif /* LOG_FULL_HEADERS */
+
+#ifdef MIME_INTERCEPT
+/* Setup delay for specific MIME type. This might be an ugly hack.. */
+static void
+icpSetupIntercept(icpStateData *icpState)
+{
+   if (icpState->entry->mem_obj) { /* icpSendMoreData looks as this might
+                                      unset at some time... */
+      char *mime=icpState->entry->mem_obj->reply->content_type;
+      mime_intlist *ml = Config.mime_int;
+      short inset = 1;
+
+      icpState->mint_setup = 1; /* We did setup for this connection */
+      while (ml && inset) {
+	  if (!regexec(&ml->rex,mime,0,0,0)) {
+              icpState->mint_sendok = ml->sendok;
+              icpState->mint_bsek   = ml->bsek;
+              inset = 0;
+	  }
+          ml = ml->next;
+      }
+      if (inset) icpState->mint_sendok = INT_MAX; /* Nothing found... */
+      /*      printf("Mime-Type %s, %d, %d\n",mime,icpState->mint_sendok,icpState->mint_bsek); */
+   }
+}
+#endif
+               
 /* Send available data from an object in the cache.  This is called either
  * on select for  write or directly by icpHandleStore. */
 
@@ -620,6 +647,19 @@
 	if (hack)
 	    *(buf + size++) = C;
     }
+#if MIME_INTERCEPT
+    if (!icpState->mint_setup) icpSetupIntercept(icpState); 
+    icpState->mint_sent += len;
+    if (icpState->mint_sent > icpState->mint_sendok) {
+        int delay = 0;
+        if (icpState->mint_bsek) 
+	  delay = (icpState->mint_sent-icpState->mint_sendok) / icpState->mint_bsek;
+	icpState->mint_sendok=icpState->mint_sent;
+	/*	printf ("Delay = %d, Mime %s\n",delay,
+          entry->mem_obj?entry->mem_obj->reply->content_type:"Leer"); */
+	comm_set_wstall(fd,delay);
+    }
+#endif
     comm_write(fd,
 	buf,
 	len,
diff -r -d -u -N squid-1.1.22/src/icp.h squid-1.1.22-mint/src/icp.h
--- squid-1.1.22/src/icp.h	Mon Dec 15 09:43:21 1997
+++ squid-1.1.22-mint/src/icp.h	Sat Aug  1 19:59:36 1998
@@ -201,6 +201,12 @@
     } ident;
     int ip_lookup_pending;
     int redirect_state;
+#if MIME_INTERCEPT
+    int mint_sendok;
+    int mint_bsek;
+    int mint_sent;
+    int mint_setup;
+#endif
 } icpStateData;
 
 extern void *icpCreateMessage _PARAMS((icp_opcode opcode,
