diff -u -r -N squid-3.5.1/ChangeLog squid-3.5.2/ChangeLog
--- squid-3.5.1/ChangeLog	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/ChangeLog	2015-02-18 04:17:02.000000000 -0800
@@ -1,3 +1,21 @@
+Changes to squid-3.5.2 (18 Feb 2015):
+
+	- Regression Bug 4176: Digest auth too many helper lookups
+	- Regression Bug 4180: not-fully-initialized data member in ACLUserData
+	- Bug 4172: Solaris broken krb5-config
+	- Bug 4073: Cygwin compile errors
+	- Bug 3919: remove several never-true / never-false comparisons
+	- HTTPS: Add missing root CAs when validating chains that passed internal checks
+	- Fix some cbdataFree related memory leaks
+	- Quieten CBDATA 'leak' messages
+	- Set SNI information in transparent bumping mode
+	- negotiate_kerberos_auth: fix krb5.conf backward compatibility
+	- Fix memory leaks in cachemgr.cgi URL parser
+	- Fix sslproxy_options in peek-and-splice mode
+	- ... and fix several portability and build issues
+	- ... and some documentation updates
+	- ... and all fixes from squid 3.4.11
+
 Changes to squid-3.5.1 (13 Jan 2015):
 
 	- Fix handling of invalid SSL server certificates when splicing connections
@@ -100,6 +118,18 @@
 	- ... and many error page translation updates
 	- ... and much code cleanup and polishing
 
+Changes to squid-3.4.12 (18 Feb 2015):
+
+	- Bug 4066: Digest auth nonce indefinite rollover
+	- Bug 3997: Excessive NTLM or Negotiate auth helper annotations
+	- Fix several crashes when debugging enabled
+	- Fix silent SSL/TLS failure on split-stack operating systems
+	- HTTP/1.1: Stop emitting (Proxy-)Authentication-Info for Negotiate
+	- HTTPS: Add TLS/SSL option NO_TICKET to http[s]_port
+	- Remove dst ACL dependency on HTTP request message existence
+	- Set cap_net_admin when Squid sets TOS/Diffserv packet values
+	- ... and some documentation updates
+
 Changes to squid-3.4.11 (13 Jan 2015):
 
 	- Bug 4164: SEGFAULT when %W formating code used in errorpages
diff -u -r -N squid-3.5.1/compat/Makefile.in squid-3.5.2/compat/Makefile.in
--- squid-3.5.1/compat/Makefile.in	2015-01-13 04:53:10.000000000 -0800
+++ squid-3.5.2/compat/Makefile.in	2015-02-18 04:18:03.000000000 -0800
@@ -83,8 +83,8 @@
 build_triplet = @build@
 host_triplet = @host@
 DIST_COMMON = $(top_srcdir)/src/Common.am $(srcdir)/Makefile.in \
-	$(srcdir)/Makefile.am tempnam.c initgroups.c drand48.c \
-	psignal.c strtoll.c strerror.c $(top_srcdir)/cfgaux/depcomp \
+	$(srcdir)/Makefile.am strtoll.c strerror.c initgroups.c \
+	drand48.c tempnam.c psignal.c $(top_srcdir)/cfgaux/depcomp \
 	$(top_srcdir)/cfgaux/test-driver
 check_PROGRAMS = testPreCompiler$(EXEEXT)
 TESTS = testPreCompiler$(EXEEXT) testHeaders
diff -u -r -N squid-3.5.1/compat/osdetect.h squid-3.5.2/compat/osdetect.h
--- squid-3.5.1/compat/osdetect.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/compat/osdetect.h	2015-02-18 04:17:02.000000000 -0800
@@ -72,9 +72,8 @@
 #elif defined(__DragonFly__)
 #define _SQUID_DRAGONFLY_ 1
 
-#elif defined(__CYGWIN32__) || defined(__CYGWIN__)
+#elif defined(__CYGWIN__)
 #define _SQUID_CYGWIN_ 1
-#define _SQUID_WINDOWS_ 1
 
 #elif defined(__MINGW32__) || defined(__MINGW__)
 #define _SQUID_MINGW_ 1
diff -u -r -N squid-3.5.1/configure squid-3.5.2/configure
--- squid-3.5.1/configure	2015-01-13 04:54:26.000000000 -0800
+++ squid-3.5.2/configure	2015-02-18 04:18:57.000000000 -0800
@@ -1,7 +1,7 @@
 #! /bin/sh
 # From configure.ac Revision.
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Squid Web Proxy 3.5.1.
+# Generated by GNU Autoconf 2.69 for Squid Web Proxy 3.5.2.
 #
 # Report bugs to <http://bugs.squid-cache.org/>.
 #
@@ -595,8 +595,8 @@
 # Identity of this package.
 PACKAGE_NAME='Squid Web Proxy'
 PACKAGE_TARNAME='squid'
-PACKAGE_VERSION='3.5.1'
-PACKAGE_STRING='Squid Web Proxy 3.5.1'
+PACKAGE_VERSION='3.5.2'
+PACKAGE_STRING='Squid Web Proxy 3.5.2'
 PACKAGE_BUGREPORT='http://bugs.squid-cache.org/'
 PACKAGE_URL=''
 
