Fix CVE-2012-3501, DoS when external URL checker is used

This fix was integrated into 6.7 and 5.8.

Obtained-from: https://github.com/darold/squidclamav/commit/80f74451f628264d1d9a1f1c0bbcebc932ba5e00.diff

--- src/squidclamav.c.orig	2010-12-11 15:20:46.000000000 +0300
+++ src/squidclamav.c	2012-08-25 15:55:51.708586983 +0400
@@ -62,6 +62,7 @@
 static char * escape_quote (char *s);
 void timeit (struct timeval start, char *level);
 int dconnect (void);
+char * replace(const char *s, const char *old, const char *new);
 void replace_chr(char string[], char *from, char *to);
 void free_global ();		/* routine to free global pointer */
 void freeBuff (struct IN_BUFF);
@@ -474,11 +475,15 @@
       /* chaining with SquidGuard - before bridge mode or not*/
       if ((bridge_mode == 0) && (squidguard != NULL)) {
 		if (usepipe == 1) {
+ 			char *rbuff = NULL;
+			/* escaping escaped character to prevent unescaping by squidguard */
+			rbuff = replace(rbuff, "%", "%25");
 			if (debug > 0)
 			    logit(log_file, "DEBUG Sending request to chained program: %s\n", squidguard);
 			fprintf(sgfpw,"%s\n",sbuff);
 			fflush(sgfpw);
 			xfree(escaped);
+			xfree(rbuff);
 			escaped = NULL;
 			/* the chained redirector must return empty line if ok or the redirection url */
 			chain_ret = (char *)malloc(sizeof(char)*MAX_URL);
@@ -1114,3 +1119,38 @@
 }
 
 
+/**
+ * Searches all occurrences of old into s
+ * and replaces with new
+ */
+char *
+replace(const char *s, const char *old, const char *new)
+{
+	char *ret;
+	int i, count = 0;
+	size_t newlen = strlen(new);
+	size_t oldlen = strlen(old);
+
+	for (i = 0; s[i] != '\0'; i++) {
+		if (strstr(&s[i], old) == &s[i]) {
+			count++;
+			i += oldlen - 1;
+		}
+	}
+	ret = malloc(i + 1 + count * (newlen - oldlen));
+	if (ret != NULL) {
+		i = 0;
+		while (*s) {
+			if (strstr(s, old) == s) {
+				strcpy(&ret[i], new);
+				i += newlen;
+				s += oldlen;
+			} else {
+				ret[i++] = *s++;
+			}
+		}
+		ret[i] = '\0';
+	}
+
+	return ret;
+}