@@ -1617,7 +1617,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures Squid Web Proxy 3.5.1 to adapt to many kinds of systems.
+\`configure' configures Squid Web Proxy 3.5.2 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1687,7 +1687,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of Squid Web Proxy 3.5.1:";;
+     short | recursive ) echo "Configuration of Squid Web Proxy 3.5.2:";;
    esac
   cat <<\_ACEOF
 
@@ -2094,7 +2094,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-Squid Web Proxy configure 3.5.1
+Squid Web Proxy configure 3.5.2
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -3198,7 +3198,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by Squid Web Proxy $as_me 3.5.1, which was
+It was created by Squid Web Proxy $as_me 3.5.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4065,7 +4065,7 @@
 
 # Define the identity of the package.
  PACKAGE='squid'
- VERSION='3.5.1'
+ VERSION='3.5.2'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -6748,15 +6748,143 @@
 
 fi
 
+# Guess the compiler type (sets squid_cv_compiler)
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking what kind of compiler we're using" >&5
+$as_echo_n "checking what kind of compiler we're using... " >&6; }
+if ${squid_cv_compiler+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+
+          if test -z "$squid_cv_compiler" ; then
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+#if !defined(__SUNPRO_C) && !defined(__SUNPRO_CC)
+#error "not sunpro c"
+#endif
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  squid_cv_compiler="sunstudio"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  fi
+    if test -z "$squid_cv_compiler" ; then
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+#if !defined(__ICC)
+#error "not Intel(R) C++ Compiler"
+#endif
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  squid_cv_compiler="icc"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  fi
+    if test -z "$squid_cv_compiler" ; then
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+#if !defined(__clang__)
+#error "not clang"
+#endif
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  squid_cv_compiler="clang"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  fi
+    if test -z "$squid_cv_compiler" ; then
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+#if !defined(_MSC_VER)
+#error "not Microsoft VC++"
+#endif
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  squid_cv_compiler="msvc"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  fi
+    if test -z "$squid_cv_compiler" ; then
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+#if !defined(__GNUC__)
+#error "not gcc"
+#endif
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  squid_cv_compiler="gcc"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  fi
+    if test -z "$squid_cv_compiler" ; then
+   squid_cv_compiler="none"
+  fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $squid_cv_compiler" >&5
+$as_echo "$squid_cv_compiler" >&6; }
+
 # Check for C++11 compiler support
-if test "x$squid_host_os" != "xmingw" ; then
-    #BUG 3613: when clang -std=c++0x is used, it activates a "strict mode"
-    # in the system libraries, which makes some c99 methods unavailable
-    # (e.g. strtoll), yet configure detects them as avilable.
-    case "$CXX" in
-      *clang++*) ;; #do nothing
-      *)
-          ax_cxx_compile_cxx11_required=false
+#
+# BUG 3613: when clang -std=c++0x is used, it activates a "strict mode"
+# in the system libraries, which makes some c99 methods unavailable
+# (e.g. strtoll), yet configure detects them as avilable.
+#
+# Similar POSIX issues on MinGW 32-bit and Cygwin
+#
+if ! test "x$squid_host_os" = "xmingw" -o "x$squid_host_os" = "xcygwin" -o "x$squid_cv_compiler" = "xclang"; then
+      ax_cxx_compile_cxx11_required=false
   ac_ext=cpp
 ac_cpp='$CXXCPP $CPPFLAGS'
 ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -6894,7 +7022,6 @@
 
   fi
 
-    esac
 fi
 
 # test for programs
@@ -19575,131 +19702,6 @@
 fi
 
 
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking what kind of compiler we're using" >&5
-$as_echo_n "checking what kind of compiler we're using... " >&6; }
-if ${squid_cv_compiler+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-
-
-          if test -z "$squid_cv_compiler" ; then
-   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-
-#if !defined(__SUNPRO_C) && !defined(__SUNPRO_CC)
-#error "not sunpro c"
-#endif
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-  squid_cv_compiler="sunstudio"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  fi
-    if test -z "$squid_cv_compiler" ; then
-   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-
-#if !defined(__ICC)
-#error "not Intel(R) C++ Compiler"
-#endif
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-  squid_cv_compiler="icc"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  fi
-    if test -z "$squid_cv_compiler" ; then
-   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-
-#if !defined(__clang__)
-#error "not clang"
-#endif
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-  squid_cv_compiler="clang"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  fi
-    if test -z "$squid_cv_compiler" ; then
-   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-
-#if !defined(_MSC_VER)
-#error "not Microsoft VC++"
-#endif
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-  squid_cv_compiler="msvc"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  fi
-    if test -z "$squid_cv_compiler" ; then
-   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-
-#if !defined(__GNUC__)
-#error "not gcc"
-#endif
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
-  squid_cv_compiler="gcc"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  fi
-    if test -z "$squid_cv_compiler" ; then
-   squid_cv_compiler="none"
-  fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $squid_cv_compiler" >&5
-$as_echo "$squid_cv_compiler" >&6; }
-
 
  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler variant" >&5
 $as_echo_n "checking for compiler variant... " >&6; }
@@ -19755,7 +19757,7 @@
 fi
 
 
- if test "x$squid_host_os" = "xmingw" -o "x$squid_host_os" = "xcygwin"; then
+ if test "x$squid_host_os" = "xmingw"; then
   ENABLE_WIN32SPECIFIC_TRUE=
   ENABLE_WIN32SPECIFIC_FALSE='#'
 else
@@ -21969,10 +21971,10 @@
 
 if test "x${enable_eui:=yes}" = "xyes" ; then
   case "$squid_host_os" in
-    linux|solaris|freebsd|openbsd|netbsd)
+    linux|solaris|freebsd|openbsd|netbsd|cygwin)
       ${TRUE}
       ;;
-    cygwin|mingw)
+    mingw)
       EUILIB="-liphlpapi"
       ;;
     *)
@@ -25511,8 +25513,12 @@
 $as_echo "$as_me: Use krb5-config to get CXXFLAGS and LIBS" >&6;}
     LIB_KRB5_CFLAGS="`$ac_krb5_config --cflags krb5 2>/dev/null`"
     LIB_KRB5_LIBS="`$ac_krb5_config --libs krb5 2>/dev/null`"
-    LIB_KRB5_CFLAGS="`$ac_krb5_config --cflags gssapi 2>/dev/null` $LIB_KRB5_CFLAGS"
-    LIB_KRB5_LIBS="`$ac_krb5_config --libs gssapi 2>/dev/null` $LIB_KRB5_LIBS"
+    # Solaris 10 Update 11 patches the krb5-config tool to produce stderr messages on stdout.
+    SOLARIS_BROKEN_KRB5CONFIG_GSSAPI="`$ac_krb5_config --libs gssapi 2>/dev/null | grep "krb5-config"`"
+    if test "x$SOLARIS_BROKEN_KRB5CONFIG_GSSAPI" = "x"; then
+      LIB_KRB5_CFLAGS="`$ac_krb5_config --cflags gssapi 2>/dev/null` $LIB_KRB5_CFLAGS"
+      LIB_KRB5_LIBS="`$ac_krb5_config --libs gssapi 2>/dev/null` $LIB_KRB5_LIBS"
+    fi
   else
     ## For some OS pkg-config is broken or unavailable.
     ## Detect libraries the hard way.
@@ -40707,7 +40713,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by Squid Web Proxy $as_me 3.5.1, which was
+This file was extended by Squid Web Proxy $as_me 3.5.2, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -40773,7 +40779,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-Squid Web Proxy config.status 3.5.1
+Squid Web Proxy config.status 3.5.2
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -u -r -N squid-3.5.1/configure.ac squid-3.5.2/configure.ac
--- squid-3.5.1/configure.ac	2015-01-13 04:54:25.000000000 -0800
+++ squid-3.5.2/configure.ac	2015-02-18 04:18:57.000000000 -0800
@@ -5,7 +5,7 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-AC_INIT([Squid Web Proxy],[3.5.1],[http://bugs.squid-cache.org/],[squid])
+AC_INIT([Squid Web Proxy],[3.5.2],[http://bugs.squid-cache.org/],[squid])
 AC_PREREQ(2.61)
 AC_CONFIG_HEADERS([include/autoconf.h])
 AC_CONFIG_AUX_DIR(cfgaux)
@@ -92,16 +92,19 @@
 	AC_USE_SYSTEM_EXTENSIONS
 fi
 
+# Guess the compiler type (sets squid_cv_compiler)
+SQUID_CC_GUESS_VARIANT
+
 # Check for C++11 compiler support
-if test "x$squid_host_os" != "xmingw" ; then
-    #BUG 3613: when clang -std=c++0x is used, it activates a "strict mode"
-    # in the system libraries, which makes some c99 methods unavailable
-    # (e.g. strtoll), yet configure detects them as avilable.
-    case "$CXX" in
-      *clang++*) ;; #do nothing
-      *)
-      AX_CXX_COMPILE_STDCXX_11([noext],[optional])
-    esac
+#
+# BUG 3613: when clang -std=c++0x is used, it activates a "strict mode"
+# in the system libraries, which makes some c99 methods unavailable
+# (e.g. strtoll), yet configure detects them as avilable.
+#
+# Similar POSIX issues on MinGW 32-bit and Cygwin
+#
+if ! test "x$squid_host_os" = "xmingw" -o "x$squid_host_os" = "xcygwin" -o "x$squid_cv_compiler" = "xclang"; then
+  AX_CXX_COMPILE_STDCXX_11([noext],[optional])
 fi
 
 # test for programs
@@ -198,7 +201,6 @@
   AC_SUBST([LIBADD_DL])
 fi
 
-SQUID_CC_GUESS_VARIANT
 SQUID_CC_GUESS_OPTIONS
 
 dnl find out the exe extension for this platform.
@@ -214,8 +216,7 @@
 fi
 AC_SUBST(CGIEXT)
 
-AM_CONDITIONAL(ENABLE_WIN32SPECIFIC,
-               [test "x$squid_host_os" = "xmingw" -o "x$squid_host_os" = "xcygwin"])
+AM_CONDITIONAL(ENABLE_WIN32SPECIFIC,[test "x$squid_host_os" = "xmingw"])
 AM_CONDITIONAL(ENABLE_WIN32_IPC,[test "x$squid_host_os" = "xmingw"])
 
 case "$squid_host_os" in
@@ -1132,10 +1133,10 @@
 ])
 if test "x${enable_eui:=yes}" = "xyes" ; then
   case "$squid_host_os" in
-    linux|solaris|freebsd|openbsd|netbsd)
+    linux|solaris|freebsd|openbsd|netbsd|cygwin)
       ${TRUE}
       ;;
-    cygwin|mingw)
+    mingw)
       EUILIB="-liphlpapi"
       ;;
     *)
@@ -1583,8 +1584,12 @@
     AC_MSG_NOTICE([Use krb5-config to get CXXFLAGS and LIBS])
     LIB_KRB5_CFLAGS="`$ac_krb5_config --cflags krb5 2>/dev/null`"
     LIB_KRB5_LIBS="`$ac_krb5_config --libs krb5 2>/dev/null`"
-    LIB_KRB5_CFLAGS="`$ac_krb5_config --cflags gssapi 2>/dev/null` $LIB_KRB5_CFLAGS"
-    LIB_KRB5_LIBS="`$ac_krb5_config --libs gssapi 2>/dev/null` $LIB_KRB5_LIBS"
+    # Solaris 10 Update 11 patches the krb5-config tool to produce stderr messages on stdout.
+    SOLARIS_BROKEN_KRB5CONFIG_GSSAPI="`$ac_krb5_config --libs gssapi 2>/dev/null | grep "krb5-config"`"
+    if test "x$SOLARIS_BROKEN_KRB5CONFIG_GSSAPI" = "x"; then
+      LIB_KRB5_CFLAGS="`$ac_krb5_config --cflags gssapi 2>/dev/null` $LIB_KRB5_CFLAGS"
+      LIB_KRB5_LIBS="`$ac_krb5_config --libs gssapi 2>/dev/null` $LIB_KRB5_LIBS"
+    fi
   else
     ## For some OS pkg-config is broken or unavailable.
     ## Detect libraries the hard way.
diff -u -r -N squid-3.5.1/helpers/basic_auth/DB/basic_db_auth.8 squid-3.5.2/helpers/basic_auth/DB/basic_db_auth.8
--- squid-3.5.1/helpers/basic_auth/DB/basic_db_auth.8	2015-01-13 05:43:16.000000000 -0800
+++ squid-3.5.2/helpers/basic_auth/DB/basic_db_auth.8	2015-02-18 04:55:55.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_DB_AUTH 1"
-.TH BASIC_DB_AUTH 1 "2015-01-13" "perl v5.20.1" "User Contributed Perl Documentation"
+.TH BASIC_DB_AUTH 1 "2015-02-18" "perl v5.20.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.1/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8 squid-3.5.2/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8
--- squid-3.5.1/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8	2015-01-13 05:43:22.000000000 -0800
+++ squid-3.5.2/helpers/basic_auth/MSNT-multi-domain/basic_msnt_multi_domain_auth.8	2015-02-18 04:55:58.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_MSNT_MULTI_DOMAIN_AUTH 1"
-.TH BASIC_MSNT_MULTI_DOMAIN_AUTH 1 "2015-01-13" "perl v5.20.1" "User Contributed Perl Documentation"
+.TH BASIC_MSNT_MULTI_DOMAIN_AUTH 1 "2015-02-18" "perl v5.20.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.1/helpers/basic_auth/POP3/basic_pop3_auth.8 squid-3.5.2/helpers/basic_auth/POP3/basic_pop3_auth.8
--- squid-3.5.1/helpers/basic_auth/POP3/basic_pop3_auth.8	2015-01-13 05:43:28.000000000 -0800
+++ squid-3.5.2/helpers/basic_auth/POP3/basic_pop3_auth.8	2015-02-18 04:56:01.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_POP3_AUTH 1"
-.TH BASIC_POP3_AUTH 1 "2015-01-13" "perl v5.20.1" "User Contributed Perl Documentation"
+.TH BASIC_POP3_AUTH 1 "2015-02-18" "perl v5.20.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.1/helpers/external_acl/delayer/ext_delayer_acl.8 squid-3.5.2/helpers/external_acl/delayer/ext_delayer_acl.8
--- squid-3.5.1/helpers/external_acl/delayer/ext_delayer_acl.8	2015-01-13 05:43:44.000000000 -0800
+++ squid-3.5.2/helpers/external_acl/delayer/ext_delayer_acl.8	2015-02-18 04:56:11.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_DELAYER_ACL 1"
-.TH EXT_DELAYER_ACL 1 "2015-01-13" "perl v5.20.1" "User Contributed Perl Documentation"
+.TH EXT_DELAYER_ACL 1 "2015-02-18" "perl v5.20.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.1/helpers/external_acl/LDAP_group/ext_ldap_group_acl.8 squid-3.5.2/helpers/external_acl/LDAP_group/ext_ldap_group_acl.8
--- squid-3.5.1/helpers/external_acl/LDAP_group/ext_ldap_group_acl.8	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/helpers/external_acl/LDAP_group/ext_ldap_group_acl.8	2015-02-18 04:17:02.000000000 -0800
@@ -7,19 +7,19 @@
 .
 .SH SYNOPSIS
 .if !'po4a'hide' .B ext_ldap_group_acl
-.if !'po4a'hide' .B "\-b \""
-base DN
-.if !'po4a'hide' .B "\" \-f \""
-LDAP search filter
-.if !'po4a'hide' .B "\" ["
+.if !'po4a'hide' .B \-b
+base\-DN
+.if !'po4a'hide' .B \-f
+filter
+.if !'po4a'hide' .B "["
 options
 .if !'po4a'hide' .B "] ["
-LDAP server name
-.if !'po4a'hide' .B "[:"
+server
+.if !'po4a'hide' .B "[ ':' "
 port
-.if !'po4a'hide' .B "]|"
+.if !'po4a'hide' .B "] |"
 URI
-.if !'po4a'hide' .B "]..."
+.if !'po4a'hide' .B "] ..."
 .
 .SH DESCRIPTION
 .B ext_ldap_group_acl
@@ -100,7 +100,7 @@
 configuration file without getting the secretfile.
 .
 .if !'po4a'hide' .TP
-.if !'po4a'hide' .BI \-E certpath
+.if !'po4a'hide' .BI "\-E " certpath
 Enable LDAP over SSL (requires Netscape LDAP API libraries)
 .
 .if !'po4a'hide' .TP
diff -u -r -N squid-3.5.1/helpers/external_acl/SQL_session/ext_sql_session_acl.8 squid-3.5.2/helpers/external_acl/SQL_session/ext_sql_session_acl.8
--- squid-3.5.1/helpers/external_acl/SQL_session/ext_sql_session_acl.8	2015-01-13 05:43:55.000000000 -0800
+++ squid-3.5.2/helpers/external_acl/SQL_session/ext_sql_session_acl.8	2015-02-18 04:56:18.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_SQL_SESSION_ACL 1"
-.TH EXT_SQL_SESSION_ACL 1 "2015-01-13" "perl v5.20.1" "User Contributed Perl Documentation"
+.TH EXT_SQL_SESSION_ACL 1 "2015-02-18" "perl v5.20.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.1/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8 squid-3.5.2/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8
--- squid-3.5.1/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8	2015-01-13 05:43:59.000000000 -0800
+++ squid-3.5.2/helpers/external_acl/wbinfo_group/ext_wbinfo_group_acl.8	2015-02-18 04:56:21.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_WBINFO_GROUP_ACL 1"
-.TH EXT_WBINFO_GROUP_ACL 1 "2015-01-13" "perl v5.20.1" "User Contributed Perl Documentation"
+.TH EXT_WBINFO_GROUP_ACL 1 "2015-02-18" "perl v5.20.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.1/helpers/log_daemon/DB/log_db_daemon.8 squid-3.5.2/helpers/log_daemon/DB/log_db_daemon.8
--- squid-3.5.1/helpers/log_daemon/DB/log_db_daemon.8	2015-01-13 05:44:02.000000000 -0800
+++ squid-3.5.2/helpers/log_daemon/DB/log_db_daemon.8	2015-02-18 04:56:23.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "LOG_DB_DAEMON 1"
-.TH LOG_DB_DAEMON 1 "2015-01-13" "perl v5.20.1" "User Contributed Perl Documentation"
+.TH LOG_DB_DAEMON 1 "2015-02-18" "perl v5.20.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.1/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc squid-3.5.2/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc
--- squid-3.5.1/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/helpers/negotiate_auth/kerberos/negotiate_kerberos_auth.cc	2015-02-18 04:17:02.000000000 -0800
@@ -105,7 +105,7 @@
         return NULL;
     }
     rc = getaddrinfo(hostname, NULL, NULL, &hres);
-    if (rc != 0) {
+    if (rc != 0 || hres == NULL ) {
         debug((char *) "%s| %s: ERROR: resolving hostname with getaddrinfo: %s failed\n",
               LogTime(), PROGRAM, gai_strerror(rc));
         fprintf(stderr,
@@ -339,10 +339,8 @@
     gss_buffer_desc type_id = GSS_C_EMPTY_BUFFER;
 #endif
 #endif
-#if HAVE_PAC_SUPPORT || HAVE_KRB5_MEMORY_KEYTAB
     krb5_context context = NULL;
     krb5_error_code ret;
-#endif
     long length = 0;
     static int err = 0;
     int opt, log = 0, norealm = 0;
@@ -352,6 +350,7 @@
     char *service_principal = NULL;
     char *keytab_name = NULL;
     char *keytab_name_env = NULL;
+    char default_keytab[MAXPATHLEN];
 #if HAVE_KRB5_MEMORY_KEYTAB
     char *memory_keytab_name = NULL;
 #endif
@@ -536,9 +535,14 @@
         putenv(keytab_name_env);
     } else {
         keytab_name_env = getenv("KRB5_KTNAME");
-        if (!keytab_name_env)
-            keytab_name = xstrdup("/etc/krb5.keytab");
-        else
+        if (!keytab_name_env) {
+            ret = krb5_init_context(&context);
+            if (!check_k5_err(context, "krb5_init_context", ret)) {
+                krb5_kt_default_name(context, default_keytab, MAXPATHLEN);
+            }
+            keytab_name = default_keytab;
+            krb5_free_context(context);
+        } else
             keytab_name = xstrdup(keytab_name_env);
     }
     debug((char *) "%s| %s: INFO: Setting keytab to %s\n", LogTime(), PROGRAM, keytab_name);
diff -u -r -N squid-3.5.1/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc squid-3.5.2/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc
--- squid-3.5.1/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/helpers/negotiate_auth/kerberos/negotiate_kerberos_pac.cc	2015-02-18 04:17:02.000000000 -0800
@@ -40,7 +40,7 @@
 
 #include "negotiate_kerberos.h"
 
-#if HAVE_PAC_SUPPORT
+#if HAVE_GSSAPI && HAVE_PAC_SUPPORT
 
 static int bpos;
 static krb5_data *ad_data;
@@ -141,9 +141,9 @@
 int
 checkustr(RPC_UNICODE_STRING *string)
 {
-    uint32_t size,off,len;
 
     if (string->pointer != 0) {
+        uint32_t size,off,len;
         align(4);
         size = (uint32_t)((p[bpos]<<0) | (p[bpos+1]<<8) | (p[bpos+2]<<16) | (p[bpos+3]<<24));
         bpos = bpos+4;
@@ -168,7 +168,6 @@
 {
     if (GroupIds!= 0) {
         uint32_t ngroup;
-        uint32_t sauth;
         int l;
 
         align(4);
@@ -182,6 +181,7 @@
 
         Rids=(char **)xcalloc(GroupCount*sizeof(char*),1);
         for ( l=0; l<(int)GroupCount; l++) {
+            uint32_t sauth;
             Rids[l]=(char *)xcalloc(4*sizeof(char),1);
             memcpy((void *)Rids[l],(void *)&p[bpos],4);
             sauth = get4byt();
@@ -196,11 +196,16 @@
 char *
 getdomaingids(char *ad_groups, uint32_t DomainLogonId, char **Rids, uint32_t GroupCount)
 {
+    if (!ad_groups) {
+        debug((char *) "%s| %s: ERR: No space to store groups\n",
+              LogTime(), PROGRAM);
+        return NULL;
+    }
+
     if (DomainLogonId!= 0) {
         uint32_t nauth;
         uint8_t rev;
         uint64_t idauth;
-        uint32_t sauth;
         char dli[256];
         char *ag;
         size_t length;
@@ -244,6 +249,7 @@
 
         snprintf(dli,sizeof(dli),"S-%d-%lu",rev,(long unsigned int)idauth);
         for ( l=0; l<(int)nauth; l++ ) {
+            uint32_t sauth;
             sauth = get4byt();
             snprintf((char *)&dli[strlen(dli)],sizeof(dli)-strlen(dli),"-%u",sauth);
         }
@@ -279,23 +285,23 @@
 
         for ( l=0; l<(int)SidCount; l++ ) {
             char es[256];
-            uint32_t nauth;
-            uint8_t rev;
-            uint64_t idauth;
-            uint32_t sauth;
-            int k;
 
             if (pa[l] != 0) {
+                uint32_t nauth;
+                uint8_t rev;
+                uint64_t idauth;
+
                 nauth = get4byt();
 
                 length = 1+1+6+nauth*4;
                 ag = (char *)xcalloc((length)*sizeof(char),1);
                 memcpy((void *)ag,(const void*)&p[bpos],length);
                 if (!ad_groups) {
-                    if (!pstrcpy(ad_groups,"group=")) {
-                        debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n",
-                              LogTime(), PROGRAM, MAX_PAC_GROUP_SIZE, ad_groups);
-                    }
+                    debug((char *) "%s| %s: ERR: No space to store groups\n",
+                          LogTime(), PROGRAM);
+                    xfree(pa);
+                    xfree(ag);
+                    return NULL;
                 } else {
                     if (!pstrcat(ad_groups," group=")) {
                         debug((char *) "%s| %s: WARN: Too many groups ! size > %d : %s\n",
@@ -313,7 +319,8 @@
                 idauth = get6byt_be();
 
                 snprintf(es,sizeof(es),"S-%d-%lu",rev,(long unsigned int)idauth);
-                for ( k=0; k<(int)nauth; k++ ) {
+                for (int k=0; k<(int)nauth; k++ ) {
+                    uint32_t sauth;
                     sauth = get4byt();
                     snprintf((char *)&es[strlen(es)],sizeof(es)-strlen(es),"-%u",sauth);
                 }
@@ -350,6 +357,12 @@
     char **Rids=NULL;
     int l=0;
 
+    if (!ad_groups) {
+        debug((char *) "%s| %s: ERR: No space to store groups\n",
+              LogTime(), PROGRAM);
+        return NULL;
+    }
+
     ad_data = (krb5_data *)xcalloc(1,sizeof(krb5_data));
 
 #define KERB_LOGON_INFO 1
diff -u -r -N squid-3.5.1/helpers/storeid_rewrite/file/storeid_file_rewrite.8 squid-3.5.2/helpers/storeid_rewrite/file/storeid_file_rewrite.8
--- squid-3.5.1/helpers/storeid_rewrite/file/storeid_file_rewrite.8	2015-01-13 05:44:19.000000000 -0800
+++ squid-3.5.2/helpers/storeid_rewrite/file/storeid_file_rewrite.8	2015-02-18 04:56:33.000000000 -0800
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "STOREID_FILE_REWRITE 1"
-.TH STOREID_FILE_REWRITE 1 "2015-01-13" "perl v5.20.1" "User Contributed Perl Documentation"
+.TH STOREID_FILE_REWRITE 1 "2015-02-18" "perl v5.20.1" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-3.5.1/include/splay.h squid-3.5.2/include/splay.h
--- squid-3.5.1/include/splay.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/include/splay.h	2015-02-18 04:17:02.000000000 -0800
@@ -9,16 +9,13 @@
 #ifndef SQUID_SPLAY_H
 #define SQUID_SPLAY_H
 
-#if defined(__cplusplus)
-
 #include "fatal.h"
-
 #include <stack>
 
+// private class of Splay. Do not use directly
 template <class V>
 class SplayNode
 {
-
 public:
     typedef V Value;
     typedef int SPLAYCMP(Value const &a, Value const &b);
@@ -30,9 +27,8 @@
     Value data;
     mutable SplayNode<V> *left;
     mutable SplayNode<V> *right;
-    void destroy(SPLAYFREE *);
+    void destroy(SPLAYFREE * = DefaultFree);
     void walk(SPLAYWALKEE *, void *callerState);
-    bool empty() const { return this == NULL; }
     SplayNode<V> const * start() const;
     SplayNode<V> const * finish() const;
 
@@ -40,6 +36,8 @@
 
     SplayNode<V> * insert(Value data, SPLAYCMP * compare);
 
+    /// look in the splay for data for where compare(data,candidate) == true.
+    /// return NULL if not found, a pointer to the sought data if found.
     template <class FindValue> SplayNode<V> * splay(const FindValue &data, int( * compare)(FindValue const &a, Value const &b)) const;
 
     /// recursively visit left nodes, this node, and then right nodes
@@ -57,7 +55,6 @@
 template <class V>
 class Splay
 {
-
 public:
     typedef V Value;
     typedef int SPLAYCMP(Value const &a, Value const &b);
@@ -66,13 +63,13 @@
     typedef const SplayConstIterator<V> const_iterator;
     Splay():head(NULL), elements (0) {}
 
-    mutable SplayNode<V> * head;
     template <class FindValue> Value const *find (FindValue const &, int( * compare)(FindValue const &a, Value const &b)) const;
+
     void insert(Value const &, SPLAYCMP *compare);
 
     void remove(Value const &, SPLAYCMP *compare);
 
-    void destroy(SPLAYFREE *);
+    void destroy(SPLAYFREE * = SplayNode<V>::DefaultFree);
 
     SplayNode<V> const * start() const;
 
@@ -80,6 +77,8 @@
 
     size_t size() const;
 
+    bool empty() const { return size() == 0; }
+
     const_iterator begin() const;
 
     const_iterator end() const;
@@ -87,22 +86,13 @@
     /// recursively visit all nodes, in left-to-right order
     template <class Visitor> void visit(Visitor &v) const;
 
+private:
+    mutable SplayNode<V> * head;
     size_t elements;
 };
 
 SQUIDCEXTERN int splayLastResult;
 
-SQUIDCEXTERN splayNode *splay_insert(void *, splayNode *, splayNode::SPLAYCMP *);
-
-SQUIDCEXTERN splayNode *splay_delete(const void *, splayNode *, splayNode::SPLAYCMP *);
-
-SQUIDCEXTERN splayNode *splay_splay(const void **, splayNode *, splayNode::SPLAYCMP *);
-
-SQUIDCEXTERN void splay_destroy(splayNode *, splayNode::SPLAYFREE *);
-
-SQUIDCEXTERN void splay_walk(splayNode *, splayNode::SPLAYWALKEE *, void *callerState);
-
-/* inline methods */
 template<class V>
 SplayNode<V>::SplayNode (Value const &someData) : data(someData), left(NULL), right (NULL) {}
 
@@ -110,9 +100,6 @@
 void
 SplayNode<V>::walk(SPLAYWALKEE * walkee, void *state)
 {
-    if (this == NULL)
-        return;
-
     if (left)
         left->walk(walkee, state);
 
@@ -126,7 +113,7 @@
 SplayNode<V> const *
 SplayNode<V>::start() const
 {
-    if (this && left)
+    if (left)
         return left->start();
 
     return this;
@@ -136,7 +123,7 @@
 SplayNode<V> const *
 SplayNode<V>::finish() const
 {
-    if (this && right)
+    if (right)
         return right->finish();
 
     return this;
@@ -146,9 +133,6 @@
 void
 SplayNode<V>::destroy(SPLAYFREE * free_func)
 {
-    if (!this)
-        return;
-
     if (left)
         left->destroy(free_func);
 
@@ -164,9 +148,6 @@
 SplayNode<V> *
 SplayNode<V>::remove(Value const dataToRemove, SPLAYCMP * compare)
 {
-    if (this == NULL)
-        return NULL;
-
     SplayNode<V> *result = splay(dataToRemove, compare);
 
     if (splayLastResult == 0) { /* found it */
@@ -194,13 +175,6 @@
 {
     /* create node to insert */
     SplayNode<V> *newNode = new SplayNode<V>(dataToInsert);
-
-    if (this == NULL) {
-        splayLastResult = -1;
-        newNode->left = newNode->right = NULL;
-        return newNode;
-    }
-
     SplayNode<V> *newTop = splay(dataToInsert, compare);
 
     if (splayLastResult < 0) {
@@ -225,12 +199,6 @@
 SplayNode<V> *
 SplayNode<V>::splay(FindValue const &dataToFind, int( * compare)(FindValue const &a, Value const &b)) const
 {
-    if (this == NULL) {
-        /* can't have compared successfully :} */
-        splayLastResult = -1;
-        return NULL;
-    }
-
     Value temp = Value();
     SplayNode<V> N(temp);
     SplayNode<V> *l;
@@ -316,6 +284,9 @@
 typename Splay<V>::Value const *
 Splay<V>::find (FindValue const &value, int( * compare)(FindValue const &a, Value const &b)) const
 {
+    if (head == NULL)
+        return NULL;
+
     head = head->splay(value, compare);
 
     if (splayLastResult != 0)
@@ -328,8 +299,13 @@
 void
 Splay<V>::insert(Value const &value, SPLAYCMP *compare)
 {
-    assert (!find (value, compare));
-    head = head->insert(value, compare);
+    if (find(value, compare) != NULL) // ignore duplicates
+        return;
+
+    if (head == NULL)
+        head = new SplayNode<V>(value);
+    else
+        head = head->insert(value, compare);
     ++elements;
 }
 
@@ -513,7 +489,5 @@
     return toVisit.top()->data;
 }
 
-#endif /* cplusplus */
-
 #endif /* SQUID_SPLAY_H */
 
diff -u -r -N squid-3.5.1/include/version.h squid-3.5.2/include/version.h
--- squid-3.5.1/include/version.h	2015-01-13 04:54:26.000000000 -0800
+++ squid-3.5.2/include/version.h	2015-02-18 04:18:57.000000000 -0800
@@ -7,7 +7,7 @@
  */
 
 #ifndef SQUID_RELEASE_TIME
-#define SQUID_RELEASE_TIME 1421153513
+#define SQUID_RELEASE_TIME 1424261814
 #endif
 
 /*
diff -u -r -N squid-3.5.1/lib/MemPoolChunked.cc squid-3.5.2/lib/MemPoolChunked.cc
--- squid-3.5.1/lib/MemPoolChunked.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/lib/MemPoolChunked.cc	2015-02-18 04:17:02.000000000 -0800
@@ -141,16 +141,11 @@
     pool->allChunks.insert(this, memCompChunks);
 }
 
-MemPoolChunked::MemPoolChunked(const char *aLabel, size_t aSize) : MemImplementingAllocator(aLabel, aSize)
+MemPoolChunked::MemPoolChunked(const char *aLabel, size_t aSize) :
+    MemImplementingAllocator(aLabel, aSize) , chunk_size(0),
+    chunk_capacity(0), chunkCount(0), freeCache(0), nextFreeChunk(0),
+    Chunks(0), allChunks(Splay<MemChunk *>())
 {
-    chunk_size = 0;
-    chunk_capacity = 0;
-    chunkCount = 0;
-    freeCache = 0;
-    nextFreeChunk = 0;
-    Chunks = 0;
-    next = 0;
-
     setChunkSize(MEM_CHUNK_SIZE);
 
 #if HAVE_MALLOPT && M_MMAP_MAX
@@ -367,8 +362,6 @@
     MemChunk *chunk, *freechunk, *listTail;
     time_t age;
 
-    if (!this)
-        return;
     if (!Chunks)
         return;
 
diff -u -r -N squid-3.5.1/RELEASENOTES.html squid-3.5.2/RELEASENOTES.html
--- squid-3.5.1/RELEASENOTES.html	2015-01-13 05:45:58.000000000 -0800
+++ squid-3.5.2/RELEASENOTES.html	2015-02-18 04:57:35.000000000 -0800
@@ -2,10 +2,10 @@
 <HTML>
 <HEAD>
  <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.69">
- <TITLE>Squid 3.5.1 release notes</TITLE>
+ <TITLE>Squid 3.5.2 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 3.5.1 release notes</H1>
+<H1>Squid 3.5.2 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -63,10 +63,10 @@
 <HR>
 <H2><A NAME="s1">1.</A> <A HREF="#toc1">Notice</A></H2>
 
-<P>The Squid Team are pleased to announce the release of Squid-3.5.1 for testing.</P>
+<P>The Squid Team are pleased to announce the release of Squid-3.5.2.</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v3/3.5/">http://www.squid-cache.org/Versions/v3/3.5/</A> or the
-<A HREF="http://www.squid-cache.org/Mirrors/http-mirrors.html">mirrors</A>.</P>
+<A HREF="http://www.squid-cache.org/Download/http-mirrors.html">mirrors</A>.</P>
 
 <P>Some interesting new features adding system flexibility have been added along with general improvements all around.
 While this release is not fully bug-free we believe it is ready for use in production on many systems.</P>
@@ -322,7 +322,7 @@
 receive traffic from client software sending in this protocol.
 HTTP traffic without the PROXY header is not accepted on such a port.</P>
 
-<P>The <EM>accel</EM> and <EM>intercept</EM> options are still used to identify the
+<P>The <EM>accel</EM> and <EM>intercept</EM> options are still used to identify the HTTP
 traffic syntax being delivered by the client proxy.</P>
 
 <P>Squid can be configured by adding an <EM>http_port</EM>
@@ -414,17 +414,13 @@
 Collapsing of requests is performed across SMP workers.</P>
 
 <DT><B>ftp_client_idle_timeout</B><DD>
-<P>This new configuration directive controls how long Squid should
-wait for an FTP request on a connection to an ftp_port.  Many FTP
-clients do not deal with idle connection closures well,
-necessitating a longer default timeout (30 minutes) than
-client_idle_pconn_timeout used for incoming HTTP requests (2
-minutes). The current default may be changed as we get more
-experience with FTP relaying.</P>
-
-<DT><B>ftp_client_idle_timeout</B><DD>
 <P>New directive controlling how long to wait for an FTP request on a
 client connection to Squid <EM>ftp_port</EM>.</P>
+<P>Many FTP clients do not deal with idle connection closures well,
+necessitating a longer default timeout (30 minutes) than
+<EM>client_idle_pconn_timeout</EM> used for incoming HTTP requests (2
+minutes).</P>
+<P>The current default may be changed as we get more experience with FTP relaying.</P>
 
 <DT><B>ftp_port</B><DD>
 <P>New configuration directive to accept and relay native FTP
diff -u -r -N squid-3.5.1/src/acl/Acl.cc squid-3.5.2/src/acl/Acl.cc
--- squid-3.5.1/src/acl/Acl.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/Acl.cc	2015-02-18 04:17:02.000000000 -0800
@@ -377,7 +377,7 @@
 
 ACL::~ACL()
 {
-    debugs(28, 3, "ACL::~ACL: '" << cfgline << "'");
+    debugs(28, 3, "freeing ACL " << name);
     safe_free(cfgline);
     AclMatchedName = NULL; // in case it was pointing to our name
 }
diff -u -r -N squid-3.5.1/src/acl/Arp.cc squid-3.5.2/src/acl/Arp.cc
--- squid-3.5.1/src/acl/Arp.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/Arp.cc	2015-02-18 04:17:02.000000000 -0800
@@ -20,10 +20,7 @@
 #include "globals.h"
 #include "ip/Address.h"
 
-static void aclParseArpList(SplayNode<Eui::Eui48 *> **curlist);
-static int aclMatchArp(SplayNode<Eui::Eui48 *> **dataptr, Ip::Address &c);
-static SplayNode<Eui::Eui48 *>::SPLAYCMP aclArpCompare;
-static SplayNode<Eui::Eui48 *>::SPLAYWALKEE aclDumpArpListWalkee;
+#include <algorithm>
 
 ACL *
 ACLARP::clone() const
@@ -31,19 +28,11 @@
     return new ACLARP(*this);
 }
 
-ACLARP::ACLARP (char const *theClass) : data (NULL), class_ (theClass)
+ACLARP::ACLARP (char const *theClass) : class_ (theClass)
 {}
 
-ACLARP::ACLARP (ACLARP const & old) : data (NULL), class_ (old.class_)
+ACLARP::ACLARP (ACLARP const & old) : class_ (old.class_), aclArpData(old.aclArpData)
 {
-    /* we don't have copy constructors for the data yet */
-    assert (!old.data);
-}
-
-ACLARP::~ACLARP()
-{
-    if (data)
-        data->destroy(SplayNode<Eui::Eui48*>::DefaultFree);
 }
 
 char const *
@@ -55,7 +44,7 @@
 bool
 ACLARP::empty () const
 {
-    return data->empty();
+    return aclArpData.empty();
 }
 
 /* ==== BEGIN ARP ACL SUPPORT ============================================= */
@@ -93,14 +82,14 @@
 
     if (sscanf(t, "%[0-9a-fA-F:]", buf) != 1) {
         debugs(28, DBG_CRITICAL, "aclParseArpData: Bad ethernet address: '" << t << "'");
-        safe_free(q);
+        delete q;
         return NULL;
     }
 
     if (!q->decode(buf)) {
         debugs(28, DBG_CRITICAL, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
         debugs(28, DBG_CRITICAL, "aclParseArpData: Ignoring invalid ARP acl entry: can't parse '" << buf << "'");
-        safe_free(q);
+        delete q;
         return NULL;
     }
 
@@ -113,21 +102,11 @@
 void
 ACLARP::parse()
 {
-    aclParseArpList(&data);
-}
-
-void
-aclParseArpList(SplayNode<Eui::Eui48 *> **curlist)
-{
-    char *t = NULL;
-    SplayNode<Eui::Eui48*> **Top = curlist;
-    Eui::Eui48 *q = NULL;
-
-    while ((t = strtokFile())) {
-        if ((q = aclParseArpData(t)) == NULL)
-            continue;
-
-        *Top = (*Top)->insert(q, aclArpCompare);
+    while (const char *t = strtokFile()) {
+        if (Eui::Eui48 *q = aclParseArpData(t)) {
+            aclArpData.insert(*q);
+            delete q;
+        }
     }
 }
 
@@ -142,51 +121,20 @@
         return 0;
     }
 
-    return aclMatchArp(&data, checklist->src_addr);
-}
-
-/***************/
-/* aclMatchArp */
-/***************/
-int
-aclMatchArp(SplayNode<Eui::Eui48 *> **dataptr, Ip::Address &c)
-{
-    Eui::Eui48 result;
-    SplayNode<Eui::Eui48 *> **Top = dataptr;
-
-    if (result.lookup(c)) {
-        /* Do ACL match lookup */
-        *Top = (*Top)->splay(&result, aclArpCompare);
-        debugs(28, 3, "aclMatchArp: '" << c << "' " << (splayLastResult ? "NOT found" : "found"));
-        return (0 == splayLastResult);
-    }
-
-    /*
-     * Address was not found on any interface
-     */
-    debugs(28, 3, "aclMatchArp: " << c << " NOT found");
-    return 0;
-}
-
-static int
-aclArpCompare(Eui::Eui48 * const &a, Eui::Eui48 * const &b)
-{
-    return memcmp(a, b, sizeof(Eui::Eui48));
-}
-
-static void
-aclDumpArpListWalkee(Eui::Eui48 * const &node, void *state)
-{
-    static char buf[48];
-    node->encode(buf, 48);
-    static_cast<SBufList *>(state)->push_back(SBuf(buf));
+    Eui::Eui48 lookingFor;
+    lookingFor.lookup(checklist->src_addr);
+    return (aclArpData.find(lookingFor) != aclArpData.end());
 }
 
 SBufList
 ACLARP::dump() const
 {
     SBufList sl;
-    data->walk(aclDumpArpListWalkee, &sl);
+    for (AclArpData_t::iterator i = aclArpData.begin(); i != aclArpData.end(); ++i) {
+        char buf[48];
+        i->encode(buf,48);
+        sl.push_back(SBuf(buf));
+    }
     return sl;
 }
 
diff -u -r -N squid-3.5.1/src/acl/Arp.h squid-3.5.2/src/acl/Arp.h
--- squid-3.5.1/src/acl/Arp.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/Arp.h	2015-02-18 04:17:02.000000000 -0800
@@ -11,7 +11,8 @@
 
 #include "acl/Acl.h"
 #include "acl/Checklist.h"
-#include "splay.h"
+
+#include <set>
 
 namespace Eui
 {
@@ -27,7 +28,7 @@
 
     ACLARP(char const *);
     ACLARP(ACLARP const &);
-    ~ACLARP();
+    ~ACLARP() {}
     ACLARP&operator=(ACLARP const &);
 
     virtual ACL *clone()const;
@@ -40,8 +41,9 @@
 protected:
     static Prototype RegistryProtoype;
     static ACLARP RegistryEntry_;
-    SplayNode<Eui::Eui48 *> *data;
     char const *class_;
+    typedef std::set<Eui::Eui48> AclArpData_t;
+    AclArpData_t aclArpData;
 };
 
 MEMPROXY_CLASS_INLINE(ACLARP);
diff -u -r -N squid-3.5.1/src/acl/CertificateData.cc squid-3.5.2/src/acl/CertificateData.cc
--- squid-3.5.1/src/acl/CertificateData.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/CertificateData.cc	2015-02-18 04:17:02.000000000 -0800
@@ -71,25 +71,20 @@
     return values.match(value);
 }
 
-static void
-aclDumpAttributeListWalkee(char * const & node_data, void *outlist)
-{
-    /* outlist is really a SBufList * */
-    static_cast<SBufList *>(outlist)->push_back(SBuf(node_data));
-}
-
 SBufList
 ACLCertificateData::dump() const
 {
     SBufList sl;
     if (validAttributesStr)
         sl.push_back(SBuf(attribute));
-    /* damn this is VERY inefficient for long ACL lists... filling
-     * a wordlist this way costs Sum(1,N) iterations. For instance
-     * a 1000-elements list will be filled in 499500 iterations.
-     */
-    /* XXX FIXME: don't break abstraction */
-    values.values->walk(aclDumpAttributeListWalkee, &sl);
+
+#if __cplusplus >= 201103L
+    sl.splice(sl.end(),values.dump());
+#else
+    // temp is needed until c++11 move constructor
+    SBufList tmp = values.dump();
+    sl.splice(sl.end(),tmp);
+#endif
     return sl;
 }
 
diff -u -r -N squid-3.5.1/src/acl/DestinationIp.cc squid-3.5.2/src/acl/DestinationIp.cc
--- squid-3.5.1/src/acl/DestinationIp.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/DestinationIp.cc	2015-02-18 04:17:02.000000000 -0800
@@ -29,6 +29,10 @@
 {
     ACLFilledChecklist *checklist = Filled(cl);
 
+    // if there is no HTTP request details fallback to the dst_addr
+    if (!checklist->request)
+        return ACLIP::match(checklist->dst_addr);
+
     // Bug 3243: CVE 2009-0801
     // Bypass of browser same-origin access control in intercepted communication
     // To resolve this we will force DIRECT and only to the original client destination.
diff -u -r -N squid-3.5.1/src/acl/DestinationIp.h squid-3.5.2/src/acl/DestinationIp.h
--- squid-3.5.1/src/acl/DestinationIp.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/DestinationIp.h	2015-02-18 04:17:02.000000000 -0800
@@ -33,7 +33,6 @@
     ACLDestinationIP(): ACLIP(ACLDestinationIP::SupportedFlags) {}
     virtual char const *typeString() const;
     virtual int match(ACLChecklist *checklist);
-    virtual bool requiresRequest() const {return true;}
 
     virtual ACL *clone()const;
 
diff -u -r -N squid-3.5.1/src/acl/DomainData.cc squid-3.5.2/src/acl/DomainData.cc
--- squid-3.5.1/src/acl/DomainData.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/DomainData.cc	2015-02-18 04:17:02.000000000 -0800
@@ -24,8 +24,10 @@
 
 ACLDomainData::~ACLDomainData()
 {
-    if (domains)
+    if (domains) {
         domains->destroy(xRefFree);
+        delete domains;
+    }
 }
 
 template<class T>
@@ -105,30 +107,27 @@
 
     debugs(28, 3, "aclMatchDomainList: checking '" << host << "'");
 
-    domains = domains->splay((char *)host, aclHostDomainCompare);
+    char *h = const_cast<char *>(host);
+    char const * const * result = domains->find(h, aclHostDomainCompare);
 
-    debugs(28, 3, "aclMatchDomainList: '" << host << "' " << (splayLastResult ? "NOT found" : "found"));
+    debugs(28, 3, "aclMatchDomainList: '" << host << "' " << (result ? "found" : "NOT found"));
 
-    return !splayLastResult;
+    return (result != NULL);
 }
 
-static void
-aclDumpDomainListWalkee(char * const & node_data, void *outlist)
-{
-    /* outlist is really a SBufList ** */
-    static_cast<SBufList *>(outlist)->push_back(SBuf(node_data));
-}
+struct AclDomainDataDumpVisitor {
+    SBufList contents;
+    void operator() (char * const & node_data) {
+        contents.push_back(SBuf(node_data));
+    }
+};
 
 SBufList
 ACLDomainData::dump() const
 {
-    SBufList sl;
-    /* damn this is VERY inefficient for long ACL lists... filling
-     * a wordlist this way costs Sum(1,N) iterations. For instance
-     * a 1000-elements list will be filled in 499500 iterations.
-     */
-    domains->walk(aclDumpDomainListWalkee, &sl);
-    return sl;
+    AclDomainDataDumpVisitor visitor;
+    domains->visit(visitor);
+    return visitor.contents;
 }
 
 void
@@ -136,9 +135,12 @@
 {
     char *t = NULL;
 
+    if (!domains)
+        domains = new Splay<char *>();
+
     while ((t = strtokFile())) {
         Tolower(t);
-        domains = domains->insert(xstrdup(t), aclDomainCompare);
+        domains->insert(xstrdup(t), aclDomainCompare);
     }
 }
 
diff -u -r -N squid-3.5.1/src/acl/DomainData.h squid-3.5.2/src/acl/DomainData.h
--- squid-3.5.1/src/acl/DomainData.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/DomainData.h	2015-02-18 04:17:02.000000000 -0800
@@ -27,7 +27,7 @@
     bool empty() const;
     virtual ACLData<char const *> *clone() const;
 
-    SplayNode<char *> *domains;
+    Splay<char *> *domains;
 };
 
 MEMPROXY_CLASS_INLINE(ACLDomainData);
diff -u -r -N squid-3.5.1/src/acl/Eui64.cc squid-3.5.2/src/acl/Eui64.cc
--- squid-3.5.1/src/acl/Eui64.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/Eui64.cc	2015-02-18 04:17:02.000000000 -0800
@@ -20,30 +20,17 @@
 #include "globals.h"
 #include "ip/Address.h"
 
-static void aclParseEuiList(SplayNode<Eui::Eui64 *> **curlist);
-static int aclMatchEui(SplayNode<Eui::Eui64 *> **dataptr, Ip::Address &c);
-static SplayNode<Eui::Eui64 *>::SPLAYCMP aclEui64Compare;
-static SplayNode<Eui::Eui64 *>::SPLAYWALKEE aclDumpEuiListWalkee;
-
 ACL *
 ACLEui64::clone() const
 {
     return new ACLEui64(*this);
 }
 
-ACLEui64::ACLEui64 (char const *theClass) : data (NULL), class_ (theClass)
+ACLEui64::ACLEui64 (char const *theClass) : class_ (theClass)
 {}
 
-ACLEui64::ACLEui64 (ACLEui64 const & old) : data (NULL), class_ (old.class_)
-{
-    /* we don't have copy constructors for the data yet */
-    assert (!old.data);
-}
-
-ACLEui64::~ACLEui64()
+ACLEui64::ACLEui64 (ACLEui64 const & old) : eui64Data(old.eui64Data), class_ (old.class_)
 {
-    if (data)
-        data->destroy(SplayNode<Eui::Eui64*>::DefaultFree);
 }
 
 char const *
@@ -55,7 +42,7 @@
 bool
 ACLEui64::empty () const
 {
-    return data->empty();
+    return eui64Data.empty();
 }
 
 Eui::Eui64 *
@@ -67,14 +54,14 @@
 
     if (sscanf(t, "%[0-9a-fA-F:]", buf) != 1) {
         debugs(28, DBG_CRITICAL, "aclParseEuiData: Bad EUI-64 address: '" << t << "'");
-        safe_free(q);
+        delete q;
         return NULL;
     }
 
     if (!q->decode(buf)) {
         debugs(28, DBG_CRITICAL, "" << cfg_filename << " line " << config_lineno << ": " << config_input_line);
         debugs(28, DBG_CRITICAL, "aclParseEuiData: Ignoring invalid EUI-64 acl entry: can't parse '" << buf << "'");
-        safe_free(q);
+        delete q;
         return NULL;
     }
 
@@ -87,21 +74,11 @@
 void
 ACLEui64::parse()
 {
-    aclParseEuiList(&data);
-}
-
-void
-aclParseEuiList(SplayNode<Eui::Eui64 *> **curlist)
-{
-    char *t = NULL;
-    SplayNode<Eui::Eui64*> **Top = curlist;
-    Eui::Eui64 *q = NULL;
-
-    while ((t = strtokFile())) {
-        if ((q = aclParseEuiData(t)) == NULL)
-            continue;
-
-        *Top = (*Top)->insert(q, aclEui64Compare);
+    while (const char * t = strtokFile()) {
+        if (Eui::Eui64 * q = aclParseEuiData(t)) {
+            eui64Data.insert(*q);
+            delete q;
+        }
     }
 }
 
@@ -116,52 +93,27 @@
         return 0;
     }
 
-    return aclMatchEui(&data, checklist->src_addr);
-}
-
-/***************/
-/* aclMatchEui */
-/***************/
-int
-aclMatchEui(SplayNode<Eui::Eui64 *> **dataptr, Ip::Address &c)
-{
-    Eui::Eui64 result;
-    SplayNode<Eui::Eui64 *> **Top = dataptr;
+    Eui::Eui64 lookingFor;
+    if (lookingFor.lookup(checklist->src_addr)) {
+        bool found = (eui64Data.find(lookingFor) != eui64Data.end());
+        debugs(28, 3,  checklist->src_addr << "' " << (found ? "found" : "NOT found"));
+        return found;
+    }
 
-    if (result.lookup(c)) {
-        /* Do ACL match lookup */
-        *Top = (*Top)->splay(&result, aclEui64Compare);
-        debugs(28, 3, "aclMatchEui: '" << c << "' " << (splayLastResult ? "NOT found" : "found"));
-        return (0 == splayLastResult);
-    }
-
-    /*
-     * Address was not found on any interface
-     */
-    debugs(28, 3, "aclMatchEui: " << c << " NOT found");
+    debugs(28, 3, checklist->src_addr << " NOT found");
     return 0;
 }
 
-static int
-aclEui64Compare(Eui::Eui64 * const &a, Eui::Eui64 * const &b)
-{
-    return memcmp(a, b, sizeof(Eui::Eui64));
-}
-
-static void
-aclDumpEuiListWalkee(Eui::Eui64 * const &node, void *state)
-{
-    static char buf[48];
-    node->encode(buf, 48);
-    static_cast<SBufList *>(state)->push_back(SBuf(buf));
-}
-
 SBufList
 ACLEui64::dump() const
 {
-    SBufList w;
-    data->walk(aclDumpEuiListWalkee, &w);
-    return w;
+    SBufList sl;
+    for (Eui64Data_t::iterator i = eui64Data.begin(); i != eui64Data.end(); ++i) {
+        static char buf[48];
+        i->encode(buf,48);
+        sl.push_back(SBuf(buf));
+    }
+    return sl;
 }
 
 #endif /* USE_SQUID_EUI */
diff -u -r -N squid-3.5.1/src/acl/Eui64.h squid-3.5.2/src/acl/Eui64.h
--- squid-3.5.1/src/acl/Eui64.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/Eui64.h	2015-02-18 04:17:02.000000000 -0800
@@ -11,7 +11,8 @@
 
 #include "acl/Acl.h"
 #include "acl/Checklist.h"
-#include "splay.h"
+
+#include <set>
 
 namespace Eui
 {
@@ -27,7 +28,7 @@
 
     ACLEui64(char const *);
     ACLEui64(ACLEui64 const &);
-    ~ACLEui64();
+    ~ACLEui64() {}
     ACLEui64&operator=(ACLEui64 const &);
 
     virtual ACL *clone()const;
@@ -40,7 +41,8 @@
 protected:
     static Prototype RegistryProtoype;
     static ACLEui64 RegistryEntry_;
-    SplayNode<Eui::Eui64 *> *data;
+    typedef std::set<Eui::Eui64> Eui64Data_t;
+    Eui64Data_t eui64Data;
     char const *class_;
 };
 
diff -u -r -N squid-3.5.1/src/acl/HttpHeaderData.cc squid-3.5.2/src/acl/HttpHeaderData.cc
--- squid-3.5.1/src/acl/HttpHeaderData.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/HttpHeaderData.cc	2015-02-18 04:17:02.000000000 -0800
@@ -60,9 +60,13 @@
 {
     SBufList sl;
     sl.push_back(SBuf(hdrName));
+#if __cplusplus >= 201103L
+    sl.splice(sl.end(), regex_rule->dump());
+#else
     // temp is needed until c++11 move-constructor
     SBufList temp = regex_rule->dump();
     sl.splice(sl.end(), temp);
+#endif
     return sl;
 }
 
diff -u -r -N squid-3.5.1/src/acl/HttpStatus.cc squid-3.5.2/src/acl/HttpStatus.cc
--- squid-3.5.1/src/acl/HttpStatus.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/HttpStatus.cc	2015-02-18 04:17:02.000000000 -0800
@@ -17,9 +17,9 @@
 
 #include <climits>
 
-static void aclParseHTTPStatusList(SplayNode<acl_httpstatus_data *> **curlist);
+static void aclParseHTTPStatusList(Splay<acl_httpstatus_data *> **curlist);
 static int aclHTTPStatusCompare(acl_httpstatus_data * const &a, acl_httpstatus_data * const &b);
-static int aclMatchHTTPStatus(SplayNode<acl_httpstatus_data*> **dataptr, Http::StatusCode status);
+static int aclMatchHTTPStatus(Splay<acl_httpstatus_data*> **dataptr, Http::StatusCode status);
 
 acl_httpstatus_data::acl_httpstatus_data(int x) : status1(x), status2(x) { ; }
 
@@ -74,8 +74,10 @@
 
 ACLHTTPStatus::~ACLHTTPStatus()
 {
-    if (data)
-        data->destroy(SplayNode<acl_httpstatus_data*>::DefaultFree);
+    if (data) {
+        data->destroy();
+        delete data;
+    }
 }
 
 char const *
@@ -109,21 +111,23 @@
 void
 ACLHTTPStatus::parse()
 {
+    if (!data)
+        data = new Splay<acl_httpstatus_data*>();
+
     aclParseHTTPStatusList (&data);
 }
 
 void
-aclParseHTTPStatusList(SplayNode<acl_httpstatus_data *> **curlist)
+aclParseHTTPStatusList(Splay<acl_httpstatus_data *> **curlist)
 {
     char *t = NULL;
-    SplayNode<acl_httpstatus_data*> **Top = curlist;
     acl_httpstatus_data *q = NULL;
 
     while ((t = strtokFile())) {
         if ((q = aclParseHTTPStatusData(t)) == NULL)
             continue;
 
-        *Top = (*Top)->insert(q, acl_httpstatus_data::compare);
+        (*curlist)->insert(q, acl_httpstatus_data::compare);
     }
 }
 
@@ -134,15 +138,13 @@
 }
 
 int
-aclMatchHTTPStatus(SplayNode<acl_httpstatus_data*> **dataptr, const Http::StatusCode status)
+aclMatchHTTPStatus(Splay<acl_httpstatus_data*> **dataptr, const Http::StatusCode status)
 {
-
     acl_httpstatus_data X(status);
-    SplayNode<acl_httpstatus_data*> **Top = dataptr;
-    *Top = Top[0]->splay(&X, aclHTTPStatusCompare);
+    const acl_httpstatus_data * const * result = (*dataptr)->find(&X, aclHTTPStatusCompare);
 
-    debugs(28, 3, "aclMatchHTTPStatus: '" << status << "' " << (splayLastResult ? "NOT found" : "found"));
-    return (0 == splayLastResult);
+    debugs(28, 3, "aclMatchHTTPStatus: '" << status << "' " << (result ? "found" : "NOT found"));
+    return (result != NULL);
 }
 
 static int
@@ -157,18 +159,18 @@
     return 0;
 }
 
-static void
-aclDumpHTTPStatusListWalkee(acl_httpstatus_data * const &node, void *state)
-{
-    // state is a SBufList*
-    static_cast<SBufList *>(state)->push_back(node->toStr());
-}
+struct HttpStatusAclDumpVisitor {
+    SBufList contents;
+    void operator() (const acl_httpstatus_data * node) {
+        contents.push_back(node->toStr());
+    }
+};
 
 SBufList
 ACLHTTPStatus::dump() const
 {
-    SBufList w;
-    data->walk(aclDumpHTTPStatusListWalkee, &w);
-    return w;
+    HttpStatusAclDumpVisitor visitor;
+    data->visit(visitor);
+    return visitor.contents;
 }
 
diff -u -r -N squid-3.5.1/src/acl/HttpStatus.h squid-3.5.2/src/acl/HttpStatus.h
--- squid-3.5.1/src/acl/HttpStatus.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/HttpStatus.h	2015-02-18 04:17:02.000000000 -0800
@@ -46,7 +46,7 @@
 protected:
     static Prototype RegistryProtoype;
     static ACLHTTPStatus RegistryEntry_;
-    SplayNode<acl_httpstatus_data*> *data;
+    Splay<acl_httpstatus_data*> *data;
     char const *class_;
 };
 
diff -u -r -N squid-3.5.1/src/acl/Ip.cc squid-3.5.2/src/acl/Ip.cc
--- squid-3.5.1/src/acl/Ip.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/Ip.cc	2015-02-18 04:17:02.000000000 -0800
@@ -31,18 +31,6 @@
 }
 
 /**
- * Writes an IP ACL data into a buffer, then copies the buffer into the wordlist given
- *
- \param ip  ACL data structure to display
- \param state   wordlist structure which is being generated
- */
-void
-ACLIP::DumpIpListWalkee(acl_ip_data * const & ip, void *state)
-{
-    static_cast<SBufList *>(state)->push_back(ip->toSBuf());
-}
-
-/**
  * print/format an acl_ip_data structure for debugging output.
  *
  \param buf string buffer to write to
@@ -485,6 +473,9 @@
 void
 ACLIP::parse()
 {
+    if (data == NULL)
+        data = new IPSplay();
+
     flags.parseFlags();
 
     while (char *t = strtokFile()) {
@@ -494,7 +485,8 @@
             /* pop each result off the list and add it to the data tree individually */
             acl_ip_data *next_node = q->next;
             q->next = NULL;
-            data = data->insert(q, acl_ip_data::NetworkCompare);
+            if (!data->find(q,acl_ip_data::NetworkCompare))
+                data->insert(q, acl_ip_data::NetworkCompare);
             q = next_node;
         }
     }
@@ -502,16 +494,25 @@
 
 ACLIP::~ACLIP()
 {
-    if (data)
-        data->destroy(IPSplay::DefaultFree);
+    if (data) {
+        data->destroy();
+        delete data;
+    }
 }
 
+struct IpAclDumpVisitor {
+    SBufList contents;
+    void operator() (acl_ip_data * const & ip) {
+        contents.push_back(ip->toSBuf());
+    }
+};
+
 SBufList
 ACLIP::dump() const
 {
-    SBufList sl;
-    data->walk(DumpIpListWalkee, &sl);
-    return sl;
+    IpAclDumpVisitor visitor;
+    data->visit(visitor);
+    return visitor.contents;
 }
 
 bool
@@ -534,9 +535,9 @@
     ClientAddress.addr2.setEmpty();
     ClientAddress.mask.setEmpty();
 
-    data = data->splay(&ClientAddress, aclIpAddrNetworkCompare);
-    debugs(28, 3, "aclIpMatchIp: '" << clientip << "' " << (splayLastResult ? "NOT found" : "found"));
-    return !splayLastResult;
+    const acl_ip_data * const * result =  data->find(&ClientAddress, aclIpAddrNetworkCompare);
+    debugs(28, 3, "aclIpMatchIp: '" << clientip << "' " << (result ? "found" : "NOT found"));
+    return (result != NULL);
 }
 
 acl_ip_data::acl_ip_data() :addr1(), addr2(), mask(), next (NULL) {}
diff -u -r -N squid-3.5.1/src/acl/Ip.h squid-3.5.2/src/acl/Ip.h
--- squid-3.5.1/src/acl/Ip.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/Ip.h	2015-02-18 04:17:02.000000000 -0800
@@ -57,7 +57,7 @@
 
     ~ACLIP();
 
-    typedef SplayNode<acl_ip_data *> IPSplay;
+    typedef Splay<acl_ip_data *> IPSplay;
 
     virtual char const *typeString() const = 0;
     virtual void parse();
@@ -71,8 +71,6 @@
     int match(Ip::Address &);
     IPSplay *data;
 
-private:
-    static void DumpIpListWalkee(acl_ip_data * const & ip, void *state);
 };
 
 #endif /* SQUID_ACLIP_H */
diff -u -r -N squid-3.5.1/src/acl/NoteData.cc squid-3.5.2/src/acl/NoteData.cc
--- squid-3.5.1/src/acl/NoteData.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/NoteData.cc	2015-02-18 04:17:02.000000000 -0800
@@ -64,9 +64,13 @@
 {
     SBufList sl;
     sl.push_back(SBuf(name));
+#if __cplusplus >= 201103L
+    sl.splice(sl.end(), values->dump());
+#else
     // temp is needed until c++11 move constructor
     SBufList temp = values->dump();
     sl.splice(sl.end(), temp);
+#endif
     return sl;
 }
 
diff -u -r -N squid-3.5.1/src/acl/StringData.cc squid-3.5.2/src/acl/StringData.cc
--- squid-3.5.1/src/acl/StringData.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/StringData.cc	2015-02-18 04:17:02.000000000 -0800
@@ -14,70 +14,36 @@
 #include "cache_cf.h"
 #include "Debug.h"
 
-ACLStringData::ACLStringData() : values (NULL)
-{}
-
-ACLStringData::ACLStringData(ACLStringData const &old) : values (NULL)
-{
-    assert (!old.values);
-}
-
-template<class T>
-inline void
-xRefFree(T &thing)
+ACLStringData::ACLStringData(ACLStringData const &old) : stringValues(old.stringValues)
 {
-    xfree (thing);
-}
-
-ACLStringData::~ACLStringData()
-{
-    if (values)
-        values->destroy(xRefFree);
-}
-
-static int
-splaystrcmp (char * const &l, char * const &r)
-{
-    return strcmp (l,r);
 }
 
 void
 ACLStringData::insert(const char *value)
 {
-    values = values->insert(xstrdup(value), splaystrcmp);
+    stringValues.insert(SBuf(value));
 }
 
 bool
 ACLStringData::match(char const *toFind)
 {
-    if (!values || !toFind)
+    if (stringValues.empty() || !toFind)
         return 0;
 
-    debugs(28, 3, "aclMatchStringList: checking '" << toFind << "'");
+    SBuf tf(toFind);
+    debugs(28, 3, "aclMatchStringList: checking '" << tf << "'");
 
-    values = values->splay((char *)toFind, splaystrcmp);
+    bool found = (stringValues.find(tf) != stringValues.end());
+    debugs(28, 3, "aclMatchStringList: '" << tf << "' " << (found ? "found" : "NOT found"));
 
-    debugs(28, 3, "aclMatchStringList: '" << toFind << "' " << (splayLastResult ? "NOT found" : "found"));
-
-    return !splayLastResult;
-}
-
-static void
-aclDumpStringWalkee(char * const & node_data, void *outlist)
-{
-    /* outlist is really a SBufList* */
-    static_cast<SBufList*>(outlist)->push_back(SBuf(node_data));
+    return found;
 }
 
 SBufList
 ACLStringData::dump() const
 {
     SBufList sl;
-    /* damn this is VERY inefficient for long ACL lists... filling
-     * a SBufList this way costs Sum(1,N) iterations. For instance
-     * a 1000-elements list will be filled in 499500 iterations.
-     */
-    values->walk(aclDumpStringWalkee, &sl);
+    sl.insert(sl.end(), stringValues.begin(), stringValues.end());
     return sl;
 }
 
@@ -85,22 +51,20 @@
 ACLStringData::parse()
 {
     char *t;
-
     while ((t = strtokFile()))
-        values = values->insert(xstrdup(t), splaystrcmp);
+        stringValues.insert(SBuf(t));
 }
 
 bool
 ACLStringData::empty() const
 {
-    return values->empty();
+    return stringValues.empty();
 }
 
 ACLData<char const *> *
 ACLStringData::clone() const
 {
     /* Splay trees don't clone yet. */
-    assert (!values);
     return new ACLStringData(*this);
 }
 
diff -u -r -N squid-3.5.1/src/acl/StringData.h squid-3.5.2/src/acl/StringData.h
--- squid-3.5.1/src/acl/StringData.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/StringData.h	2015-02-18 04:17:02.000000000 -0800
@@ -10,7 +10,9 @@
 #define SQUID_ACLSTRINGDATA_H
 #include "acl/Acl.h"
 #include "acl/Data.h"
-#include "splay.h"
+#include "SBuf.h"
+
+#include <set>
 
 class ACLStringData : public ACLData<char const *>
 {
@@ -18,10 +20,10 @@
 public:
     MEMPROXY_CLASS(ACLStringData);
 
-    ACLStringData();
+    ACLStringData() {}
     ACLStringData(ACLStringData const &);
     ACLStringData &operator= (ACLStringData const &);
-    virtual ~ACLStringData();
+    virtual ~ACLStringData() {}
     bool match(char const *);
     virtual SBufList dump() const;
     virtual void parse();
@@ -30,7 +32,9 @@
     /// Insert a string data value
     void insert(const char *);
 
-    SplayNode<char *> *values;
+private:
+    typedef std::set<SBuf> StringValues_t;
+    StringValues_t stringValues;
 };
 
 /* TODO move into .cci files */
diff -u -r -N squid-3.5.1/src/acl/UserData.cc squid-3.5.2/src/acl/UserData.cc
--- squid-3.5.1/src/acl/UserData.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/UserData.cc	2015-02-18 04:17:02.000000000 -0800
@@ -13,39 +13,13 @@
 #include "acl/UserData.h"
 #include "ConfigParser.h"
 #include "Debug.h"
-
-template<class T>
-inline void
-xRefFree(T &thing)
-{
-    xfree (thing);
-}
-
-ACLUserData::~ACLUserData()
-{
-    if (names)
-        names->destroy(xRefFree);
-}
-
-static int
-splaystrcasecmp (char * const &l, char * const &r)
-{
-    return strcasecmp ((char *)l,(char *)r);
-}
-
-static int
-splaystrcmp (char * const &l, char * const &r)
-{
-    return strcmp ((char *)l,(char *)r);
-}
+#include "globals.h"
+#include "SBufAlgos.h"
 
 bool
 ACLUserData::match(char const *user)
 {
-    SplayNode<char *> *Top = names;
-
-    debugs(28, 7, "aclMatchUser: user is " << user << ", case_insensitive is " << flags.case_insensitive);
-    debugs(28, 8, "Top is " << Top << ", Top->data is " << ((char *) (Top != NULL ? (Top)->data : "Unavailable")));
+    debugs(28, 7, "user is " << user << ", case_insensitive is " << flags.case_insensitive);
 
     if (user == NULL || strcmp(user, "-") == 0)
         return 0;
@@ -55,25 +29,9 @@
         return 1;
     }
 
-    if (flags.case_insensitive)
-        Top = Top->splay((char *)user, splaystrcasecmp);
-    else
-        Top = Top->splay((char *)user, splaystrcmp);
-
-    /* Top=splay_splay(user,Top,(splayNode::SPLAYCMP *)dumping_strcmp); */
-    debugs(28, 7, "aclMatchUser: returning " << !splayLastResult << ",Top is " <<
-           Top << ", Top->data is " << ((char *) (Top ? Top->data : "Unavailable")));
-
-    names = Top;
-
-    return !splayLastResult;
-}
-
-static void
-aclDumpUserListWalkee(char * const & node_data, void *outlist)
-{
-    /* outlist is really a SBufList* */
-    static_cast<SBufList *>(outlist)->push_back(SBuf(node_data));
+    bool result = (userDataNames.find(SBuf(user)) != userDataNames.end());
+    debugs(28, 7, "returning " << result);
+    return result;
 }
 
 SBufList
@@ -89,65 +47,94 @@
     if (flags.case_insensitive)
         sl.push_back(SBuf("-i"));
 
-    /* damn this is VERY inefficient for long ACL lists... filling
-     * a SBufList this way costs Sum(1,N) iterations. For instance
-     * a 1000-elements list will be filled in 499500 iterations.
-     */
-    if (names)
-        names->walk(aclDumpUserListWalkee, &sl);
+    sl.insert(sl.end(), userDataNames.begin(), userDataNames.end());
 
+    debugs(28,5, "ACLUserData dump output: " << SBufContainerJoin(userDataNames,SBuf(" ")));
     return sl;
 }
 
+static bool
+CaseInsensitveSBufCompare(const SBuf &lhs, const SBuf &rhs)
+{
+    return (lhs.caseCmp(rhs) < 0);
+}
+
+static bool
+CaseSensitveSBufCompare(const SBuf &lhs, const SBuf &rhs)
+{
+    return (lhs < rhs);
+}
+
+ACLUserData::ACLUserData() : userDataNames(CaseSensitveSBufCompare)
+{
+}
+
 void
 ACLUserData::parse()
 {
-    debugs(28, 2, "aclParseUserList: parsing user list");
-    char *t = NULL;
+    debugs(28, 2, "parsing user list");
 
+    char *t = NULL;
     if ((t = ConfigParser::strtokFile())) {
-        debugs(28, 5, "aclParseUserList: First token is " << t);
+        SBuf s(t);
+        debugs(28, 5, "first token is " << s);
 
-        if (strcmp("-i", t) == 0) {
-            debugs(28, 5, "aclParseUserList: Going case-insensitive");
+        if (s.cmp("-i",2) == 0) {
+            debugs(28, 5, "Going case-insensitive");
             flags.case_insensitive = true;
-        } else if (strcmp("REQUIRED", t) == 0) {
-            debugs(28, 5, "aclParseUserList: REQUIRED-type enabled");
+            // due to how the std::set API work, if we want to change
+            // the comparison function we have to create a new std::set
+            UserDataNames_t newUdn(CaseInsensitveSBufCompare);
+            newUdn.insert(userDataNames.begin(), userDataNames.end());
+            swap(userDataNames,newUdn);
+        } else if (s.cmp("REQUIRED") == 0) {
+            debugs(28, 5, "REQUIRED-type enabled");
             flags.required = true;
         } else {
             if (flags.case_insensitive)
-                Tolower(t);
+                s.toLower();
 
-            names = names->insert(xstrdup(t), splaystrcmp);
+            debugs(28, 6, "Adding user " << s);
+            userDataNames.insert(s);
         }
     }
 
-    debugs(28, 3, "aclParseUserList: Case-insensitive-switch is " << flags.case_insensitive);
+    debugs(28, 3, "Case-insensitive-switch is " << flags.case_insensitive);
     /* we might inherit from a previous declaration */
 
-    debugs(28, 4, "aclParseUserList: parsing user list");
+    debugs(28, 4, "parsing following tokens");
 
     while ((t = ConfigParser::strtokFile())) {
-        debugs(28, 6, "aclParseUserList: Got token: " << t);
+        SBuf s(t);
+        debugs(28, 6, "Got token: " << s);
 
         if (flags.case_insensitive)
-            Tolower(t);
+            s.toLower();
+
+        debugs(28, 6, "Adding user " << s);
+        userDataNames.insert(s);
+    }
 
-        names = names->insert(xstrdup(t), splaystrcmp);
+    if (flags.required && !userDataNames.empty()) {
+        debugs(28, DBG_PARSE_NOTE(1), "WARNING: detected attempt to add usernames to an acl of type REQUIRED");
+        userDataNames.clear();
     }
+
+    debugs(28,4, "ACL contains " << userDataNames.size() << " users");
 }
 
 bool
 ACLUserData::empty() const
 {
-    return names->empty() && !flags.required;
+    debugs(28,6,"required: " << flags.required << ", number of users: " << userDataNames.size());
+    if (flags.required)
+        return false;
+    return userDataNames.empty();
 }
 
 ACLData<char const *> *
 ACLUserData::clone() const
 {
-    /* Splay trees don't clone yet. */
-    assert (!names);
     return new ACLUserData;
 }
 
diff -u -r -N squid-3.5.1/src/acl/UserData.h squid-3.5.2/src/acl/UserData.h
--- squid-3.5.1/src/acl/UserData.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/acl/UserData.h	2015-02-18 04:17:02.000000000 -0800
@@ -10,7 +10,9 @@
 #define SQUID_ACLUSERDATA_H
 #include "acl/Acl.h"
 #include "acl/Data.h"
-#include "splay.h"
+#include "SBuf.h"
+
+#include <set>
 
 class ACLUserData : public ACLData<char const *>
 {
@@ -18,19 +20,24 @@
 public:
     MEMPROXY_CLASS(ACLUserData);
 
-    virtual ~ACLUserData();
+    virtual ~ACLUserData() {}
+    ACLUserData();
     bool match(char const *user);
     virtual SBufList dump() const;
     void parse();
     bool empty() const;
     virtual ACLData<char const *> *clone() const;
 
-    SplayNode<char *> *names;
+private:
+
+    typedef std::set<SBuf,bool(*)(const SBuf&, const SBuf&)> UserDataNames_t;
+    UserDataNames_t userDataNames;
 
     struct {
         bool case_insensitive;
         bool required;
     } flags;
+
 };
 
 MEMPROXY_CLASS_INLINE(ACLUserData);
diff -u -r -N squid-3.5.1/src/anyp/PortCfg.cc squid-3.5.2/src/anyp/PortCfg.cc
--- squid-3.5.1/src/anyp/PortCfg.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/anyp/PortCfg.cc	2015-02-18 04:17:02.000000000 -0800
@@ -119,22 +119,34 @@
     b->disable_pmtu_discovery = disable_pmtu_discovery;
     b->tcp_keepalive = tcp_keepalive;
 
-#if 0
-    // TODO: AYJ: 2009-07-18: for now SSL does not clone. Configure separate ports with IPs and SSL settings
-
 #if USE_OPENSSL
-    char *cert;
-    char *key;
-    int version;
-    char *cipher;
-    char *options;
-    char *clientca;
-    char *cafile;
-    char *capath;
-    char *crlfile;
-    char *dhfile;
-    char *sslflags;
-    char *sslContextSessionId;
+    if (cert)
+        b->cert = xstrdup(cert);
+    if (key)
+        b->key = xstrdup(key);
+    b->version = version;
+    if (cipher)
+        b->cipher = xstrdup(cipher);
+    if (options)
+        b->options = xstrdup(options);
+    if (clientca)
+        b->clientca = xstrdup(clientca);
+    if (cafile)
+        b->cafile = xstrdup(cafile);
+    if (capath)
+        b->capath = xstrdup(capath);
+    if (crlfile)
+        b->crlfile = xstrdup(crlfile);
+    if (dhfile)
+        b->dhfile = xstrdup(dhfile);
+    if (sslflags)
+        b->sslflags = xstrdup(sslflags);
+    if (sslContextSessionId)
+        b->sslContextSessionId = xstrdup(sslContextSessionId);
+
+#if 0
+    // TODO: AYJ: 2015-01-15: for now SSL does not clone the context object.
+    // cloning should only be done before the PortCfg is post-configure initialized and opened
     SSL_CTX *sslContext;
 #endif
 
diff -u -r -N squid-3.5.1/src/auth/digest/Config.cc squid-3.5.2/src/auth/digest/Config.cc
--- squid-3.5.1/src/auth/digest/Config.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/auth/digest/Config.cc	2015-02-18 04:17:02.000000000 -0800
@@ -1006,12 +1006,7 @@
         debugs(29, 2, "Username for the nonce does not equal the username for the request");
         nonce = NULL;
     }
-    /* check for stale nonce */
-    if (authDigestNonceIsStale(nonce)) {
-        debugs(29, 3, "The received nonce is stale from " << username);
-        digest_request->setDenyMessage("Stale nonce");
-        nonce = NULL;
-    }
+
     if (!nonce) {
         /* we couldn't find a matching nonce! */
         debugs(29, 2, "Unexpected or invalid nonce received from " << username);
diff -u -r -N squid-3.5.1/src/auth/digest/UserRequest.cc squid-3.5.2/src/auth/digest/UserRequest.cc
--- squid-3.5.1/src/auth/digest/UserRequest.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/auth/digest/UserRequest.cc	2015-02-18 04:17:02.000000000 -0800
@@ -173,10 +173,14 @@
     }
 
     /* check for stale nonce */
-    if (!authDigestNonceIsValid(digest_request->nonce, digest_request->nc)) {
-        debugs(29, 3, "user '" << auth_user->username() << "' validated OK but nonce stale");
-        auth_user->credentials(Auth::Handshake);
-        digest_request->setDenyMessage("Stale nonce");
+    /* check Auth::Pending to avoid loop */
+
+    if (!authDigestNonceIsValid(digest_request->nonce, digest_request->nc) && user()->credentials() != Auth::Pending) {
+        debugs(29, 3, auth_user->username() << "' validated OK but nonce stale: " << digest_request->nonceb64);
+        /* Pending prevent banner and makes a ldap control */
+        auth_user->credentials(Auth::Pending);
+        nonce->flags.valid = false;
+        authDigestNoncePurge(nonce);
         return;
     }
 
@@ -329,6 +333,8 @@
     // add new helper kv-pair notes to the credentials object
     // so that any transaction using those credentials can access them
     auth_user_request->user()->notes.appendNewOnly(&reply.notes);
+    // remove any private credentials detail which got added.
+    auth_user_request->user()->notes.remove("ha1");
 
     static bool oldHelperWarningDone = false;
     switch (reply.result) {
diff -u -r -N squid-3.5.1/src/auth/negotiate/Config.cc squid-3.5.2/src/auth/negotiate/Config.cc
--- squid-3.5.1/src/auth/negotiate/Config.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/auth/negotiate/Config.cc	2015-02-18 04:17:02.000000000 -0800
@@ -261,6 +261,8 @@
     auth_user_request->user(newUser);
     auth_user_request->user()->auth_type = Auth::AUTH_NEGOTIATE;
 
+    auth_user_request->user()->BuildUserKey(proxy_auth, aRequestRealm);
+
     /* all we have to do is identify that it's Negotiate - the helper does the rest */
     debugs(29, 9, HERE << "decode Negotiate authentication");
     return auth_user_request;
diff -u -r -N squid-3.5.1/src/auth/negotiate/UserRequest.cc squid-3.5.2/src/auth/negotiate/UserRequest.cc
--- squid-3.5.1/src/auth/negotiate/UserRequest.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/auth/negotiate/UserRequest.cc	2015-02-18 04:17:02.000000000 -0800
@@ -163,8 +163,6 @@
 void
 Auth::Negotiate::UserRequest::authenticate(HttpRequest * aRequest, ConnStateData * conn, http_hdr_type type)
 {
-    assert(this);
-
     /* Check that we are in the client side, where we can generate
      * auth challenges */
 
@@ -260,6 +258,8 @@
     // add new helper kv-pair notes to the credentials object
     // so that any transaction using those credentials can access them
     auth_user_request->user()->notes.appendNewOnly(&reply.notes);
+    // remove any private credentials detail which got added.
+    auth_user_request->user()->notes.remove("token");
 
     Auth::Negotiate::UserRequest *lm_request = dynamic_cast<Auth::Negotiate::UserRequest *>(auth_user_request.getRaw());
     assert(lm_request != NULL);
@@ -312,8 +312,7 @@
 
         /* connection is authenticated */
         debugs(29, 4, HERE << "authenticated user " << auth_user_request->user()->username());
-        /* see if this is an existing user with a different proxy_auth
-         * string */
+        /* see if this is an existing user */
         AuthUserHashPointer *usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, auth_user_request->user()->userKey()));
         Auth::User::Pointer local_auth_user = lm_request->user();
         while (usernamehash && (usernamehash->user()->auth_type != Auth::AUTH_NEGOTIATE ||
@@ -390,22 +389,3 @@
     delete r;
 }
 
-void
-Auth::Negotiate::UserRequest::addAuthenticationInfoHeader(HttpReply * rep, int accel)
-{
-    http_hdr_type type;
-
-    if (!server_blob)
-        return;
-
-    /* don't add to authentication error pages */
-    if ((!accel && rep->sline.status() == Http::scProxyAuthenticationRequired)
-            || (accel && rep->sline.status() == Http::scUnauthorized))
-        return;
-
-    type = accel ? HDR_AUTHENTICATION_INFO : HDR_PROXY_AUTHENTICATION_INFO;
-    httpHeaderPutStrf(&rep->header, type, "Negotiate %s", server_blob);
-
-    safe_free(server_blob);
-}
-
diff -u -r -N squid-3.5.1/src/auth/negotiate/UserRequest.h squid-3.5.2/src/auth/negotiate/UserRequest.h
--- squid-3.5.1/src/auth/negotiate/UserRequest.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/auth/negotiate/UserRequest.h	2015-02-18 04:17:02.000000000 -0800
@@ -37,8 +37,6 @@
     virtual void startHelperLookup(HttpRequest *request, AccessLogEntry::Pointer &al, AUTHCB *, void *);
     virtual const char *credentialsStr();
 
-    virtual void addAuthenticationInfoHeader(HttpReply * rep, int accel);
-
     virtual const char * connLastHeader();
 
     /* we need to store the helper server between requests */
diff -u -r -N squid-3.5.1/src/auth/ntlm/Config.cc squid-3.5.2/src/auth/ntlm/Config.cc
--- squid-3.5.1/src/auth/ntlm/Config.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/auth/ntlm/Config.cc	2015-02-18 04:17:02.000000000 -0800
@@ -241,6 +241,8 @@
     auth_user_request->user(newUser);
     auth_user_request->user()->auth_type = Auth::AUTH_NTLM;
 
+    auth_user_request->user()->BuildUserKey(proxy_auth, aRequestRealm);
+
     /* all we have to do is identify that it's NTLM - the helper does the rest */
     debugs(29, 9, HERE << "decode: NTLM authentication");
     return auth_user_request;
diff -u -r -N squid-3.5.1/src/auth/ntlm/UserRequest.cc squid-3.5.2/src/auth/ntlm/UserRequest.cc
--- squid-3.5.1/src/auth/ntlm/UserRequest.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/auth/ntlm/UserRequest.cc	2015-02-18 04:17:02.000000000 -0800
@@ -157,8 +157,6 @@
 void
 Auth::Ntlm::UserRequest::authenticate(HttpRequest * aRequest, ConnStateData * conn, http_hdr_type type)
 {
-    assert(this);
-
     /* Check that we are in the client side, where we can generate
      * auth challenges */
 
@@ -255,6 +253,8 @@
     // add new helper kv-pair notes to the credentials object
     // so that any transaction using those credentials can access them
     auth_user_request->user()->notes.appendNewOnly(&reply.notes);
+    // remove any private credentials detail which got added.
+    auth_user_request->user()->notes.remove("token");
 
     Auth::Ntlm::UserRequest *lm_request = dynamic_cast<Auth::Ntlm::UserRequest *>(auth_user_request.getRaw());
     assert(lm_request != NULL);
@@ -306,8 +306,7 @@
         debugs(29, 4, HERE << "Successfully validated user via NTLM. Username '" << userLabel << "'");
         /* connection is authenticated */
         debugs(29, 4, HERE << "authenticated user " << auth_user_request->user()->username());
-        /* see if this is an existing user with a different proxy_auth
-         * string */
+        /* see if this is an existing user */
         AuthUserHashPointer *usernamehash = static_cast<AuthUserHashPointer *>(hash_lookup(proxy_auth_username_cache, auth_user_request->user()->userKey()));
         Auth::User::Pointer local_auth_user = lm_request->user();
         while (usernamehash && (usernamehash->user()->auth_type != Auth::AUTH_NTLM ||
diff -u -r -N squid-3.5.1/src/auth/User.cc squid-3.5.2/src/auth/User.cc
--- squid-3.5.1/src/auth/User.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/auth/User.cc	2015-02-18 04:17:02.000000000 -0800
@@ -309,7 +309,10 @@
 Auth::User::BuildUserKey(const char *username, const char *realm)
 {
     SBuf key;
-    key.Printf("%s:%s", username, realm);
+    if (realm)
+        key.Printf("%s:%s", username, realm);
+    else
+        key.append(username, strlen(username));
     return key;
 }
 
@@ -365,10 +368,11 @@
     if (aString) {
         assert(!username_);
         username_ = xstrdup(aString);
-        if (!requestRealm_.isEmpty())
-            userKey_ = BuildUserKey(username_, requestRealm_.c_str());
+        // NP: param #2 is working around a c_str() data-copy performance regression
+        userKey_ = BuildUserKey(username_, (!requestRealm_.isEmpty() ? requestRealm_.c_str() : NULL));
     } else {
         safe_free(username_);
+        userKey_.clear();
     }
 }
 
diff -u -r -N squid-3.5.1/src/auth/User.h squid-3.5.2/src/auth/User.h
--- squid-3.5.1/src/auth/User.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/auth/User.h	2015-02-18 04:17:02.000000000 -0800
@@ -63,9 +63,10 @@
     void absorb(Auth::User::Pointer from);
     virtual ~User();
     char const *username() const { return username_; }
-    void username(char const *);
+    void username(char const *); ///< set stored username and userKey
 
-    const char *userKey() {return !userKey_.isEmpty() ? userKey_.c_str() : username_;}
+    // NP: key is set at the same time as username_. Until then both are empty/NULL.
+    const char *userKey() {return !userKey_.isEmpty() ? userKey_.c_str() : NULL;}
 
     /**
      * How long these credentials are still valid for.
diff -u -r -N squid-3.5.1/src/auth/UserRequest.cc squid-3.5.2/src/auth/UserRequest.cc
--- squid-3.5.1/src/auth/UserRequest.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/auth/UserRequest.cc	2015-02-18 04:17:02.000000000 -0800
@@ -124,9 +124,8 @@
 char const *
 Auth::UserRequest::denyMessage(char const * const default_message)
 {
-    if (this == NULL || getDenyMessage() == NULL) {
+    if (getDenyMessage() == NULL)
         return default_message;
-    }
 
     return getDenyMessage();
 }
diff -u -r -N squid-3.5.1/src/cache_cf.cc squid-3.5.2/src/cache_cf.cc
--- squid-3.5.1/src/cache_cf.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/cache_cf.cc	2015-02-18 04:17:02.000000000 -0800
@@ -881,7 +881,10 @@
 
     debugs(3, DBG_IMPORTANT, "Initializing https proxy context");
 
-    Config.ssl_client.sslContext = sslCreateClientContext(Config.ssl_client.cert, Config.ssl_client.key, Config.ssl_client.version, Config.ssl_client.cipher, Config.ssl_client.options, Config.ssl_client.flags, Config.ssl_client.cafile, Config.ssl_client.capath, Config.ssl_client.crlfile);
+    Config.ssl_client.sslContext = sslCreateClientContext(Config.ssl_client.cert, Config.ssl_client.key, Config.ssl_client.version, Config.ssl_client.cipher, NULL, Config.ssl_client.flags, Config.ssl_client.cafile, Config.ssl_client.capath, Config.ssl_client.crlfile);
+    // Pre-parse SSL client options to be applied when the client SSL objects created.
+    // Options must not used in the case of peek or stare bump mode.
+    Config.ssl_client.parsedOptions = Ssl::parse_options(::Config.ssl_client.options);
 
     for (CachePeer *p = Config.peers; p != NULL; p = p->next) {
         if (p->use_ssl) {
diff -u -r -N squid-3.5.1/src/cbdata.cc squid-3.5.2/src/cbdata.cc
--- squid-3.5.1/src/cbdata.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/cbdata.cc	2015-02-18 04:17:02.000000000 -0800
@@ -439,7 +439,7 @@
 
     if (c->valid) {
 #if USE_CBDATA_DEBUG
-        debugs(45, DBG_IMPORTANT, "CBDATA memory leak. cbdata=" << p << " " << file << ":" << line);
+        debugs(45, 3, "CBDATA valid with no references ... cbdata=" << p << " " << file << ":" << line);
 #endif
         return;
     }
diff -u -r -N squid-3.5.1/src/cbdata.h squid-3.5.2/src/cbdata.h
--- squid-3.5.1/src/cbdata.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/cbdata.h	2015-02-18 04:17:02.000000000 -0800
@@ -426,6 +426,7 @@
         delete this;
     }
 
+private:
     /**
      * The wrapped data - only public to allow the mild abuse of this facility
      * done by store_swapout - it gives a wrapped StoreEntry to StoreIO as the
diff -u -r -N squid-3.5.1/src/cf.data.pre squid-3.5.2/src/cf.data.pre
--- squid-3.5.1/src/cf.data.pre	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/cf.data.pre	2015-02-18 04:17:02.000000000 -0800
@@ -155,6 +155,7 @@
 	Remove this line. Use always_direct or cache_peer_access ACLs instead if you need to prevent cache_peer use.
 DOC_END
 
+# Options removed in 3.4
 NAME: log_access
 TYPE: obsolete
 DOC_START
@@ -175,6 +176,12 @@
 DOC_END
 
 # Options Removed in 3.2
+NAME: chunked_request_body_max_size
+TYPE: obsolete
+DOC_START
+	Remove this line. Squid is now HTTP/1.1 compliant.
+DOC_END
+
 NAME: dns_v4_fallback
 TYPE: obsolete
 DOC_START
@@ -1753,6 +1760,7 @@
 			    NO_TLSv1_2  Disallow the use of TLSv1.2
 			    SINGLE_DH_USE Always create a new key when using
 				      temporary/ephemeral DH key exchanges
+			    NO_TICKET Disables TLS tickets extension
 			    ALL       Enable various bug workarounds
 				      suggested as "harmless" by OpenSSL
 				      Be warned that this reduces SSL/TLS
@@ -5552,33 +5560,6 @@
 	a large file.
 DOC_END
 
-NAME: chunked_request_body_max_size
-COMMENT: (bytes)
-TYPE: b_int64_t
-DEFAULT: 64 KB
-LOC: Config.maxChunkedRequestBodySize
-DOC_START
-	A broken or confused HTTP/1.1 client may send a chunked HTTP
-	request to Squid. Squid does not have full support for that
-	feature yet. To cope with such requests, Squid buffers the
-	entire request and then dechunks request body to create a
-	plain HTTP/1.0 request with a known content length. The plain
-	request is then used by the rest of Squid code as usual.
-
-	The option value specifies the maximum size of the buffer used
-	to hold the request before the conversion. If the chunked
-	request size exceeds the specified limit, the conversion
-	fails, and the client receives an "unsupported request" error,
-	as if dechunking was disabled.
-
-	Dechunking is enabled by default. To disable conversion of
-	chunked requests, set the maximum to zero.
-
-	Request dechunking feature and this option in particular are a
-	temporary hack. When chunking requests and responses are fully
-	supported, there will be no need to buffer a chunked request.
-DOC_END
-
 NAME: broken_posts
 IFDEF: USE_HTTP_VIOLATIONS
 TYPE: acl_access
diff -u -r -N squid-3.5.1/src/client_side.cc squid-3.5.2/src/client_side.cc
--- squid-3.5.1/src/client_side.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/client_side.cc	2015-02-18 04:17:02.000000000 -0800
@@ -621,15 +621,16 @@
 
 #endif
 
-    /*Add notes*/
-    // The al->notes and request->notes must point to the same object.
-    (void)SyncNotes(*al, *request);
-    typedef Notes::iterator ACAMLI;
-    for (ACAMLI i = Config.notes.begin(); i != Config.notes.end(); ++i) {
-        if (const char *value = (*i)->match(request, al->reply, NULL)) {
-            NotePairs &notes = SyncNotes(*al, *request);
-            notes.add((*i)->key.termedBuf(), value);
-            debugs(33, 3, HERE << (*i)->key.termedBuf() << " " << value);
+    /* Add notes (if we have a request to annotate) */
+    if (request) {
+        // The al->notes and request->notes must point to the same object.
+        (void)SyncNotes(*al, *request);
+        for (Notes::iterator i = Config.notes.begin(); i != Config.notes.end(); ++i) {
+            if (const char *value = (*i)->match(request, al->reply, NULL)) {
+                NotePairs &notes = SyncNotes(*al, *request);
+                notes.add((*i)->key.termedBuf(), value);
+                debugs(33, 3, (*i)->key.termedBuf() << " " << value);
+            }
         }
     }
 
@@ -688,7 +689,6 @@
 bool
 ConnStateData::areAllContextsForThisConnection() const
 {
-    assert(this != NULL);
     ClientSocketContext::Pointer context = getCurrentContext();
 
     while (context.getRaw()) {
@@ -844,7 +844,6 @@
 
 ConnStateData::~ConnStateData()
 {
-    assert(this != NULL);
     debugs(33, 3, HERE << clientConnection);
 
     if (isOpen())
@@ -924,7 +923,6 @@
 ClientSocketContext::Pointer
 ConnStateData::getCurrentContext() const
 {
-    assert(this);
     return currentobject;
 }
 
@@ -1255,7 +1253,6 @@
 String
 ClientHttpRequest::rangeBoundaryStr() const
 {
-    assert(this);
     const char *key;
     String b(APP_FULLNAME);
     b.append(":",1);
diff -u -r -N squid-3.5.1/src/comm/Read.cc squid-3.5.2/src/comm/Read.cc
--- squid-3.5.1/src/comm/Read.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/comm/Read.cc	2015-02-18 04:17:02.000000000 -0800
@@ -28,7 +28,7 @@
 bool
 Comm::MonitorsRead(int fd)
 {
-    assert(isOpen(fd) && COMMIO_FD_READCB(fd));
+    assert(isOpen(fd) && COMMIO_FD_READCB(fd) != NULL);
     // Being active is usually the same as monitoring because we always
     // start monitoring the FD when we configure Comm::IoCallback for I/O
     // and we usually configure Comm::IoCallback for I/O when we starting
diff -u -r -N squid-3.5.1/src/comm.cc squid-3.5.2/src/comm.cc
--- squid-3.5.1/src/comm.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/comm.cc	2015-02-18 04:17:02.000000000 -0800
@@ -148,7 +148,7 @@
 bool
 comm_has_incomplete_write(int fd)
 {
-    assert(isOpen(fd) && COMMIO_FD_WRITECB(fd));
+    assert(isOpen(fd) && COMMIO_FD_WRITECB(fd) != NULL);
     return COMMIO_FD_WRITECB(fd)->active();
 }
 
@@ -1082,44 +1082,30 @@
 int
 commSetNonBlocking(int fd)
 {
-#if !_SQUID_WINDOWS_
-    int flags;
-    int dummy = 0;
-#endif
 #if _SQUID_WINDOWS_
     int nonblocking = TRUE;
 
-#if _SQUID_CYGWIN_
-    if (fd_table[fd].type != FD_PIPE) {
-#endif
-
-        if (ioctl(fd, FIONBIO, &nonblocking) < 0) {
-            debugs(50, 0, "commSetNonBlocking: FD " << fd << ": " << xstrerror() << " " << fd_table[fd].type);
-            return Comm::COMM_ERROR;
-        }
-
-#if _SQUID_CYGWIN_
-    } else {
-#endif
-#endif
-#if !_SQUID_WINDOWS_
+    if (ioctl(fd, FIONBIO, &nonblocking) < 0) {
+        debugs(50, 0, "commSetNonBlocking: FD " << fd << ": " << xstrerror() << " " << fd_table[fd].type);
+        return Comm::COMM_ERROR;
+    }
 
-        if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) {
-            debugs(50, 0, "FD " << fd << ": fcntl F_GETFL: " << xstrerror());
-            return Comm::COMM_ERROR;
-        }
+#else
+    int flags;
+    int dummy = 0;
 
-        if (fcntl(fd, F_SETFL, flags | SQUID_NONBLOCK) < 0) {
-            debugs(50, 0, "commSetNonBlocking: FD " << fd << ": " << xstrerror());
-            return Comm::COMM_ERROR;
-        }
+    if ((flags = fcntl(fd, F_GETFL, dummy)) < 0) {
+        debugs(50, 0, "FD " << fd << ": fcntl F_GETFL: " << xstrerror());
+        return Comm::COMM_ERROR;
+    }
 
-#endif
-#if _SQUID_CYGWIN_
+    if (fcntl(fd, F_SETFL, flags | SQUID_NONBLOCK) < 0) {
+        debugs(50, 0, "commSetNonBlocking: FD " << fd << ": " << xstrerror());
+        return Comm::COMM_ERROR;
     }
 #endif
-    fd_table[fd].flags.nonblocking = true;
 
+    fd_table[fd].flags.nonblocking = true;
     return 0;
 }
 
diff -u -r -N squid-3.5.1/src/DelayTagged.cc squid-3.5.2/src/DelayTagged.cc
--- squid-3.5.1/src/DelayTagged.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/DelayTagged.cc	2015-02-18 04:17:02.000000000 -0800
@@ -35,15 +35,15 @@
     DelayPools::registerForUpdates (this);
 }
 
-static SplayNode<DelayTaggedBucket::Pointer>::SPLAYFREE DelayTaggedFree;
+static Splay<DelayTaggedBucket::Pointer>::SPLAYFREE DelayTaggedFree;
 
 DelayTagged::~DelayTagged()
 {
     DelayPools::deregisterForUpdates (this);
-    buckets.head->destroy (DelayTaggedFree);
+    buckets.destroy(DelayTaggedFree);
 }
 
-static SplayNode<DelayTaggedBucket::Pointer>::SPLAYCMP DelayTaggedCmp;
+static Splay<DelayTaggedBucket::Pointer>::SPLAYCMP DelayTaggedCmp;
 
 int
 DelayTaggedCmp(DelayTaggedBucket::Pointer const &left, DelayTaggedBucket::Pointer const &right)
@@ -56,11 +56,13 @@
 DelayTaggedFree(DelayTaggedBucket::Pointer &)
 {}
 
-void
-DelayTaggedStatsWalkee(DelayTaggedBucket::Pointer const &current, void *state)
-{
-    current->stats ((StoreEntry *)state);
-}
+struct DelayTaggedStatsVisitor {
+    StoreEntry *sentry;
+    explicit DelayTaggedStatsVisitor(StoreEntry *se): sentry(se) {}
+    void operator() (DelayTaggedBucket::Pointer const &current) {
+        current->stats(sentry);
+    }
+};
 
 void
 DelayTagged::stats(StoreEntry * sentry)
@@ -72,12 +74,13 @@
 
     storeAppendPrintf(sentry, "\t\tCurrent: ");
 
-    if (!buckets.head) {
+    if (buckets.empty()) {
         storeAppendPrintf (sentry, "Not used yet.\n\n");
         return;
     }
 
-    buckets.head->walk(DelayTaggedStatsWalkee, sentry);
+    DelayTaggedStatsVisitor visitor(sentry);
+    buckets.visit(visitor);
     storeAppendPrintf(sentry, "\n\n");
 }
 
@@ -102,11 +105,20 @@
     const_cast<DelayTaggedBucket *>(current.getRaw())->theBucket.update(t->spec, t->incr);
 }
 
+struct DelayTaggedUpdateVisitor {
+    DelayTaggedUpdater *updater;
+    explicit DelayTaggedUpdateVisitor(DelayTaggedUpdater *u) : updater(u) {}
+    void operator() (DelayTaggedBucket::Pointer const &current) {
+        const_cast<DelayTaggedBucket *>(current.getRaw())->theBucket.update(updater->spec, updater->incr);
+    }
+};
+
 void
 DelayTagged::update(int incr)
 {
     DelayTaggedUpdater updater(spec, incr);
-    buckets.head->walk (DelayTaggedUpdateWalkee, &updater);
+    DelayTaggedUpdateVisitor visitor(&updater);
+    buckets.visit(visitor);
     kickReads();
 }
 
@@ -182,7 +194,7 @@
     }
 
     theBucket->theBucket.init(theTagged->spec);
-    theTagged->buckets.head = theTagged->buckets.head->insert (theBucket, DelayTaggedCmp);
+    theTagged->buckets.insert (theBucket, DelayTaggedCmp);
 }
 
 DelayTagged::Id::~Id()
diff -u -r -N squid-3.5.1/src/DelayUser.cc squid-3.5.2/src/DelayUser.cc
--- squid-3.5.1/src/DelayUser.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/DelayUser.cc	2015-02-18 04:17:02.000000000 -0800
@@ -37,15 +37,15 @@
     DelayPools::registerForUpdates (this);
 }
 
-static SplayNode<DelayUserBucket::Pointer>::SPLAYFREE DelayUserFree;
+static Splay<DelayUserBucket::Pointer>::SPLAYFREE DelayUserFree;
 
 DelayUser::~DelayUser()
 {
     DelayPools::deregisterForUpdates (this);
-    buckets.head->destroy (DelayUserFree);
+    buckets.destroy(DelayUserFree);
 }
 
-static SplayNode<DelayUserBucket::Pointer>::SPLAYCMP DelayUserCmp;
+static Splay<DelayUserBucket::Pointer>::SPLAYCMP DelayUserCmp;
 
 int
 DelayUserCmp(DelayUserBucket::Pointer const &left, DelayUserBucket::Pointer const &right)
@@ -68,6 +68,14 @@
     current->stats ((StoreEntry *)state);
 }
 
+struct DelayUserStatsVisitor {
+    StoreEntry *se;
+    explicit DelayUserStatsVisitor(StoreEntry *s) : se(s) {}
+    void operator() (DelayUserBucket::Pointer const &current) {
+        current->stats(se);
+    }
+};
+
 void
 DelayUser::stats(StoreEntry * sentry)
 {
@@ -78,12 +86,13 @@
 
     storeAppendPrintf(sentry, "\t\tCurrent: ");
 
-    if (!buckets.head) {
+    if (buckets.empty()) {
         storeAppendPrintf (sentry, "Not used yet.\n\n");
         return;
     }
 
-    buckets.head->walk(DelayUserStatsWalkee, sentry);
+    DelayUserStatsVisitor visitor(sentry);
+    buckets.visit(visitor);
     storeAppendPrintf(sentry, "\n\n");
 }
 
@@ -108,11 +117,20 @@
     const_cast<DelayUserBucket *>(current.getRaw())->theBucket.update(t->spec, t->incr);
 }
 
+struct DelayUserUpdateVisitor {
+    DelayUserUpdater *t;
+    DelayUserUpdateVisitor(DelayUserUpdater *updater) : t(updater) {}
+    void operator() (DelayUserBucket::Pointer const &current) {
+        const_cast<DelayUserBucket *>(current.getRaw())->theBucket.update(t->spec, t->incr);
+    }
+};
+
 void
 DelayUser::update(int incr)
 {
     DelayUserUpdater updater(spec, incr);
-    buckets.head->walk (DelayUserUpdateWalkee, &updater);
+    DelayUserUpdateVisitor visitor(&updater);
+    buckets.visit(visitor);
 }
 
 void
@@ -188,7 +206,7 @@
     }
 
     theBucket->theBucket.init(theUser->spec);
-    theUser->buckets.head = theUser->buckets.head->insert (theBucket, DelayUserCmp);
+    theUser->buckets.insert (theBucket, DelayUserCmp);
 }
 
 DelayUser::Id::~Id()
diff -u -r -N squid-3.5.1/src/dns_internal.cc squid-3.5.2/src/dns_internal.cc
--- squid-3.5.1/src/dns_internal.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/dns_internal.cc	2015-02-18 04:17:02.000000000 -0800
@@ -381,7 +381,7 @@
 idnsParseResolvConf(void)
 {
     bool result = false;
-#if !_SQUID_WINDOWS_ || _SQUID_CYGWIN_
+#if !_SQUID_WINDOWS_
     FILE *fp = fopen(_PATH_RESCONF, "r");
 
     if (fp == NULL) {
@@ -389,10 +389,6 @@
         return false;
     }
 
-#if _SQUID_CYGWIN_
-    setmode(fileno(fp), O_TEXT);
-#endif
-
     char buf[RESOLV_BUFSZ];
     const char *t = NULL;
     while (fgets(buf, RESOLV_BUFSZ, fp)) {
diff -u -r -N squid-3.5.1/src/esi/Esi.cc squid-3.5.2/src/esi/Esi.cc
--- squid-3.5.1/src/esi/Esi.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/esi/Esi.cc	2015-02-18 04:17:02.000000000 -0800
@@ -311,8 +311,6 @@
 esiKick_t
 ESIContext::kick ()
 {
-    assert (this);
-
     if (flags.kicked) {
         debugs(86, 5, "esiKick: Re-entered whilst in progress");
         // return ESI_KICK_INPROGRESS;
@@ -1681,7 +1679,6 @@
 esiTry::render(ESISegment::Pointer output)
 {
     /* Try renders from it's children */
-    assert (this);
     assert (attempt.getRaw());
     assert (except.getRaw());
     debugs(86, 5, "esiTryRender: Rendering Try " << this);
@@ -1749,7 +1746,6 @@
 esiTry::process (int dovars)
 {
     esiProcessResult_t rv = ESI_PROCESS_PENDING_MAYFAIL;
-    assert (this);
 
     if (!attempt.getRaw()) {
         debugs(86, DBG_CRITICAL, "esiTryProcess: Try has no attempt element - ESI template is invalid (section 3.4)");
diff -u -r -N squid-3.5.1/src/esi/Include.cc squid-3.5.2/src/esi/Include.cc
--- squid-3.5.1/src/esi/Include.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/esi/Include.cc	2015-02-18 04:17:02.000000000 -0800
@@ -198,7 +198,6 @@
 /* esiStream functions */
 ESIStreamContext::~ESIStreamContext()
 {
-    assert (this);
     freeResources();
 }
 
@@ -453,8 +452,6 @@
 void
 ESIInclude::subRequestDone (ESIStreamContext::Pointer stream, bool success)
 {
-    assert (this);
-
     if (!dataNeeded())
         return;
 
diff -u -r -N squid-3.5.1/src/eui/Eui48.cc squid-3.5.2/src/eui/Eui48.cc
--- squid-3.5.1/src/eui/Eui48.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/eui/Eui48.cc	2015-02-18 04:17:02.000000000 -0800
@@ -116,7 +116,7 @@
 }
 
 bool
-Eui::Eui48::encode(char *buf, const int len)
+Eui::Eui48::encode(char *buf, const int len) const
 {
     if (len < SZ_EUI48_BUF)
         return false;
diff -u -r -N squid-3.5.1/src/eui/Eui48.h squid-3.5.2/src/eui/Eui48.h
--- squid-3.5.1/src/eui/Eui48.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/eui/Eui48.h	2015-02-18 04:17:02.000000000 -0800
@@ -30,6 +30,8 @@
 public:
     Eui48() { clear(); }
     Eui48(const Eui48 &t) { memcpy(this, &t, sizeof(Eui48)); }
+    bool operator== (const Eui48 &t) const { return memcmp(eui, t.eui, SZ_EUI48_BUF) == 0; }
+    bool operator< (const Eui48 &t) const { return memcmp(eui, t.eui, SZ_EUI48_BUF) < 0; }
     ~Eui48() {}
 
     const unsigned char *get(void);
@@ -62,7 +64,7 @@
      * \retval false        Conversion to ASCII failed.
      * \retval true         Conversion completed successfully.
      */
-    bool encode(char *buf, const int len);
+    bool encode(char *buf, const int len) const;
 
     // lookup an EUI-48 / MAC address via ARP
     bool lookup(const Ip::Address &c);
diff -u -r -N squid-3.5.1/src/eui/Eui64.cc squid-3.5.2/src/eui/Eui64.cc
--- squid-3.5.1/src/eui/Eui64.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/eui/Eui64.cc	2015-02-18 04:17:02.000000000 -0800
@@ -31,7 +31,7 @@
 }
 
 bool
-Eui::Eui64::encode(char *buf, const int len)
+Eui::Eui64::encode(char *buf, const int len) const
 {
     if (len < SZ_EUI64_BUF) return false;
 
diff -u -r -N squid-3.5.1/src/eui/Eui64.h squid-3.5.2/src/eui/Eui64.h
--- squid-3.5.1/src/eui/Eui64.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/eui/Eui64.h	2015-02-18 04:17:02.000000000 -0800
@@ -37,6 +37,9 @@
 public:
     Eui64() { clear(); }
     Eui64(const Eui64 &t) { memcpy(this, &t, sizeof(Eui64)); }
+    Eui64& operator= (const Eui64 &t) {memcpy(this, &t, sizeof(Eui64)); return *this;}
+    bool operator== (const Eui64 &t) const { return (memcmp(eui,t.eui,SZ_EUI64_BUF) == 0); }
+    bool operator< (const Eui64 &t) const { return (memcmp(eui,t.eui,SZ_EUI64_BUF) < 0); }
     ~Eui64() {}
 
     const unsigned char *get(void);
@@ -69,7 +72,7 @@
      * \retval false        Conversion to ASCII failed.
      * \retval true         Conversion completed successfully.
      */
-    bool encode(char *buf, const int len);
+    bool encode(char *buf, const int len) const;
 
     // lookup an EUI-64 address via IPv6 SLAAC or NDP
     bool lookup(const Ip::Address &c);
diff -u -r -N squid-3.5.1/src/fs/ufs/RebuildState.cc squid-3.5.2/src/fs/ufs/RebuildState.cc
--- squid-3.5.1/src/fs/ufs/RebuildState.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/fs/ufs/RebuildState.cc	2015-02-18 04:17:02.000000000 -0800
@@ -130,7 +130,6 @@
 
     struct stat sb;
     int fd = -1;
-    assert(this != NULL);
     debugs(47, 3, HERE << "DIR #" << sd->index);
 
     assert(fd == -1);
diff -u -r -N squid-3.5.1/src/htcp.cc squid-3.5.2/src/htcp.cc
--- squid-3.5.1/src/htcp.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/htcp.cc	2015-02-18 04:17:02.000000000 -0800
@@ -47,8 +47,6 @@
 
 typedef struct _htcpAuthHeader htcpAuthHeader;
 
-typedef struct _htcpStuff htcpStuff;
-
 typedef struct _htcpDetail htcpDetail;
 
 struct _Countstr {
@@ -139,6 +137,17 @@
 public:
     MEMPROXY_CLASS(htcpSpecifier);
 
+    htcpSpecifier() :
+        method(NULL),
+        uri(NULL),
+        version(NULL),
+        req_hdrs(NULL),
+        request(NULL),
+        checkHitRequest(NULL),
+        dhdr(NULL)
+    {}
+    // XXX: destructor?
+
     void created (StoreEntry *newEntry);
     void checkHit();
     void checkedHit(StoreEntry *e);
@@ -166,7 +175,20 @@
     char *cache_hdrs;
 };
 
-struct _htcpStuff {
+class htcpStuff
+{
+public:
+    htcpStuff(uint32_t id, int o, int r, int f) :
+        op(o),
+        rr(r),
+        f1(f),
+        response(0),
+        reason(0),
+        msg_id(id)
+    {
+        memset(&D, 0, sizeof(D));
+    }
+
     int op;
     int rr;
     int f1;
@@ -834,19 +856,15 @@
 static void
 htcpTstReply(htcpDataHeader * dhdr, StoreEntry * e, htcpSpecifier * spec, Ip::Address &from)
 {
-    htcpStuff stuff;
     static char pkt[8192];
     HttpHeader hdr(hoHtcpReply);
     MemBuf mb;
     Packer p;
     ssize_t pktlen;
-    memset(&stuff, '\0', sizeof(stuff));
-    stuff.op = HTCP_TST;
-    stuff.rr = RR_RESPONSE;
-    stuff.f1 = 0;
+
+    htcpStuff stuff(dhdr->msg_id, HTCP_TST, RR_RESPONSE, 0);
     stuff.response = e ? 0 : 1;
     debugs(31, 3, "htcpTstReply: response = " << stuff.response);
-    stuff.msg_id = dhdr->msg_id;
 
     if (spec) {
         mb.init();
@@ -923,7 +941,6 @@
 
 htcpClrReply(htcpDataHeader * dhdr, int purgeSucceeded, Ip::Address &from)
 {
-    htcpStuff stuff;
     static char pkt[8192];
     ssize_t pktlen;
 
@@ -932,20 +949,12 @@
     if (dhdr->F1 == 0)
         return;
 
-    memset(&stuff, '\0', sizeof(stuff));
-
-    stuff.op = HTCP_CLR;
-
-    stuff.rr = RR_RESPONSE;
-
-    stuff.f1 = 0;
+    htcpStuff stuff(dhdr->msg_id, HTCP_CLR, RR_RESPONSE, 0);
 
     stuff.response = purgeSucceeded ? 0 : 2;
 
     debugs(31, 3, "htcpClrReply: response = " << stuff.response);
 
-    stuff.msg_id = dhdr->msg_id;
-
     pktlen = htcpBuildPacket(pkt, sizeof(pkt), &stuff);
 
     if (pktlen == 0) {
@@ -1538,7 +1547,6 @@
     static char pkt[8192];
     ssize_t pktlen;
     char vbuf[32];
-    htcpStuff stuff;
     HttpHeader hdr(hoRequest);
     Packer pa;
     MemBuf mb;
@@ -1551,11 +1559,8 @@
     memset(&flags, '\0', sizeof(flags));
     snprintf(vbuf, sizeof(vbuf), "%d/%d",
              req->http_ver.major, req->http_ver.minor);
-    stuff.op = HTCP_TST;
-    stuff.rr = RR_REQUEST;
-    stuff.f1 = 1;
-    stuff.response = 0;
-    stuff.msg_id = ++msg_id_counter;
+
+    htcpStuff stuff(++msg_id_counter, HTCP_TST, RR_REQUEST, 1);
     SBuf sb = req->method.image();
     stuff.S.method = sb.c_str();
     stuff.S.uri = (char *) e->url();
@@ -1594,7 +1599,6 @@
     static char pkt[8192];
     ssize_t pktlen;
     char vbuf[32];
-    htcpStuff stuff;
     HttpHeader hdr(hoRequest);
     Packer pa;
     MemBuf mb;
@@ -1607,19 +1611,11 @@
     memset(&flags, '\0', sizeof(flags));
     snprintf(vbuf, sizeof(vbuf), "%d/%d",
              req->http_ver.major, req->http_ver.minor);
-    stuff.op = HTCP_CLR;
-    stuff.rr = RR_REQUEST;
-    stuff.f1 = 0;
-    stuff.response = 0;
-    stuff.msg_id = ++msg_id_counter;
-    switch (reason) {
-    case HTCP_CLR_INVALIDATION:
+
+    htcpStuff stuff(++msg_id_counter, HTCP_CLR, RR_REQUEST, 0);
+    if (reason == HTCP_CLR_INVALIDATION)
         stuff.reason = 1;
-        break;
-    default:
-        stuff.reason = 0;
-        break;
-    }
+
     SBuf sb = req->method.image();
     stuff.S.method = sb.c_str();
     if (e == NULL || e->mem_obj == NULL) {
diff -u -r -N squid-3.5.1/src/HttpHdrRange.cc squid-3.5.2/src/HttpHdrRange.cc
--- squid-3.5.1/src/HttpHdrRange.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/HttpHdrRange.cc	2015-02-18 04:17:02.000000000 -0800
@@ -224,7 +224,7 @@
     const char *item;
     const char *pos = NULL;
     int ilen;
-    assert(this && range_spec);
+    assert(range_spec);
     ++ParsedCount;
     debugs(64, 8, "parsing range field: '" << range_spec << "'");
     /* check range type */
@@ -306,7 +306,6 @@
 HttpHdrRange::packInto(Packer * packer) const
 {
     const_iterator pos = begin();
-    assert(this);
 
     while (pos != end()) {
         if (pos != begin())
@@ -371,7 +370,7 @@
 int
 HttpHdrRange::canonize(HttpReply *rep)
 {
-    assert(this && rep);
+    assert(rep);
 
     if (rep->content_range)
         clen = rep->content_range->elength;
@@ -401,7 +400,6 @@
 HttpHdrRange::isComplex() const
 {
     int64_t offset = 0;
-    assert(this);
     /* check that all rangers are in "strong" order */
     const_iterator pos (begin());
 
@@ -427,7 +425,6 @@
 bool
 HttpHdrRange::willBeComplex() const
 {
-    assert(this);
     /* check that all rangers are in "strong" order, */
     /* as far as we can tell without the content length */
     int64_t offset = 0;
@@ -460,7 +457,6 @@
 HttpHdrRange::firstOffset() const
 {
     int64_t offset = HttpHdrRangeSpec::UnknownPosition;
-    assert(this);
     const_iterator pos = begin();
 
     while (pos != end()) {
@@ -484,7 +480,6 @@
 {
     int64_t offset = HttpHdrRangeSpec::UnknownPosition;
     const_iterator pos = begin();
-    assert(this);
 
     while (pos != end()) {
         int64_t current = (*pos)->offset;
@@ -512,10 +507,6 @@
 bool
 HttpHdrRange::offsetLimitExceeded(const int64_t limit) const
 {
-    if (NULL == this)
-        /* not a range request */
-        return false;
-
     if (limit == 0)
         /* 0 == disabled */
         return true;
diff -u -r -N squid-3.5.1/src/log/ModStdio.cc squid-3.5.2/src/log/ModStdio.cc
--- squid-3.5.1/src/log/ModStdio.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/log/ModStdio.cc	2015-02-18 04:17:02.000000000 -0800
@@ -108,7 +108,6 @@
     char from[MAXPATHLEN];
     char to[MAXPATHLEN];
     l_stdio_t *ll = (l_stdio_t *) lf->data;
-    assert(lf->path);
     const char *realpath = lf->path+6; // skip 'stdio:' prefix.
     assert(realpath);
 
diff -u -r -N squid-3.5.1/src/neighbors.cc squid-3.5.2/src/neighbors.cc
--- squid-3.5.1/src/neighbors.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/neighbors.cc	2015-02-18 04:17:02.000000000 -0800
@@ -1447,8 +1447,7 @@
     fake->abort(); // sets ENTRY_ABORTED and initiates releated cleanup
     HTTPMSGUNLOCK(fake->mem_obj->request);
     fake->unlock("peerCountMcastPeersDone");
-    HTTPMSGUNLOCK(psstate->request);
-    cbdataFree(psstate);
+    delete psstate;
 }
 
 static void
diff -u -r -N squid-3.5.1/src/parser/Tokenizer.cc squid-3.5.2/src/parser/Tokenizer.cc
--- squid-3.5.1/src/parser/Tokenizer.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/parser/Tokenizer.cc	2015-02-18 04:17:02.000000000 -0800
@@ -71,11 +71,13 @@
 bool
 Parser::Tokenizer::prefix(SBuf &returnedToken, const CharacterSet &tokenChars, const SBuf::size_type limit)
 {
-    const SBuf::size_type prefixLen = buf_.substr(0,limit).findFirstNotOf(tokenChars);
+    SBuf::size_type prefixLen = buf_.substr(0,limit).findFirstNotOf(tokenChars);
     if (prefixLen == 0)
         return false;
     if (prefixLen == SBuf::npos && (atEnd() || limit == 0))
         return false;
+    if (prefixLen == SBuf::npos && limit > 0)
+        prefixLen = limit;
     returnedToken = consume(prefixLen); // cannot be empty after the npos check
     return true;
 }
diff -u -r -N squid-3.5.1/src/peer_select.cc squid-3.5.2/src/peer_select.cc
--- squid-3.5.1/src/peer_select.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/peer_select.cc	2015-02-18 04:17:02.000000000 -0800
@@ -107,7 +107,7 @@
     assert(entry);
     assert(entry->ping_status == PING_NONE);
     assert(direct != DIRECT_YES);
-    debugs(44, 3, "peerSelectIcpPing: " << entry->url()  );
+    debugs(44, 3, "peerSelectIcpPing: " << entry->url());
 
     if (!request->flags.hierarchical && direct != DIRECT_NO)
         return 0;
@@ -255,7 +255,7 @@
     if (fs && psstate->paths->size() < (unsigned int)Config.forward_max_tries) {
         // send the next one off for DNS lookup.
         const char *host = fs->_peer ? fs->_peer->host : psstate->request->GetHost();
-        debugs(44, 2, "Find IP destination for: " << psstate->entry->url() << "' via " << host);
+        debugs(44, 2, "Find IP destination for: " << psstate->url() << "' via " << host);
         ipcache_nbgethostbyname(host, peerSelectDnsResults, psstate);
         return;
     }
@@ -753,7 +753,7 @@
     StoreEntry *entry = psstate->entry;
 
     if (entry)
-        debugs(44, 3, "peerPingTimeout: '" << entry->url() << "'" );
+        debugs(44, 3, "peerPingTimeout: '" << psstate->url() << "'" );
 
     if (!cbdataReferenceValid(psstate->callback_data)) {
         /* request aborted */
@@ -821,7 +821,7 @@
 {
     ps_state *psstate = (ps_state *)data;
     icp_opcode op = header->getOpCode();
-    debugs(44, 3, "peerHandleIcpReply: " << icp_opcode_str[op] << " " << psstate->entry->url()  );
+    debugs(44, 3, "peerHandleIcpReply: " << icp_opcode_str[op] << " " << psstate->url()  );
 #if USE_CACHE_DIGESTS && 0
     /* do cd lookup to count false misses */
 
@@ -854,9 +854,7 @@
 peerHandleHtcpReply(CachePeer * p, peer_t type, HtcpReplyData * htcp, void *data)
 {
     ps_state *psstate = (ps_state *)data;
-    debugs(44, 3, "peerHandleHtcpReply: " <<
-           (htcp->hit ? "HIT" : "MISS") << " " <<
-           psstate->entry->url()  );
+    debugs(44, 3, "" << (htcp->hit ? "HIT" : "MISS") << " " << psstate->url());
     ++ psstate->ping.n_recv;
 
     if (htcp->hit) {
diff -u -r -N squid-3.5.1/src/SquidConfig.h squid-3.5.2/src/SquidConfig.h
--- squid-3.5.1/src/SquidConfig.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/SquidConfig.h	2015-02-18 04:17:02.000000000 -0800
@@ -100,7 +100,6 @@
     } Timeout;
     size_t maxRequestHeaderSize;
     int64_t maxRequestBodySize;
-    int64_t maxChunkedRequestBodySize;
     size_t maxRequestBufferSize;
     size_t maxReplyHeaderSize;
     AclSizeLimit *ReplyBodySize;
@@ -499,6 +498,7 @@
         char *key;
         int version;
         char *options;
+        long parsedOptions;
         char *cipher;
         char *cafile;
         char *capath;
diff -u -r -N squid-3.5.1/src/ssl/PeerConnector.cc squid-3.5.2/src/ssl/PeerConnector.cc
--- squid-3.5.1/src/ssl/PeerConnector.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/ssl/PeerConnector.cc	2015-02-18 04:17:02.000000000 -0800
@@ -144,48 +144,61 @@
 
         if (peer->sslSession)
             SSL_set_session(ssl, peer->sslSession);
-
-    } else if (request->clientConnectionManager->sslBumpMode == Ssl::bumpPeek || request->clientConnectionManager->sslBumpMode == Ssl::bumpStare) {
-        // client connection is required for Peek or Stare mode in the case we need to splice
+    } else if (ConnStateData *csd = request->clientConnectionManager.valid()) {
+        // client connection is required in the case we need to splice
         // or terminate client and server connections
         assert(clientConn != NULL);
-        SSL *clientSsl = fd_table[request->clientConnectionManager->clientConnection->fd].ssl;
-        BIO *b = SSL_get_rbio(clientSsl);
-        Ssl::ClientBio *clnBio = static_cast<Ssl::ClientBio *>(b->ptr);
-        const Ssl::Bio::sslFeatures &features = clnBio->getFeatures();
-        if (features.sslVersion != -1) {
-            features.applyToSSL(ssl);
-            // Should we allow it for all protocols?
-            if (features.sslVersion >= 3) {
-                b = SSL_get_rbio(ssl);
-                Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
-                srvBio->setClientFeatures(features);
-                srvBio->recordInput(true);
-                srvBio->mode(request->clientConnectionManager->sslBumpMode);
+        const char *hostName = NULL;
+        Ssl::ClientBio *cltBio = NULL;
+
+        // In server-first bumping mode, clientSsl is NULL.
+        if (SSL *clientSsl = fd_table[clientConn->fd].ssl) {
+            BIO *b = SSL_get_rbio(clientSsl);
+            cltBio = static_cast<Ssl::ClientBio *>(b->ptr);
+            const Ssl::Bio::sslFeatures &features = cltBio->getFeatures();
+            if (!features.serverName.isEmpty())
+                hostName = features.serverName.c_str();
+        }
+
+        if (!hostName) {
+            // While we are peeking at the certificate, we may not know the server
+            // name that the client will request (after interception or CONNECT)
+            // unless it was the CONNECT request with a user-typed address.
+            const bool isConnectRequest = !csd->port->flags.isIntercepted();
+            if (!request->flags.sslPeek || isConnectRequest)
+                hostName = request->GetHost();
+        }
+
+        if (hostName)
+            SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)hostName);
+
+        Must(!csd->serverBump() || csd->serverBump()->step <= Ssl::bumpStep2);
+        if (csd->sslBumpMode == Ssl::bumpPeek || csd->sslBumpMode == Ssl::bumpStare) {
+            assert(cltBio);
+            const Ssl::Bio::sslFeatures &features = cltBio->getFeatures();
+            if (features.sslVersion != -1) {
+                features.applyToSSL(ssl);
+                // Should we allow it for all protocols?
+                if (features.sslVersion >= 3) {
+                    BIO *b = SSL_get_rbio(ssl);
+                    Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
+                    // Inherite client features, like SSL version, SNI and other
+                    srvBio->setClientFeatures(features);
+                    srvBio->recordInput(true);
+                    srvBio->mode(csd->sslBumpMode);
+                }
             }
+        } else {
+            // Set client SSL options
+            SSL_set_options(ssl, ::Config.ssl_client.parsedOptions);
 
-            const bool isConnectRequest = request->clientConnectionManager.valid() &&
-                                          !request->clientConnectionManager->port->flags.isIntercepted();
-            if (isConnectRequest)
-                SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)request->GetHost());
-            else if (!features.serverName.isEmpty())
-                SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)features.serverName.c_str());
+            // Use SNI TLS extension only when we connect directly
+            // to the origin server and we know the server host name.
+            const char *sniServer = hostName ? hostName :
+                                    (!request->GetHostIsNumeric() ? request->GetHost() : NULL);
+            if (sniServer)
+                Ssl::setClientSNI(ssl, sniServer);
         }
-    } else {
-        // While we are peeking at the certificate, we may not know the server
-        // name that the client will request (after interception or CONNECT)
-        // unless it was the CONNECT request with a user-typed address.
-        const char *hostname = request->GetHost();
-        const bool hostnameIsIp = request->GetHostIsNumeric();
-        const bool isConnectRequest = request->clientConnectionManager.valid() &&
-                                      !request->clientConnectionManager->port->flags.isIntercepted();
-        if (!request->flags.sslPeek || isConnectRequest)
-            SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)hostname);
-
-        // Use SNI TLS extension only when we connect directly
-        // to the origin server and we know the server host name.
-        if (!hostnameIsIp)
-            Ssl::setClientSNI(ssl, hostname);
     }
 
     // If CertValidation Helper used do not lookup checklist for errors,
diff -u -r -N squid-3.5.1/src/ssl/support.cc squid-3.5.2/src/ssl/support.cc
--- squid-3.5.1/src/ssl/support.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/ssl/support.cc	2015-02-18 04:17:02.000000000 -0800
@@ -312,16 +312,19 @@
             // pass them to certficate validator for more processing
             else if (Ssl::TheConfig.ssl_crt_validator) {
                 ok = 1;
-                // Check if we have stored certificates chain. Store if not.
-                if (!SSL_get_ex_data(ssl, ssl_ex_index_ssl_cert_chain)) {
-                    STACK_OF(X509) *certStack = X509_STORE_CTX_get1_chain(ctx);
-                    if (certStack && !SSL_set_ex_data(ssl, ssl_ex_index_ssl_cert_chain, certStack))
-                        sk_X509_pop_free(certStack, X509_free);
-                }
             }
         }
     }
 
+    if (Ssl::TheConfig.ssl_crt_validator) {
+        // Check if we have stored certificates chain. Store if not.
+        if (!SSL_get_ex_data(ssl, ssl_ex_index_ssl_cert_chain)) {
+            STACK_OF(X509) *certStack = X509_STORE_CTX_get1_chain(ctx);
+            if (certStack && !SSL_set_ex_data(ssl, ssl_ex_index_ssl_cert_chain, certStack))
+                sk_X509_pop_free(certStack, X509_free);
+        }
+    }
+
     if (!ok && !SSL_get_ex_data(ssl, ssl_ex_index_ssl_error_detail) ) {
 
         // Find the broken certificate. It may be intermediate.
@@ -477,6 +480,11 @@
         "No_Compression", SSL_OP_NO_COMPRESSION
     },
 #endif
+#if SSL_OP_NO_TICKET
+    {
+        "NO_TICKET", SSL_OP_NO_TICKET
+    },
+#endif
     {
         "", 0
     },
diff -u -r -N squid-3.5.1/src/stat.cc squid-3.5.2/src/stat.cc
--- squid-3.5.1/src/stat.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/stat.cc	2015-02-18 04:17:02.000000000 -0800
@@ -370,11 +370,11 @@
             storeAppendPrintf(state->sentry, "} by kid%d\n\n", KidIdentifier);
         state->sentry->complete();
         state->sentry->unlock("statObjects+isDone");
-        cbdataFree(state);
+        delete state;
         return;
     } else if (EBIT_TEST(state->sentry->flags, ENTRY_ABORTED)) {
         state->sentry->unlock("statObjects+aborted");
-        cbdataFree(state);
+        delete state;
         return;
     } else if (state->sentry->checkDeferRead(-1)) {
         state->sentry->flush();
diff -u -r -N squid-3.5.1/src/stmem.cc squid-3.5.2/src/stmem.cc
--- squid-3.5.1/src/stmem.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/stmem.cc	2015-02-18 04:17:02.000000000 -0800
@@ -58,7 +58,7 @@
 void
 mem_hdr::freeContent()
 {
-    nodes.destroy(SplayNode<mem_node *>::DefaultFree);
+    nodes.destroy();
     inmem_hi = 0;
     debugs(19, 9, HERE << this << " hi: " << inmem_hi);
 }
diff -u -r -N squid-3.5.1/src/stmem.h squid-3.5.2/src/stmem.h
--- squid-3.5.1/src/stmem.h	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/stmem.h	2015-02-18 04:17:02.000000000 -0800
@@ -44,7 +44,7 @@
     /* Only for use of MemObject */
     void internalAppend(const char *data, int len);
 
-    static SplayNode<mem_node *>::SPLAYCMP NodeCompare;
+    static Splay<mem_node *>::SPLAYCMP NodeCompare;
 
 private:
     void debugDump() const;
diff -u -r -N squid-3.5.1/src/store.cc squid-3.5.2/src/store.cc
--- squid-3.5.1/src/store.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/store.cc	2015-02-18 04:17:02.000000000 -0800
@@ -1686,9 +1686,7 @@
 const char *
 StoreEntry::url() const
 {
-    if (this == NULL)
-        return "[null_entry]";
-    else if (mem_obj == NULL)
+    if (mem_obj == NULL)
         return "[null_mem_obj]";
     else
         return mem_obj->storeId();
diff -u -r -N squid-3.5.1/src/store_swapout.cc squid-3.5.2/src/store_swapout.cc
--- squid-3.5.1/src/store_swapout.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/store_swapout.cc	2015-02-18 04:17:02.000000000 -0800
@@ -89,8 +89,9 @@
 static void
 storeSwapOutFileNotify(void *data, int errflag, StoreIOState::Pointer self)
 {
-    generic_cbdata *c = (generic_cbdata *)data;
-    StoreEntry *e = (StoreEntry *)c->data;
+    StoreEntry *e;
+    static_cast<generic_cbdata *>(data)->unwrap(&e);
+
     MemObject *mem = e->mem_obj;
     assert(e->swap_status == SWAPOUT_WRITING);
     assert(mem);
@@ -281,12 +282,12 @@
 static void
 storeSwapOutFileClosed(void *data, int errflag, StoreIOState::Pointer self)
 {
-    generic_cbdata *c = (generic_cbdata *)data;
-    StoreEntry *e = (StoreEntry *)c->data;
+    StoreEntry *e;
+    static_cast<generic_cbdata *>(data)->unwrap(&e);
+
     MemObject *mem = e->mem_obj;
     assert(mem->swapout.sio == self);
     assert(e->swap_status == SWAPOUT_WRITING);
-    cbdataFree(c);
 
     // if object_size is still unknown, the entry was probably aborted
     if (errflag || e->objectLen() < 0) {
diff -u -r -N squid-3.5.1/src/String.cc squid-3.5.2/src/String.cc
--- squid-3.5.1/src/String.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/String.cc	2015-02-18 04:17:02.000000000 -0800
@@ -105,7 +105,7 @@
 String::allocAndFill(const char *str, int len)
 {
     PROF_start(StringAllocAndFill);
-    assert(this && str);
+    assert(str);
     allocBuffer(len + 1);
     len_ = len;
     memcpy(buf_, str, len);
@@ -127,7 +127,6 @@
 String::clean()
 {
     PROF_start(StringClean);
-    assert(this);
 
     /* TODO if mempools has already closed this will FAIL!! */
     if (defined())
@@ -163,7 +162,6 @@
 void
 String::append( char const *str, int len)
 {
-    assert(this);
     assert(str && len >= 0);
 
     PROF_start(StringAppend);
diff -u -r -N squid-3.5.1/src/tests/stub_libeui.cc squid-3.5.2/src/tests/stub_libeui.cc
--- squid-3.5.1/src/tests/stub_libeui.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/tests/stub_libeui.cc	2015-02-18 04:17:02.000000000 -0800
@@ -18,7 +18,7 @@
 #if USE_SQUID_EUI
 const unsigned char *Eui::Eui48::get(void) STUB_RETVAL(NULL)
 bool Eui::Eui48::decode(const char *asc) STUB_RETVAL(false)
-bool Eui::Eui48::encode(char *buf, const int len) STUB_RETVAL(false)
+bool Eui::Eui48::encode(char *buf, const int len) const STUB_RETVAL(false)
 bool Eui::Eui48::lookup(const Ip::Address &c) STUB_RETVAL(false)
 #endif
 
@@ -26,7 +26,7 @@
 #if USE_SQUID_EUI
 const unsigned char *Eui::Eui64::get(void) STUB_RETVAL(NULL)
 bool Eui::Eui64::decode(const char *asc) STUB_RETVAL(false)
-bool Eui::Eui64::encode(char *buf, const int len) STUB_RETVAL(false)
+bool Eui::Eui64::encode(char *buf, const int len) const STUB_RETVAL(false)
 bool Eui::Eui64::lookup(const Ip::Address &c) STUB_RETVAL(false)
 bool Eui::Eui64::lookupNdp(const Ip::Address &c) STUB_RETVAL(false)
 bool Eui::Eui64::lookupSlaac(const Ip::Address &c) STUB_RETVAL(false)
diff -u -r -N squid-3.5.1/src/tests/testRefCount.cc squid-3.5.2/src/tests/testRefCount.cc
--- squid-3.5.1/src/tests/testRefCount.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/tests/testRefCount.cc	2015-02-18 04:17:02.000000000 -0800
@@ -20,7 +20,7 @@
     ~_ToRefCount() {--Instances;}
 
     int someMethod() {
-        if (!this)
+        if (!Instances)
             exit(1);
 
         return 1;
@@ -40,7 +40,7 @@
     typedef RefCount<AlsoRefCountable> Pointer;
 
     int doSomething() {
-        if (!this)
+        if (!Instances)
             exit (1);
         return 1;
     }
diff -u -r -N squid-3.5.1/src/tools.cc squid-3.5.2/src/tools.cc
--- squid-3.5.1/src/tools.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/src/tools.cc	2015-02-18 04:17:02.000000000 -0800
@@ -896,7 +896,7 @@
     }
 #endif /* HAVE_SETRLIMIT */
 
-#if HAVE_SETRLIMIT && defined(RLIMIT_DATA)
+#if HAVE_SETRLIMIT && defined(RLIMIT_DATA) && !_SQUID_CYGWIN_
     if (getrlimit(RLIMIT_DATA, &rl) < 0) {
         debugs(50, DBG_CRITICAL, "getrlimit: RLIMIT_DATA: " << xstrerror());
     } else if (rl.rlim_max > rl.rlim_cur) {
@@ -912,7 +912,7 @@
         debugs(50, DBG_IMPORTANT, "NOTICE: Could not increase the number of filedescriptors");
     }
 
-#if HAVE_SETRLIMIT && defined(RLIMIT_VMEM)
+#if HAVE_SETRLIMIT && defined(RLIMIT_VMEM) && !_SQUID_CYGWIN_
     if (getrlimit(RLIMIT_VMEM, &rl) < 0) {
         debugs(50, DBG_CRITICAL, "getrlimit: RLIMIT_VMEM: " << xstrerror());
     } else if (rl.rlim_max > rl.rlim_cur) {
@@ -1227,7 +1227,10 @@
         cap_value_t cap_list[10];
         cap_list[ncaps] = CAP_NET_BIND_SERVICE;
         ++ncaps;
-        if (Ip::Interceptor.TransparentActive() || Ip::Qos::TheConfig.isHitNfmarkActive() || Ip::Qos::TheConfig.isAclNfmarkActive()) {
+        if (Ip::Interceptor.TransparentActive() ||
+                Ip::Qos::TheConfig.isHitNfmarkActive() ||
+                Ip::Qos::TheConfig.isAclNfmarkActive() ||
+                Ip::Qos::TheConfig.isAclTosActive()) {
             cap_list[ncaps] = CAP_NET_ADMIN;
             ++ncaps;
         }
diff -u -r -N squid-3.5.1/test-suite/mem_hdr_test.cc squid-3.5.2/test-suite/mem_hdr_test.cc
--- squid-3.5.1/test-suite/mem_hdr_test.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/test-suite/mem_hdr_test.cc	2015-02-18 04:17:02.000000000 -0800
@@ -75,7 +75,7 @@
     assert (!aSplay.find(&ref13,mem_hdr::NodeCompare));
     ref13.nodeBuffer.length = 1;
     assert (aSplay.find(&ref13,mem_hdr::NodeCompare));
-    aSplay.destroy(SplayNode<mem_node *>::DefaultFree);
+    aSplay.destroy();
 }
 
 void
diff -u -r -N squid-3.5.1/test-suite/splay.cc squid-3.5.2/test-suite/splay.cc
--- squid-3.5.1/test-suite/splay.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/test-suite/splay.cc	2015-02-18 04:17:02.000000000 -0800
@@ -18,14 +18,7 @@
 #include <unistd.h>
 #endif
 
-#if 0
-#define assert(X) {if (!(X)) exit (1);}
 #include "splay.h"
-#undef assert
-#else
-#include "splay.h"
-#endif
-
 #include "util.h"
 
 class intnode
@@ -146,7 +139,10 @@
         for (i = 0; i < 100; ++i) {
             I = (intnode *)xcalloc(sizeof(intnode), 1);
             I->i = squid_random();
-            top = top->insert(I, compareintvoid);
+            if (top)
+                top = top->insert(I, compareintvoid);
+            else
+                top = new splayNode(static_cast<void*>(new intnode(101)));
         }
 
         SplayCheck::BeginWalk();
@@ -155,15 +151,12 @@
         SplayCheck::BeginWalk();
         top->walk(SplayCheck::WalkVoid, NULL);
         top->destroy(destintvoid);
-        /* check we don't segfault on NULL splay calls */
-        top = NULL;
-        top->splay((void *)NULL, compareintvoid);
     }
 
     /* test typesafe splay containers */
     {
         /* intnode* */
-        SplayNode<intnode *> *safeTop = NULL;
+        SplayNode<intnode *> *safeTop = new SplayNode<intnode *>(new intnode(101));
 
         for ( int i = 0; i < 100; ++i) {
             intnode *I;
@@ -176,13 +169,10 @@
         safeTop->walk(SplayCheck::WalkNode, NULL);
 
         safeTop->destroy(destint);
-        /* check we don't segfault on NULL splay calls */
-        safeTop = NULL;
-        safeTop->splay((intnode *)NULL, compareint);
     }
     {
         /* intnode */
-        SplayNode<intnode> *safeTop = NULL;
+        SplayNode<intnode> *safeTop = new SplayNode<intnode>(101);
 
         for (int i = 0; i < 100; ++i) {
             intnode I;
@@ -194,11 +184,6 @@
         safeTop->walk(SplayCheck::WalkNodeRef, NULL);
 
         safeTop->destroy(destintref);
-        /* check we don't segfault on NULL splay calls */
-        safeTop = NULL;
-        safeTop->splay(intnode(), compareintref);
-        SplayCheck::BeginWalk();
-        safeTop->walk(SplayCheck::WalkNodeRef, NULL);
     }
 
     /* check the check routine */
@@ -215,7 +200,7 @@
 
     {
         /* check for begin() */
-        SplayNode<intnode> *safeTop = NULL;
+        Splay<intnode> *safeTop = new Splay<intnode>();
 
         if (safeTop->start() != NULL)
             exit (1);
@@ -228,15 +213,15 @@
             I.i = squid_random();
 
             if (I.i > 50 && I.i < 10000000)
-                safeTop = safeTop->insert(I, compareintref);
+                safeTop->insert(I, compareintref);
         }
 
         {
             intnode I;
             I.i = 50;
-            safeTop = safeTop->insert (I, compareintref);
+            safeTop->insert (I, compareintref);
             I.i = 10000000;
-            safeTop = safeTop->insert (I, compareintref);
+            safeTop->insert (I, compareintref);
         }
 
         if (!safeTop->start())
@@ -280,6 +265,8 @@
             exit (1);
     }
 
+    /* TODO: also test the other Splay API */
+
     return 0;
 }
 
diff -u -r -N squid-3.5.1/tools/cachemgr.cc squid-3.5.2/tools/cachemgr.cc
--- squid-3.5.1/tools/cachemgr.cc	2015-01-13 04:52:01.000000000 -0800
+++ squid-3.5.2/tools/cachemgr.cc	2015-02-18 04:17:02.000000000 -0800
@@ -980,7 +980,7 @@
 
     cachemgr_request *req;
     char *s;
-    char *t;
+    char *t = NULL;
     char *q;
 
     if ((buf = read_post_request()) != NULL)
@@ -1005,6 +1005,7 @@
     req = (cachemgr_request *)xcalloc(1, sizeof(cachemgr_request));
 
     for (s = strtok(buf, "&"); s != NULL; s = strtok(NULL, "&")) {
+        safe_free(t);
         t = xstrdup(s);
 
         if ((q = strchr(t, '=')) == NULL)
@@ -1035,8 +1036,8 @@
             req->workers = xstrdup(q);
         else if (0 == strcmp(t, "processes") && strlen(q))
             req->processes = xstrdup(q);
-        safe_free(t);
     }
+    safe_free(t);
 
     if (req->server && !req->hostname) {
         char *p;
